Skip to main content

Endpoints

Everything is served from the public origin https://joyride.exchange, with no separate API host. The trading WebSocket speaks JSON-RPC 2.0. Every request carries "jsonrpc": "2.0", an id, a method, and optional params; every response echoes the id. Server pushes arrive as "method": "subscription" notifications with no id.

Authentication

Identity is an ed25519 keypair. There are no API keys. An account is provisioned against a Solana wallet public key (see the venue pages linked at the end), and that keypair signs in from a bot, the CLI, or the web app. Sign-in uses three methods on the trading WebSocket.

Request a nonce

Sign and authenticate

The message is built byte for byte as below: a blank line between the greeting and the Wallet: line, a single newline before Nonce:.
The signature is ed25519 over the UTF-8 bytes of that message, base58-encoded (64 bytes). The request carries the wallet, the signature, and the exact message signed. The server rebuilds the message from wallet and the nonce inside message and rejects any deviation, including a trailing newline or reordered lines.
roles lists what the account may do. A quoter’s array contains rfq_quoter; a taker’s is empty. A wallet with no provisioned account is rejected with 1001. Signing in never creates an account.

Resume on reconnect

A stored session_token authenticates a new socket without a fresh signature. Resume checks that the wallet still owns the account_id in the token and recomputes roles from live account state, so a role change takes effect on the next resume.
A 1001 on resume means the cached token is no longer valid; the full nonce, sign, auth sequence is required. public/session_resume on a socket already authenticated as the same account refreshes that session and evicts nothing.

Session token

The session token is the JWT that public/auth returns after the wallet signs the nonce. There is no revocation list, so a leaked token can trade the account until its exp. Joyride never holds a maker’s private key, so the remedy is on the maker’s side: generate a new keypair and email support@joyride.exchange to bind the account to the new public key. Once the account is rebound, tokens issued to the old key are refused on public/session_resume, and any connection still open under one ends when it disconnects.

Sessions per account

Every session receives every account-scoped push, so a bot needs one authenticated socket. A client closed with 4001 and reason session_limit must not reconnect automatically: the reconnect evicts the newer session and the two clients evict each other in a loop. Reconnect only on an operator action.

Keepalive

The server never pings. The client sends a protocol-level WebSocket ping at least every 30 seconds to keep intermediaries from dropping a quiet flow, and the gateway answers each with a pong. An unauthenticated socket that sends nothing for 60 seconds is reaped with error 1001.

Rate budget

The budget is per account, so three sessions share it. Each request counts as one, whether it is a poll, a response, or a decline.
The window resets at the next second. The rejected request was never admitted and can be resent as is.

Error codes

Errors use the JSON-RPC envelope { "code", "message", "data"? }. Close codes are WebSocket close frames, not JSON-RPC errors. The 1200 frame:
The standard JSON-RPC codes (-32700 parse, -32600 invalid request, -32601 method not found, -32602 invalid params, -32603 internal) follow the JSON-RPC 2.0 specification. An unknown instrument symbol in a request is rejected as -32602.

Support

Support for live makers is support@joyride.exchange. A report that includes the operation_id from a 1200 error, the rfq_id or quote_id in question, and the UTC time of the event can be traced directly. Next: Becoming an RFQ Quoter