Skip to content

API Reference

Machine-readable OpenAPI spec

The full API surface is published as an OpenAPI 3.1 document served directly by the gateway:

  • JSON (prod): https://oracle-api.parti.com/openapi.json
  • YAML (prod): https://oracle-api.parti.com/openapi.yaml
  • Staging: https://oracle-gateway.pbcapps.dev/openapi.json

These endpoints are public — no API key, no Origin negotiation — and refresh on every gateway deploy. Use them for:

  • Codegen: npx @openapitools/openapi-generator-cli generate -i https://oracle-gateway.pbcapps.dev/openapi.json -g typescript-fetch -o ./client
  • Postman / Insomnia: import the JSON URL directly
  • AI / agent tooling: point any OpenAPI-aware agent at the JSON URL and it gets the full route + schema set without scraping HTML

Quick sanity check:

curl -s https://oracle-gateway.pbcapps.dev/openapi.json | jq '.info.version, (.paths | length)'

If your sandbox can't reach the host, see Getting Started → Sandbox network access.


Authenticated write endpoints (EIP-712)

Writes are signed client-side: every action is an EIP-712 typed struct signed under the PartiVault domain with your EVM key, and the request carries the resulting 65-byte signature. There is no managed signer service — you hold your own key. Orders additionally require the session cookie from /v1/builders/register. See Authentication.

POST /v1/builders/register

Sign the EIP-712 SessionBootstrap{user,timestamp} struct. Issues the session cookie and returns a stable builder_api_key.

Request:

{
  "user": "0x7a3f…",
  "name": "my-bot",
  "signature": "0x<65-byte EIP-712 signature>",
  "timestamp": 1777500000
}

Response (also sets Set-Cookie: parti_oracle_session=…; HttpOnly):

{"api_key": "a1b2c3d4-…", "wallet": "0x7a3f…", "name": "my-bot"}

POST /v1/orders

Auth: session cookie + a 65-byte EIP-712 Order signature.

Submit a signed order. This is the primary trading endpoint.

Request:

{
  "market_id": "abc123def456...",
  "user": "0x7a3f…",
  "side": "buy",
  "outcome": "yes",
  "price": 6500,
  "size": 100,
  "order_type": "gtc",
  "signature": "0x<65-byte EIP-712 Order signature>",
  "nonce": 1777500000123,
  "builder_api_key": "a1b2c3d4-…"
}
Field Type Description
market_id string 64-char hex or slug (see Market IDs)
user string your lowercase 0x address
side "buy" or "sell"
outcome "yes" or "no"
price int 1-9999 basis points (5000 = $0.50)
size int Number of contracts
order_type string "gtc", "ioc", "fok", "post_only"
signature string 65-byte EIP-712 signature over the Order struct — required
nonce int per-user monotonic timestamp nonce
builder_api_key string optional fee attribution

Response:

{
  "order_id": 42,
  "market_id": "abc123...",
  "fills": [
    {
      "quantity": 50,
      "price": 6200,
      "taker_fee": 7,
      "maker_rebate": 0,
      "builder_fee": 31,
      "builder_api_key": "a1b2c3d4-…",
      "settlement_type": "mint",
      "outcome": "yes",
      "taker_side": "buy",
      "maker_side": "sell",
      "maker": "0x0000000000000000000000000000000000000000",
      "taker": "0x7a3f…",
      "maker_order_id": 10,
      "taker_order_id": 42,
      "timestamp": 1700000000
    }
  ],
  "remaining": 50
}

!!! note "Fill Field Naming" Live order fills returned by /v1/orders use quantity and timestamp. The historical /v1/trades/{user} and /v1/markets/{id}/trades REST endpoints return size and time instead. Client code should handle both forms when unifying data sources.

Market Orders

To place a "market" order (fill immediately at best available price), use ioc with an extreme price:

  • Market Buy: { "side": "buy", "price": 9999, "order_type": "ioc" } — fills at best asks
  • Market Sell: { "side": "sell", "price": 100, "order_type": "ioc" } — fills at best bids

The remaining field in the response indicates any unfilled portion (which is automatically cancelled for IOC orders).

The signed Order struct

The EIP-712 Order signature covers these fields, under the PartiVault domain ({ name: 'PartiVault', version: '1', chainId, verifyingContract }):

market    bytes32   market-id slot (see Market IDs below)
user      address   your 0x EVM wallet
outcome   uint8     (0 = yes, 1 = no)
side      uint8     (0 = buy, 1 = sell)
price     uint256   basis points (1..9999)
size      uint256   contracts
nonce     uint256   per-user monotonic timestamp nonce

chainId + verifyingContract must match the gateway's domain for the environment you point at, or the signature recovers to the wrong address and the gateway returns 403 invalid_signature.

POST /v1/orders/cancel and /v1/orders/cancel-all

Auth: session cookie only — no signature. There is no CancelAll EIP-712 struct; the engine resolves the acting user from the cookie and owner-checks each resting order.

// POST /v1/orders/cancel  — single order
{"market_id": "abc...", "order_id": 42, "user": "0x7a3f…"}

// POST /v1/orders/cancel-all  — optional market_id to scope to one market
{"user": "0x7a3f…", "market_id": "abc...", "builder_api_key": "a1b2c3d4-…"}

Carry the builder_api_key on cancel-all so the engine skips the short user-halt meant for the browser "Cancel All" button.

POST /v1/positions/redeem-sets

Auth: session cookie + a 65-byte EIP-712 RedeemSets{user,market,nonce} signature. Redeems matched YES+NO sets back to collateral.

POST /v1/withdraw-signed

Auth: a 65-byte EIP-712 Withdraw{user,recipient,amount,nonce,deadline} signature with chain:'robinhood'. The nonce is the sequential on-chain vault nonce (vault.nonces(user)), not the order timestamp nonce — see Deposits → Withdraw.

{
  "user": "0x7a3f…",
  "recipient": "0x7a3f…",
  "amount": "10000000",
  "nonce": 0,
  "deadline": 1799000000,
  "signature": "0x<65-byte EIP-712 Withdraw signature>",
  "chain": "robinhood"
}

Gateway Endpoints (Public, No Auth)

Read market data directly from the gateway. No API key needed.

GET /v1/markets

Every entry has event_id + outcomes[]. Binary = 1 outcome. Multi = N outcomes. Use market_id from outcomes when placing orders.

{
  "markets": [
    {
      "event_id": "abc123...",
      "question": "Will BTC reach $200k?",
      "category": {"name": "crypto", "sub": "bitcoin"},
      "status": "active",
      "fee_bps": 25,
      "expiry": 1798761600,
      "outcomes": [
        {"label": "Yes", "market_id": "def456...", "yes_price": 7200, "yes_bid": 7000, "yes_ask": 7400, "mark_bps": 7150}
      ]
    }
  ]
}

Each outcome carries a server-refreshed oracle fair value as mark_bps (de-vigged OpticOdds for sports, Pyth-implied for crypto) — the anchor market makers quote against.

GET /v1/events

List all events (multi-outcome markets grouped under one question).

GET /v1/events/{id}

Event details with per-outcome prices.

GET /v1/markets/{id}

Single market with full price data, including per-outcome mark_bps.

GET /v1/markets/{id}/book

Full order book snapshot (yes/no bids and asks).

GET /v1/markets/{id}/trades?limit=100&before=500

Trade history for a market. Cursor-paginated, newest first.

GET /v1/markets/{id}/candles?interval=5m&from=0&to=9999999999

OHLCV candlestick data. Intervals: 1m, 5m, 15m, 1h, 1d.

GET /v1/balance/{address}

User's balance (available, locked) in micro-USDG. {address} is the lowercase 0x address.

GET /v1/position/{market_id}/{address}

User's position in a market. The gateway returns { outcome, size, yes, no, avg_price }yes/no are the raw leg counts.

GET /v1/trades/{address}

User's trade history across all markets.

GET /v1/fees

Public fee schedule -- all categories, rates, and builder info.


Market IDs (hex vs slug)

Two encodings are accepted everywhere a market_id appears:

  • 64-char hex — used verbatim as the bytes32 market slot in the signed struct.
  • Slug string (e.g. oracle-btc-5m-1700000000-0) — the slot is SHA-256(utf8(market_id)).

Both resolve to the same bytes32 the gateway and engine use when verifying the signature.


Order Types

Type Behavior
gtc Good-til-cancelled. Rests unmatched portion on the book.
ioc Immediate-or-cancel. Fills what it can, cancels the rest.
fok Fill-or-kill. Must fill entirely or is rejected.
post_only Must rest as maker. Rejected if it would match immediately.

Price Format

All prices are in basis points (1-9999): - 5000 = $0.50 (50% probability) - 7500 = $0.75 (75% probability) - 100 = $0.01 (1% probability)

Balance Format

All balances in micro-USDG (6 decimals): - 1,000,000 = $1.00 - 10,000,000 = $10.00