Skip to content
FX-Port/Docs
GuidesAPI referenceChangelog
Get API keys
  • Introduction
  • Quickstart
  • Security
  • Authentication
  • Environments and Postman
  • Sandbox
  • Conventions and naming
  • Legacy names and twins
  • Errors
  • Rate limits and fair use
  • Streaming search results

Account and suppliers

  • Suppliers
  • Overview
  • List balances
  • Balance history
  • Booking history
  • Booking detail
  • Use these docs with AI

Account · Account and suppliers

Balance history

The complete financial ledger of one currency balance: top-ups, booking debits and refunds.

GET/api/v1/balances/{balance_id}/history

GET /api/v1/balances/{balance_id}/history

Permission: Read

The money movements recorded against one balance: top-ups, booking debits and refunds, newest first. Call GET /api/v1/balances first to get the balance_id of the currency you want.

Sandbox: the answer is always empty (pagination.total is 0) and meta says why. Live: a balance_id that is not a balance of your agency, or that is not a UUID, is answered 404 balance_not_found.

The source field

Each entry has a source:

sourceWhat it represents
"transactions"Authoritative balance movements. Recorded every time the balance changes: top-up, booking charge or refund. Use these for reconciliation totals. eSIM orders and topups have no audit source: their debits are transactions rows. Transfers have no audit source either
"flight_balance_operations"Per-booking flight audit records. Granular events of a booking (initial debit, exchange fee, adjustment, refund). One booking can produce several rows
"hotel_balance_operations"Per-booking hotel audit records. The same idea as the flight operations

A single action, for example confirming a flight, produces both a transactions row and a flight_balance_operations row, and both appear in this answer. Sum only the transactions rows for financial totals. The description of an eSIM debit is eSIM Order <order code> (a topup: eSIM TopUp <order code>), where the order code is the order_id of the booking.

Parameters

ParameterTypeDescription
balance_id (path)stringThe id of a balance from GET /api/v1/balances
date_fromstringInclusive start. Any ISO 8601 spelling is read: a date (2026-07-01 or 20260701, 00:00:00 UTC) or a datetime (2026-07-01T00:00:00Z) with 1 to 9 fraction digits and an offset written Z, +01:00 or +0100 (in a URL write the + as %2B). Without an offset a datetime is UTC
date_tostringInclusive end, in the same spellings. A bare date means the end of that day (23:59:59.999999 UTC). Not before date_from
typestringKeep one type. Exact and case sensitive: CREDIT, DEBIT or REFUND match transactions; credit, debit or refund match the two *_balance_operations sources. Up to 32 characters
pageintegerThe page, starting at 1 (at most 10,000). Default 1. An empty value means not sent
limitintegerEntries per page, 1 to 100. Default 20. A larger value is refused with 422 validation_error; an empty value means not sent

Legacy names (still work; the response carries a deprecated_field warning; date_from and date_to win when both are sent):

LegacyUse instead
from, from_datedate_from
to, to_datedate_to

Never send agency_id: an API key that does is refused with 400 agency_id_not_allowed. A value that is not an ISO 8601 date (01/10/2026, an epoch number, yesterday) is 400 invalid_date, and date_from after date_to is 400 invalid_date_range.

Movement types

TypeDirectionWhen it appears
CREDIT / creditFunds inManual top-ups, deposits returned when a hold is released
DEBIT / debitFunds outBooking confirmations, exchange fees, manual debit adjustments
REFUND / refundFunds inFull or partial refund after a booking is cancelled or voided

Upper case values appear in transactions rows and lower case values in *_balance_operations rows.

Request example

curl --get \
  --url https://api.fx-port.com/api/v1/balances/db002f7a-c136-4f32-b19d-38a2542f2af9/history \
  --header 'Authorization: Bearer fxp_test_YOUR_KEY' \
  --data-urlencode 'date_from=2026-10-01' \
  --data-urlencode 'date_to=2026-10-31' \
  --data-urlencode 'limit=50'
const balanceId = "db002f7a-c136-4f32-b19d-38a2542f2af9";
const params = new URLSearchParams({ date_from: "2026-10-01", date_to: "2026-10-31", limit: "50" });
const response = await fetch(`https://api.fx-port.com/api/v1/balances/${balanceId}/history?${params}`, {
  headers: { Authorization: "Bearer fxp_test_YOUR_KEY" },
});
const { data: entries, pagination } = await response.json();
// reconciliation: only the authoritative movements
const net = entries
  .filter((entry) => entry.source === "transactions")
  .reduce((sum, entry) => sum + (entry.type === "DEBIT" ? -entry.amount : entry.amount), 0);
import requests

balance_id = "db002f7a-c136-4f32-b19d-38a2542f2af9"
response = requests.get(
    f"https://api.fx-port.com/api/v1/balances/{balance_id}/history",
    params={"date_from": "2026-10-01", "date_to": "2026-10-31", "limit": 50},
    headers={"Authorization": "Bearer fxp_test_YOUR_KEY"},
    timeout=30,
)
body = response.json()

Response example

The amounts are examples. A live answer:

{
  "environment": "live",
  "success": true,
  "data": [
    {
      "source": "transactions",
      "id": "3e8b1c02-d7a4-4f5e-9b2a-1c0d8e7f3a91",
      "type": "CREDIT",
      "amount": 2500.0,
      "currency": "DZD",
      "description": "Balance top-up",
      "balanceId": "db002f7a-c136-4f32-b19d-38a2542f2af9",
      "balance_id": "db002f7a-c136-4f32-b19d-38a2542f2af9",
      "createdAt": "2026-10-11T09:15:00.000000+00:00",
      "created_at": "2026-10-11T09:15:00.000000+00:00"
    },
    {
      "source": "flight_balance_operations",
      "id": "658185df-234c-43ba-8175-ba9a5abe6007",
      "type": "debit",
      "amount": 87.5,
      "currency": "DZD",
      "description": "Exchange fee debit for flight booking Y7PAEU",
      "bookingRecordId": "711371c3-00aa-4be2-b790-9f0ca2ccfdb7",
      "booking_record_id": "711371c3-00aa-4be2-b790-9f0ca2ccfdb7",
      "createdAt": "2026-10-09T14:30:00.000000+00:00",
      "created_at": "2026-10-09T14:30:00.000000+00:00"
    },
    {
      "source": "transactions",
      "id": "31936df0-299d-429e-b0f5-056a6c0587cc",
      "type": "DEBIT",
      "amount": 4925.44,
      "currency": "DZD",
      "description": "Booking confirmation: flight Y7PAEU (ALG → ORN)",
      "balanceId": "db002f7a-c136-4f32-b19d-38a2542f2af9",
      "balance_id": "db002f7a-c136-4f32-b19d-38a2542f2af9",
      "createdAt": "2026-10-01T15:42:34.272792+00:00",
      "created_at": "2026-10-01T15:42:34.272792+00:00"
    }
  ],
  "pagination": { "page": 1, "limit": 20, "total": 3, "total_pages": 1, "hasMore": false, "has_more": false },
  "meta": {
    "agencyId": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
    "agency_id": "0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
    "balanceId": "db002f7a-c136-4f32-b19d-38a2542f2af9",
    "balance_id": "db002f7a-c136-4f32-b19d-38a2542f2af9",
    "balanceCurrency": "DZD",
    "balance_currency": "DZD",
    "environment": "live"
  }
}

Field reference

FieldPresent whenDescription
sourceAlwaysWhere the entry comes from: see the table above
idAlwaysThe entry UUID
typeAlwaysCREDIT, DEBIT or REFUND (upper case in transactions, lower case in operations)
amountAlwaysThe amount, always positive: type gives the direction
currencyAlwaysISO 4217 code: always the currency of the balance
descriptionAlwaysA label with the booking reference and the action. It can be null
balanceId / balance_idtransactions onlyThe balance the movement was recorded against
bookingRecordId / booking_record_idoperations onlyThe internal id of the booking: use it to match the entry with the booking history
createdAt / created_atAlwaysISO 8601 datetime, UTC
pagination.hasMore / has_moreAlwaystrue when another page can be served
meta.balanceId, meta.balanceCurrencyLiveThe balance of the history and its currency. Twins: balance_id, balance_currency

How far back the pages go

pagination.total is the real number of entries that match. The pages are built from the newest entries of each source (up to 500 per source), so the oldest entries of a long history cannot be reached by paging: follow has_more and narrow the list with date_from and date_to to read an older period.

Reconciliation tip. A single booking event produces both a transactions row and a flight_balance_operations row. To compute the net change of a balance, sum only the transactions rows. To trace one booking, match the bookingRecordId of the operation rows with the id of the booking in the history.

Errors

HTTPcodeCause
400agency_id_not_allowedAn API key sent agency_id
400invalid_date, invalid_date_rangeA date is not valid, or date_from is after date_to
401authentication_required, invalid_api_keyMissing or invalid API key
404balance_not_foundThe balance_id is not a balance of your agency (live), or is longer than 64 characters (any environment)
422validation_errorpage is below 1 or above 10,000, or limit is above 100
429rate_limit_exceededOver 6,000 requests per minute for this key
503service_overloadedThe service is shedding load for a moment (its database pool is full). Nothing was read: retry after the seconds in Retry-After (2 to 5)
PreviousList balancesNext Booking history

On this page

  • The source field
  • Parameters
  • Movement types
  • Request example
  • Response example
  • Field reference
  • How far back the pages go
  • Errors

© 2026 FX-Port

TermsPrivacy[email protected]