Foreign exchange: market-order trading, Request-for-Quote (RFQ), indicative rates, held rates, and trade/exposure lookups.
The three trade-execution shapes
Banking Circle's FX API has one execution endpoint
(POST /api/v2/fx/trading) but three ways to arrive at it:
- Market order —
trade/2with noquote_id: filled instantly at the prevailing market rate. - RFQ-then-trade —
request_quotes/2to get a firm, 30-second tradable quote, thentrade/2passing thatquote_id. Do not pass atenorwhen trading against a quote — it's derived from the quote itself. - Held-rate-then-trade —
request_quotes/2withrequest_type: :held_rate(orheld_rate/3for the simpler single-pair GET form) to lock a rate for up to 24 hours, thentrade/2against itsquote_id, any number of times within the held period and your daily limits.
request_quotes/2 accepts a list of quote requests and returns a
matching list of quotes — Banking Circle supports batching multiple
currency pairs (even across customer_ids) into one round trip, matched
back up via the caller-supplied quote_request_id on each entry.
Multi-entity note
If your Banking Circle setup spans multiple legal entities, customer_id
is required on every FX request and must match the entity that owns the
sell/debit account — fetch it from BankingCircle.Accounts (the
companyNumber field) if you don't already have it cached.
Summary
Functions
FX exposure for a specific customer/legal entity.
Looks up a single FX trade by your clientOrderId. Also matchable via
bankingCircleRef, which additionally shows up in the account
reconciliation report's PaymentDetails1 field for cross-referencing.
Requests a held rate for a currency pair via the simpler GET form
(GET /api/v1/fx/rates/held-rates/{ccy1}/{ccy2}), valid for
valid_for_minutes (up to 1440 / 24h).
Convenience wrapper around request_quotes/2 for a single indicative rate lookup.
Lists all currently active held rates for the client.
Paginated FX trade history, filterable (currency pair, date range, status, etc. — see API reference).
Requests one or more quotes in a single round trip. requests is a list
of maps, each requiring :quote_request_id, :customer_id,
:amount_currency, :amount, :tenor, :request_type, and either
:currency_pair or both :currency_one/:currency_two.
Available settlement dates for FX trades, accounting for holidays and cutoff times.
Executes an FX trade — market order if attrs has no :quote_id,
or against a previously-obtained quote (RFQ or held rate) if it does.
Same trade history as list_transactions/2 in CSV form, for bulk analysis/reporting.
Types
@type client() :: atom()
@type request_type() :: :indicative | :rfq | :payment_rfq | :held_rate
@type tenor() :: :on | :tn | :spot
Functions
@spec exposure(String.t(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
FX exposure for a specific customer/legal entity.
@spec get_transaction(String.t(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Looks up a single FX trade by your clientOrderId. Also matchable via
bankingCircleRef, which additionally shows up in the account
reconciliation report's PaymentDetails1 field for cross-referencing.
@spec held_rate(String.t(), String.t(), pos_integer(), keyword(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Requests a held rate for a currency pair via the simpler GET form
(GET /api/v1/fx/rates/held-rates/{ccy1}/{ccy2}), valid for
valid_for_minutes (up to 1440 / 24h).
@spec indicative_rate(map(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Convenience wrapper around request_quotes/2 for a single indicative rate lookup.
@spec list_held_rates( keyword(), client() ) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Lists all currently active held rates for the client.
@spec list_transactions( keyword(), client() ) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Paginated FX trade history, filterable (currency pair, date range, status, etc. — see API reference).
@spec request_quotes([map()], client()) :: {:ok, [map()]} | {:error, BankingCircle.Error.t()}
Requests one or more quotes in a single round trip. requests is a list
of maps, each requiring :quote_request_id, :customer_id,
:amount_currency, :amount, :tenor, :request_type, and either
:currency_pair or both :currency_one/:currency_two.
Returns {:ok, [quote, ...]} in the same order as the input, matched
via each entry's quoteRequestId.
@spec settlement_dates( keyword(), client() ) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Available settlement dates for FX trades, accounting for holidays and cutoff times.
@spec trade(map(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t() | {:missing_field, atom()}}
Executes an FX trade — market order if attrs has no :quote_id,
or against a previously-obtained quote (RFQ or held rate) if it does.
Required: :client_order_id, :buy_currency, :sell_currency,
:amount, :amount_currency. Either :tenor (market order) or
:quote_id (trading against a quote) — not both.
@spec transactions_csv( keyword(), client() ) :: {:ok, binary()} | {:error, BankingCircle.Error.t()}
Same trade history as list_transactions/2 in CSV form, for bulk analysis/reporting.