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-ratesis rejected with a403on the upgrade (see Errors & Limits); the indicative/v1/ratesfeed 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, callPOST /v1/otc-rates(the indicative basis isPOST /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 anunknown_symbolerror.
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 sellBASE, inQUOTEask— price to buyBASE, inQUOTE
Price precision
Every OTC pair is NGN-quoted, so prices are rounded to 2 decimal places (e.g. USD/NGN → 1683.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.