Skip to main content
curl --request POST \
  --url https://api.longshot.xyz/v1/rfq \
  --header 'Authorization: Bearer <session_token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "order": {
      "user": "0x742d35cC6634C0532925A3B844Bc9e7595F8B2A1",
      "wager_micros": 1000000,
      "min_odds": 1.01,
      "legs": [{ "market_id": 61619, "direction": "up" }],
      "nonce": 1234567890,
      "expires_at_ms": 1778013900000,
      "order_type": 2,
      "shield_on": false,
      "signature": "base64-encoded-65-byte-signature"
    }
  }'
{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "odds": 1.8519,
  "payout_micros": "1851900",
  "quotes_received": 1
}
curl --request POST \
  --url https://api.longshot.xyz/v1/rfq \
  --header 'Authorization: Bearer <session_token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "order": {
      "user": "0x742d35cC6634C0532925A3B844Bc9e7595F8B2A1",
      "wager_micros": 1000000,
      "min_odds": 1.01,
      "legs": [{ "market_id": 61619, "direction": "up" }],
      "nonce": 1234567890,
      "expires_at_ms": 1778013900000,
      "order_type": 2,
      "shield_on": false,
      "signature": "base64-encoded-65-byte-signature"
    }
  }'
{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "odds": 1.8519,
  "payout_micros": "1851900",
  "quotes_received": 1
}

Endpoint

POST https://api.longshot.xyz/v1/rfq
Authorization: Bearer <session_token>
Content-Type: application/json
Creates an RFQ from a signed order. The bearer session wallet and the order signature signer must be the same wallet. Submitting the same signed order again is idempotent. When the replay key is already persisted for the authenticated user, the API returns 200 with the same request_id and the current persisted RFQ status instead of starting a second execution.

Headers

Authorization
string
required
Bearer <session_token> from wallet auth or Privy session auth.

Body Parameters

order
object
required
Signed order payload.
order.user
string
required
Wallet address, with or without 0x.
order.wager_micros
int64
required
Wager size in USDC micros. 1000000 is 1 USDC.
order.min_odds
number
required
Minimum acceptable payout multiplier, for example 1.01.
order.legs
array
required
One to eight legs. Each leg contains market_id and direction.
order.legs[].market_id
int64
required
Longshot market ID from GET /v1/markets/current or GET /v1/markets/lookup for price legs or GET /v1/mention-markets for mention legs.
order.legs[].direction
string
required
up or down.
order.nonce
int64
required
Unique nonce for replay protection.
order.expires_at_ms
int64
required
Submission deadline in Unix milliseconds.
order.order_type
int32
1 for IOC or 2 for FOK. Defaults to FOK when omitted by compatible clients.
order.shield_on
boolean
required
If true, suppresses user tier and EVM address in market-maker-facing RFQs.
order.signature
string
required
Base64-encoded 65-byte ECDSA signature over the binary order bytes.

Binary Signing Format

The signature is over binary bytes, not JSON.
OffsetSizeFieldEncoding
020userraw address bytes
208wager_microsuint64 LE
284min_oddsuint32 LE, odds times 10000
328nonceuint64 LE
408expires_at_msuint64 LE
481order_typeuint8
491shield_on0 or 1
501leg_countuint8
51+9*Nlegsmarket_id uint64 LE, direction uint8
Direction is 0 for up and 1 for down. min_odds is submitted in JSON as a decimal multiplier, for example 1.01. The signed bytes use round(min_odds * 10000), so 1.01 is signed as the little-endian uint32 value 10100. Build the order, sign it with EIP-191 personal-sign, and encode the 65-byte signature as base64.

Runnable Examples

The examples below submit the current BTC 5m Up RFQ. Set LONGSHOT_API_BEARER to a bearer session for the same wallet that signs the order.
# pip install eth-account
import base64
import json
import os
import time
import urllib.request

from eth_account import Account
from eth_account.messages import encode_defunct


BASE_URL = "https://api.longshot.xyz"
PRIVATE_KEY = os.environ["LONGSHOT_WALLET_PRIVATE_KEY"]
BEARER = os.environ["LONGSHOT_API_BEARER"]


def request_json(method: str, path: str, body: dict = None, bearer: str = None) -> dict:
    data = None if body is None else json.dumps(body).encode()
    headers = {"accept": "application/json"}
    if body is not None:
        headers["content-type"] = "application/json"
    if bearer:
        headers["authorization"] = f"Bearer {bearer}"
    req = urllib.request.Request(BASE_URL + path, data=data, method=method, headers=headers)
    with urllib.request.urlopen(req, timeout=15) as res:
        raw = res.read().decode()
        return json.loads(raw) if raw else {}


def current_market_id(asset: str, duration_secs: int) -> int:
    path = f"/v1/markets/current?asset={asset}&duration_secs={duration_secs}"
    market = request_json("GET", path, bearer=BEARER)["market"]
    return int(market["market_id"])


def wait_for_terminal_rfq(rfq: dict) -> dict:
    for _ in range(10):
        if rfq.get("status") not in {"pending", "finalizing"}:
            return rfq
        time.sleep(0.5)
        rfq = request_json("GET", f"/v1/rfq/{rfq['request_id']}", bearer=BEARER)
    return rfq


def write_u64_le(buf: bytearray, offset: int, value: int) -> None:
    buf[offset:offset + 8] = int(value).to_bytes(8, "little")


def signing_bytes(order: dict) -> bytes:
    legs = order["legs"]
    buf = bytearray(51 + len(legs) * 9)
    user_hex = order["user"].removeprefix("0x")
    for i in range(20):
        buf[i] = int(user_hex[i * 2:i * 2 + 2], 16)
    write_u64_le(buf, 20, order["wager_micros"])
    buf[28:32] = round(order["min_odds"] * 10_000).to_bytes(4, "little")
    write_u64_le(buf, 32, order["nonce"])
    write_u64_le(buf, 40, order["expires_at_ms"])
    buf[48] = order["order_type"]
    buf[49] = 1 if order["shield_on"] else 0
    buf[50] = len(legs)
    for i, leg in enumerate(legs):
        offset = 51 + i * 9
        write_u64_le(buf, offset, leg["market_id"])
        buf[offset + 8] = 0 if leg["direction"] == "up" else 1
    return bytes(buf)


account = Account.from_key(PRIVATE_KEY)
order = {
    "user": account.address,
    "wager_micros": 1_000_000,
    "min_odds": 1.01,
    "legs": [{"market_id": current_market_id("BTC", 300), "direction": "up"}],
    "nonce": int.from_bytes(os.urandom(6), "big"),
    "expires_at_ms": int(time.time() * 1000) + 60_000,
    "order_type": 2,
    "shield_on": False,
}
signed = Account.sign_message(encode_defunct(primitive=signing_bytes(order)), PRIVATE_KEY)
order["signature"] = base64.b64encode(signed.signature).decode()

rfq = request_json("POST", "/v1/rfq", {"order": order}, bearer=BEARER)
rfq = wait_for_terminal_rfq(rfq)
print(rfq)

Response Fields

request_id
uuid
RFQ request ID for status lookup and cancellation.
status
string
pending, finalizing, completed, failed, cancelled, or timeout.
odds
number | null
Effective payout multiplier when the RFQ fills.
payout_micros
string | null
Gross payout in micros if the filled position wins, encoded as a decimal integer string.
error
string | null
Failure reason when status is failed.
quotes_received
int32
Number of maker quotes received for the RFQ.