BankingCircle.FX (banking_circle v1.0.0)

Copy Markdown View Source

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:

  1. Market ordertrade/2 with no quote_id: filled instantly at the prevailing market rate.
  2. RFQ-then-traderequest_quotes/2 to get a firm, 30-second tradable quote, then trade/2 passing that quote_id. Do not pass a tenor when trading against a quote — it's derived from the quote itself.
  3. Held-rate-then-traderequest_quotes/2 with request_type: :held_rate (or held_rate/3 for the simpler single-pair GET form) to lock a rate for up to 24 hours, then trade/2 against its quote_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

client()

@type client() :: atom()

request_type()

@type request_type() :: :indicative | :rfq | :payment_rfq | :held_rate

tenor()

@type tenor() :: :on | :tn | :spot

Functions

exposure(customer_id, client \\ :default)

@spec exposure(String.t(), client()) ::
  {:ok, map()} | {:error, BankingCircle.Error.t()}

FX exposure for a specific customer/legal entity.

get_transaction(client_order_id, client \\ :default)

@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.

held_rate(currency_one, currency_two, valid_for_minutes, opts \\ [], client \\ :default)

@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).

indicative_rate(attrs, client \\ :default)

@spec indicative_rate(map(), client()) ::
  {:ok, map()} | {:error, BankingCircle.Error.t()}

Convenience wrapper around request_quotes/2 for a single indicative rate lookup.

list_held_rates(filters \\ [], client \\ :default)

@spec list_held_rates(
  keyword(),
  client()
) :: {:ok, map()} | {:error, BankingCircle.Error.t()}

Lists all currently active held rates for the client.

list_transactions(filters \\ [], client \\ :default)

@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).

request_quotes(requests, client \\ :default)

@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.

settlement_dates(filters \\ [], client \\ :default)

@spec settlement_dates(
  keyword(),
  client()
) :: {:ok, map()} | {:error, BankingCircle.Error.t()}

Available settlement dates for FX trades, accounting for holidays and cutoff times.

trade(attrs, client \\ :default)

@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.

transactions_csv(filters \\ [], client \\ :default)

@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.