Connect
Register a pricer before you connect
We refuse the upgrade if your trader has no pricer registration. Register once withPOST /rfq/pricer and the body {}. A socket-only pricer needs no webhook and gets no shared secret.
The registration outlives every connection, so you don’t register again when you reconnect.
See Registration.
Why the upgrade fails
We check your token and your registration before the upgrade. A failure comes back as a plain HTTP status.Channels
A channel is a stream of events you subscribe to. There are two.rfq events to every pricer. We send quotes events only to you.
How a round works
We open a round
rfq_created arrives on rfq with the legs, the minimum stake, and the deadline.You answer
create_quote before expires_at, or send decline to pass.The auction closes
rfq_closed arrives. Stop pricing that round.You confirm a win
quote_accepted arrives on quotes. Send confirm within 1 second.The trade fills or doesn't
quote_executed or quote_unfilled arrives on quotes.Message format
Every message is a JSON text frame with two keys:event names the message, and data holds its payload.
We answer every message you send with one ack or one error.
Every frame we send also carries timestamp, the time we emitted it.
Other times are named fields in data. For example, expires_at is when the auction closes, and executed_at is when the trade filled.
We send decimal amounts like price, max_wager, and wager as JSON strings. Send yours as strings too.
Messages you send
subscribe
Start getting a channel's events
subscribe
Start getting a channel's events
data is the channel name as a string, not an object. We ack with subscribed."rfq" or "quotes".unsubscribe
Stop getting a channel's events
unsubscribe
Stop getting a channel's events
create_quote
Quote an open round
create_quote
Quote an open round
quote_submitted.rfq_created."0.45" means a $0.45 stake per $1.00 payout. We round it to the nearest 0.001.external_flag. Leave it out if you don’t need one.rfq_id and ack it with quote_superseded.
To change your price, wait for the next round.decline
Pass on an open round
decline
Pass on an open round
quote_declined.rfq_created.confirm
Answer the last look on a quote you won
confirm
Answer the last look on a quote you won
confirm_recorded.quote_accepted.quote_accepted. It’s not the quote_id you sent on create_quote.true fills the trade at your quoted price. false rejects it.CONFIRM_ALREADY_DECIDED, or NO_CONFIRM_WINDOW once the window has closed.Events we send
You get a channel’s events after you subscribe to it.rfq_created
A round opened (rfq channel)
rfq_created
A round opened (rfq channel)
expires_at."rfq_created".GET /rfq/executions sorts the same legs by outcome ID. See Universe model.max_wager is below it, with reason below_min_wager.rfq_closed
The auction closed (rfq channel)
rfq_closed
The auction closed (rfq channel)
rfq_executed
A trade filled, with no counterparty named (rfq channel)
rfq_executed
A trade filled, with no counterparty named (rfq channel)
quote_created
We recorded your quote (quotes channel)
quote_created
We recorded your quote (quotes channel)
quote_accepted
You won. Confirm within 1 second (quotes channel)
quote_accepted
You won. Confirm within 1 second (quotes channel)
confirm."quote_accepted".confirm.max_wager you quoted.quote_id you sent on create_quote, or null if you sent none.quote_executed
Your quote filled (quotes channel)
quote_executed
Your quote filled (quotes channel)
rfq_executed leaves out."quote_executed".quote_unfilled
Your confirmed quote won't fill (quotes channel)
quote_unfilled
Your confirmed quote won't fill (quotes channel)
quote_executed or quote_unfilled."quote_unfilled".quote_dropped
We dropped your quote for a reason you can fix (quotes channel)
quote_dropped
We dropped your quote for a reason you can fix (quotes channel)
"quote_dropped".below_min_wager, unbacked, or own_rfq. The first two add one field with the number you must beat.Acks
An ack confirms that we handled your message.subscribed
The subscription is active
subscribed
The subscription is active
unsubscribed
The subscription is removed
unsubscribed
The subscription is removed
quote_submitted
Your quote entered the auction
quote_submitted
Your quote entered the auction
quote_superseded
Your first quote stands. We dropped this one
quote_superseded
Your first quote stands. We dropped this one
quote_declined
We recorded your pass
quote_declined
We recorded your pass
Errors
We answer a message we can’t handle with anerror frame.
error
Your message failed
error
Your message failed
"error".message.create_quote, decline, or confirm gets FORBIDDEN.
Timing and limits
create_quote and decline. confirm is exempt from the rate limit.
We drop only event frames when your queue is full. We never drop acks or errors.
Keep the connection alive
We send a WebSocket Ping every 15 s. Answer with a Pong. Most clients do this for you. If no Pong arrives before our next Ping, we close the connection. There’s no JSON ping message and no idle timeout. A connection that answers every Ping stays open.Reconnect
We don’t replay or backfill. A new connection starts at the live edge, so you lose anything we sent while you were away. Get missed executions from the executions listing. We close a connection without a status code, so don’t read meaning into the close frame. Reconnect with backoff, then subscribe again. If you read too slowly, we drop event frames instead of waiting for you. Read promptly, or you’ll miss quote rounds.Use webhooks and the socket together
A webhook and the socket are independent. You can register awebhookUrl, connect the socket, or do both.
quote_superseded.
A round your webhook won is confirmed over HTTP. A round your socket won arrives as quote_accepted.
Handle confirms on both legs, or run only one.
To make the socket your only path, leave out webhookUrl on your first registration.
On an existing registration, leaving it out keeps your webhook. See Registration.
