relayerUrl in your config; the shared testnet relayer is https://sparrow-relayer.dennis-furrer.workers.dev.
Conventions:
- All amounts are raw USDC strings (6 decimals); all odds and probabilities are basis points.
- Errors are
{"error": string}with an optional machinecode; the client surfaceserroras the thrown message. - POST endpoints are rate limited per IP (default 60/min, HTTP 429) and return 503
{"error": "relayer paused"}while the admin kill switch is on.
POST /quote
Prices a leg set from live Hyperliquid mids, runs the correlation engine and risk limits, builds theParlayOrder with the vault as maker, and signs the maker side. The client sends only which legs, never odds.
Request
1 to 10 legs (relayer
MAX_LEGS), each {marketId, outcome} with outcome 0 or 1.Raw USDC. Defaults: min
"1000000" (1 USDC), max "5000000000" (5,000 USDC).Taker wallet address.
Optional; a random 248-bit nonce is generated when omitted.
deadline is 600 seconds out. margin is null under isolated accounting; see Margin for the cross-mode shape.
Errors
| Status | Body | Meaning |
|---|---|---|
| 400 | {"error": "..."} | Malformed request (bad legs, stake, or address) |
| 422 | {"error": "...", "code": "mutually_exclusive"} | Legs are outcomes of the same HL question; can never win |
| 422 | {"error": "...", "code": "duplicate_leg"} | Same market twice |
| 422 | {"error": "no live price for market 101"} | Leg has no HL mid right now |
| 422 | {"error": "...", "code": "<risk code>", "marketId": 101} | Risk limit hit: stake bounds, max odds, vault utilization, per-market exposure cap |
| 502 | {"error": "could not fetch HL prices"} | Hyperliquid unreachable |
| 502 | {"error": "could not read vault capacity"} | RPC failure reading the vault |
POST /submit
Relays the co-signed order on-chain: simulatesParlayEscrow.submitParlay, then sends it from the relayer’s key (gasless for both signers).
Request
| Status | Body | Meaning |
|---|---|---|
| 400 | {"error": "malformed order"} | Order does not deserialize |
| 422 | {"error": "<revert reason>"} | On-chain revert: expired deadline, used nonce, bad signature, insufficient allowance or balance |
| 503 | {"error": "submission temporarily unavailable"} | RPC or network failure (retryable) |
POST /cashout
Quotes and signs a buy-back to close a live parlay early. Prices the remaining legs from live HL mids through the same correlation engine, then applies the buy-back spread (default 300 bps). Execution is the taker’s own transaction:ParlayEscrow.cashOut with the returned signature.
Request
deadline is 120 seconds out. cashValue = pot * jointProb * (1 - spread), clamped to the escrowed total.
Errors
| Status | Body |
|---|---|
| 400 | {"error": "bad request"} |
| 403 | {"error": "not your parlay"} |
| 404 | {"error": "unknown parlay"} |
| 409 | {"error": "already settled"} |
| 422 | {"error": "no live price for market 101"} |
| 502 | {"error": "could not read parlay"} or {"error": "could not fetch HL prices"} |
GET /margin
Public margin-engine transparency: the live accounting mode plus the isolated-vs-cross comparison. Works even while the relayer is paused. Append?detail=1 for the per-position book and netting clusters.
Response 200
?detail=1, two extra fields:
{"error": "could not compute margin state"}, 503 when the escrow is unconfigured.
GET /health
Relayer readiness. Also works while paused. Returns HTTP 200 whenok, 503 otherwise, always with the same body shape:
Response
Configured, RPC and HL reachable, a quoter authorized on the vault, and not paused.
Admin kill switch. POST endpoints return 503 while true.
Whether any configured quoter key is authorized on the vault;
null when the check could not run.Individual probes:
configured, rpc, hl, vault.Deployment flags that shape responses
Set in the relayer’swrangler.toml (defaults shown); useful when running your own stack:
| Flag | Default | Effect |
|---|---|---|
HL_TESTNET | "false" | Price from HL testnet instead of mainnet HIP-4 |
PROTOCOL_FEE_BPS / BUILDER_FEE_BPS | 100 / 25 | Fees taken from the stake |
SPREAD_BPS | 200 | Vault edge on odds |
CASHOUT_SPREAD_BPS | 300 | Buy-back spread on cash-outs |
MIN_STAKE / MAX_STAKE | 1 / 5,000 USDC | Stake bounds |
MAX_LEGS | 10 | Max legs per parlay |
MAX_ODDS_BPS | 10000000 (1000x) | Max combined odds |
MAX_UTILIZATION_BPS | 8000 | Vault utilization cap for quoting |
MAX_MARKET_EXPOSURE_BPS | 3000 | Per-market share of NAV across the book |
MARGIN_MODE / CREDIT_HAIRCUT_BPS | isolated / 2000 | Cross-margin toggle and haircut |
RATE_LIMIT_PER_MIN | 60 | Per-IP POST rate limit |

