Price channel
Subscribing to a two-way price stream, reading a quote, and unsubscribing.
Prices are streamed, not polled. You subscribe for a specific size of a specific pair at a specific tenor, and the gateway pushes a two-way quote for that size until you unsubscribe or it stops streaming.
The size matters: a subscription is priced for the quantity you asked for, so
1 BTC and 10 BTC are separate subscriptions with separate quotes. Asking for
a size no available price band covers is rejected outright rather than answered
with an approximate price.
Every price update carries a fresh quoteId. That is the token you place an
order with — see order sessions and recovery.
Updates arrive roughly twice a second per subscription, and each one
supersedes the last, so hold the most recent and re-read rather than caching.
Subscriptions do not survive a reconnect. They are bound to the connection,
not to your session, and the gateway drops all of them when the socket closes.
Re-subscribe after every reconnect, even under the same sessionId — unlike a
subscribed order, nothing is replayed for you.
Subscribe request
Sent as messageType: "subscribe". Answered by exactly one subscribe response.
beneficiaryDetails and senderDetails cannot both be sent. A request
carrying both is rejected, and because a top-level beneficiaryId is converted
into beneficiaryDetails first, sending beneficiaryId alongside
senderDetails is rejected on the same grounds.
| Field | Type | Required | Notes |
|---|---|---|---|
messageType | string | Required | Always subscribe on this message. It is how the gateway picks the message type |
instrument | string | Required | The pair, as TRADED.SETTLEMENT — for example BTC.USD. Rejected if blank, or if it is not exactly two parts separated by a dot |
tag | string | Your own label for this subscription, echoed on the subscribe response and on every price update. Never validated — use it to route updates when you hold several subscriptions on one connection | |
quantity | string | Required | The size you want priced, as a decimal string. Must parse as a number and be greater than zero. It is part of what identifies the subscription |
currency | string | Required | Which side of the pair quantity is expressed in. Must be one of the two currencies in instrument |
accountGrpUuid | string | Conditional | The account group to price for. Sending it blank is rejected, and it becomes required when you supply beneficiaryDetails |
tenor | string | Required | The settlement tenor. Rejected only if blank — the gateway does not check the value, so an unrecognised tenor is accepted here and then fails to match any price. See the tenors below |
beneficiaryId | string | The flat form of a beneficiary subscription: the beneficiary and its network sent at this level instead of in a beneficiaryDetails block. Send it and the gateway builds beneficiaryDetails from these two fields, discarding anything you sent in that field. There is no flat form for a sender | |
networkId | string | Conditional | The delivery network, sent here rather than inside beneficiaryDetails. Read only alongside a top-level beneficiaryId, and required there, because the flat form carries no payoutCurrency |
beneficiaryDetails | BeneficiaryDetails | Third-party delivery destination, for a trade settling to a party other than you. Mutually exclusive with senderDetails | |
senderDetails | SenderDetails | Third-party collection source, for a trade funded by a party other than you. Mutually exclusive with beneficiaryDetails | |
chanId | string | Set by the gateway to your connection identifier. Anything you send is discarded | |
authUserUUID | string | Set by the gateway from your credential. Anything you send is discarded |
BeneficiaryDetails
Supply at least one of networkId and payoutCurrency; a beneficiary block
with neither is rejected. Requires accountGrpUuid on the request.
| Field | Type | Required | Notes |
|---|---|---|---|
beneficiaryId | string | Required | The beneficiary to deliver to, from your settlement parties. Omit it and no beneficiary is resolved — you are priced for your own settlement rather than told anything is wrong |
networkId | string | Conditional | The delivery network. Left empty for a crypto payout, your default transfer network is used. If you do supply one for a fiat payout it must agree with the network resolved for that beneficiary, or the request is rejected |
payoutCurrency | string | Conditional | The currency the beneficiary is paid in, when that is what determines the network rather than an explicit networkId |
SenderDetails
| Field | Type | Required | Notes |
|---|---|---|---|
senderId | string | Required | The registered sender funding the trade, from your settlement parties. Omit it and no sender is resolved — you are priced for your own funding rather than told anything is wrong |
networkId | string | The collection network. Left empty, your default sender network is used. It must be a sender-type network, or the request is rejected | |
payinCurrency | string | The currency the sender delivers in. Must be a digital asset |
Subscribe response
Sent as messageType: "subscribe", once per subscribe request, whether it
succeeded or not.
Read success — a subscriptionId is present either way. The gateway
allocates the identifier before it validates, so its presence tells you nothing
about whether you are subscribed.
| Field | Type | Notes |
|---|---|---|
messageType | string | Always subscribe |
success | boolean | Whether you are now subscribed. The only reliable signal on this message |
message | string | Human-readable detail accompanying code |
subscriptionId | string | The identifier for this subscription, and what you unsubscribe with. Allocated by the gateway on every request, including one that failed |
tag | string | Your own label, echoed back |
instrument | string | The pair subscribed to |
quantity | string | The size subscribed for |
code | string | Set when success is false; see trade error codes |
tenor | string | The settlement tenor subscribed to |
settleDate | string | The settlement date resolved for that tenor |
networkId | string | The network the gateway resolved for a third-party trade, which may differ from the one you asked for. Absent when neither beneficiary nor sender details were supplied |
chanId | string | The connection the message was delivered on |
timestamp | integer | When the gateway produced this message, in milliseconds |
Price update
Sent as messageType: "pricestream", roughly every 500 ms per live
subscription for as long as a tradeable price exists.
Each update replaces the previous one. quoteId changes on every message,
and only a recent one is accepted on an order.
Price updates are delivered on a lossy channel: a client that reads slower than the stream produces silently misses ticks rather than falling behind. You will not be told, and nothing is replayed. Treat every update as the current price, not as one of a complete sequence.
| Field | Type | Notes |
|---|---|---|
instrument | string | The pair being priced |
tenor | string | The settlement tenor |
messageType | string | Always pricestream |
quoteId | string | The token you place an order against. It carries the whole quote — price, size, tenor, settlement date and who it was issued to — so it is long, opaque and not a handle you can look up. It is yours alone: an order placed with someone else's is rejected |
tag | string | Your own label from the subscribe request, echoed on every update. Use it to match an update to a subscription when you hold several |
offer | QuoteSide | The price you buy the traded currency at |
bid | QuoteSide | The price you sell the traded currency at |
settleDate | string | The settlement date this price settles on |
chanId | string | The connection the message was delivered on |
timestamp | integer | When the gateway produced this message, in milliseconds |
QuoteSide
One side of the two-way price, carried on offer and on bid.
| Field | Type | Notes |
|---|---|---|
price | string | The rate, in settlement currency per unit of the traded currency |
quantity | string | The size this rate is good for, which is the size you subscribed at |
quoteAmount | string | The other side of the same trade — what quantity at price comes to in the opposite currency |
Unsubscribe request
Sent as messageType: "unsubscribe". Stops the stream for one subscription.
An unknown subscriptionId is answered with silence. There is no error
frame for one that does not exist or belongs to another connection — you simply
receive no response. Do not block waiting for one.
| Field | Type | Required | Notes |
|---|---|---|---|
messageType | string | Required | Always unsubscribe on this message |
subscriptionId | string | Required | The subscription to stop, from the subscribe response. It must be one of yours on this connection |
chanId | string | Set by the gateway to your connection identifier. Anything you send is discarded | |
authUserUUID | string | Set by the gateway from your credential. Anything you send is discarded |
Unsubscribe response
Sent as messageType: "unsubscribe", and only when the subscription was found.
| Field | Type | Notes |
|---|---|---|
messageType | string | Always unsubscribe |
success | boolean | Always true on this message. A failed unsubscribe produces no message at all |
subscriptionId | string | The subscription that was stopped |
message | string | Human-readable detail |
instrument | string | The pair that was being priced |
quantity | string | The size that was being priced |
tenor | string | The settlement tenor that was being priced |
chanId | string | The connection the message was delivered on |
timestamp | integer | When the gateway produced this message, in milliseconds |
Stream stop
Sent as messageType: "streamStop" when a live subscription has no tradeable
price. It means "nothing to quote right now", not "your subscription is gone".
The subscription stays live and this message repeats. It is re-sent on every
broadcast tick for as long as the condition holds, so deduplicate on
subscriptionId rather than treating each one as a new event. If the condition
clears, prices resume on the same subscription with no action from you. If it
does not, the stream simply goes quiet.
| Field | Type | Notes |
|---|---|---|
messageType | string | Always streamStop |
tag | string | Your own label from the subscribe request |
code | string | Why the stream stopped; see the reasons below |
message | string | Human-readable detail. It is deliberately the same wording for every reason — read code, not this |
instrument | string | The pair that has stopped streaming |
tenor | string | The settlement tenor that has stopped streaming |
chanId | string | The connection the message was delivered on |
timestamp | integer | When the gateway produced this message, in milliseconds |
StreamStopReason
| Value | Meaning |
|---|---|
CUT_OFF_TIME_REACHED | The cut-off for same-day settlement has passed, so this tenor can no longer be traded today. Applies to TOD. Subscribe at a later tenor, or at T, which rolls to the next available one on your behalf |
VENUE_DISABLED | The venue behind the price is not trading. Handle it exactly as STREAM_UNAVAILABLE — the gateway reports venue unavailability under that reason |
STREAM_UNAVAILABLE | No tradeable price is available for this subscription. Either the instrument is not enabled for your account, or the liquidity behind it is not trading. If it does not clear, contact your desk |
Tenors
The gateway accepts any non-blank tenor and does not check the value, so a
tenor that is merely misspelled is not rejected at subscribe. It fails later, as
a price-level error, because nothing in the stream matches it. If a
subscription is refused for a size you believe is available, check the tenor
first.
TOD— today. Unavailable after the daily cut-off, which is when you receiveCUT_OFF_TIME_REACHED.TOM— the next business day.SP— spot.T— the nearest tenor still available:TODbefore the cut-off, otherwiseTOMorSP. Use this to avoid handling the cut-off yourself.T1— the next tenor afterT.
settleDate is resolved by us from the tenor and returned on the subscribe
response and every price update. You cannot request a settlement date directly.