OTC Rates Streaming

/v1/otc-rates is a second WebSocket feed that streams OTC bid/ask prices for NGN-quoted pairs. It uses the same connection, authentication, subscription, and error protocol as the indicative /v1/rates feed — only the URL, the available pairs, and the pricing basis differ.

Available on request. The OTC feed is not enabled by default. Contact your account manager to have it enabled for your API key. Until it is enabled, connecting to /v1/otc-rates is rejected with a 403 on the upgrade (see Errors & Limits); the indicative /v1/rates feed is unaffected.

Market data only. Like /v1/rates, this feed does not execute conversions. To lock in an executable rate on the OTC basis for a specific amount, call POST /v1/otc-rates (the indicative basis is POST /v1/quotes).

How it differs from /v1/rates

/v1/rates (indicative) /v1/otc-rates (OTC)
URL wss://api.esca.finance/v1/rates wss://api.esca.finance/v1/otc-rates
Rate basis Indicative market rate Esca's OTC rate for the NGN leg, combined with the live market rate for any crypto cross leg
Pairs Fiat/fiat, crypto/crypto, crypto/fiat, NGN-quoted NGN-quoted only — a subset of the indicative pairs, priced on the OTC basis
Per-account pricing Applied to crypto/FX pairs (NGN pairs are uniform) Uniform — every account sees the same price

Everything else — the welcome frame, heartbeats, subscribe/unsubscribe, snapshot/update frames, error codes, rate limits, and reconnection — is identical. See Connecting, Subscribing, and Errors & Limits.

Connection URL

wss://api.esca.finance/v1/otc-rates

WSS (TLS) only. Authenticate with the X-Api-Key header on the upgrade, exactly as for /v1/rates — see Connecting. Connection limits are shared with /v1/rates (the concurrent-connection cap is per account, across both feeds).

Supported pairs

Use these exact symbols (BASE/QUOTE). All OTC pairs are NGN-quoted.

Quote Pairs
NGN USD/NGN, GBP/NGN, EUR/NGN, USDT/NGN, USDC/NGN, BTC/NGN

These pairs also exist on /v1/rates, but are priced differently there (indicative vs OTC). Subscribing to any other symbol returns an unknown_symbol error.

Pricing

OTC bid/ask are uniform across accounts — no per-account markup is applied. The price reflects Esca's OTC rate for the NGN leg combined with the live market rate for any crypto cross leg (e.g. for BTC/NGN).

  • bid — price to sell BASE, in QUOTE
  • ask — price to buy BASE, in QUOTE

Price precision

Every OTC pair is NGN-quoted, so prices are rounded to 2 decimal places (e.g. USD/NGN1683.42).

Update cadence

Same as /v1/rates: prices are re-checked on a roughly 10-second cycle, and an update is pushed whenever a pair's bid/ask changes — not on a fixed interval. Pairs with a crypto cross leg move as the market ticks; the NGN leg moves with Esca's OTC rate.

Example (Node, ws)

const WebSocket = require('ws');

const ws = new WebSocket('wss://api.esca.finance/v1/otc-rates', {
  headers: { 'X-Api-Key': process.env.ESCA_API_KEY },
});

ws.on('open', () => {
  ws.send(JSON.stringify({
    method: 'subscribe',
    params: { channel: 'ticker', symbol: ['USD/NGN', 'BTC/NGN'], snapshot: true },
    req_id: 1,
  }));
});

ws.on('message', (raw) => {
  const msg = JSON.parse(raw.toString());
  if (msg.type === 'ping') ws.send(JSON.stringify({ type: 'pong' }));
  // handle welcome / subscribe ack / snapshot / update ...
});

The frame shapes (welcome, subscribe ack, snapshot, update, ping) are identical to the indicative feed — see Subscribing.