Skip to content

Builder Integration Guide

Build prediction market interfaces on top of the Oracle platform. Third-party frontends ("builders") can embed markets, route orders, and earn creator fees.

Architecture

Your Frontend  -->  Oracle Signer  -->  Oracle Gateway  -->  Engine
                         |
                    Signs orders          REST API        Matching
                    Manages keys
                         |
                    Oracle Deposit  -->  Proxy Wallet  -->  Vault
                         |
                    Deposit addresses    USDC custody     Settlement

The Oracle Signer is a signing server that handles Ed25519 key management so your frontend never touches private keys.

Quick Start

1. Get an API Key

curl -X POST ${SIGNER_URL}/v1/admin/builders \
  -H "X-Admin-Key: ${ADMIN_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Trading App"}'

Response:

{"api_key": "bld_a1b2c3d4e5f6...", "name": "My Trading App"}

2. Create a User Key

When a user registers on your platform, create a delegated signing keypair:

curl -X POST ${SIGNER_URL}/v1/keys \
  -H "X-Api-Key: bld_a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{"user_id": "user-123"}'

Response:

{"user_id": "user-123", "public_key": "7yQ3mH9a..."}

The public_key is the user's trading address. Store the mapping user_id <-> public_key in your database.

3. Fund the User

Get a deposit address for the user's keypair:

curl -X POST ${SIGNER_URL}/v1/deposit/address \
  -H "X-Api-Key: bld_a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{"user": "7yQ3mH9a...", "chain": "solana"}'

Response includes the USDC deposit address. Have users send USDC there.

4. Place Orders

Submit orders through the signer — it signs and forwards to the gateway:

curl -X POST ${SIGNER_URL}/v1/submit \
  -H "X-Api-Key: bld_a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{
    "user": "7yQ3mH9a...",
    "market_id": "abc123...",
    "side": "buy",
    "outcome": "yes",
    "price": 6500,
    "size": 100,
    "order_type": "gtc",
    "nonce": 1
  }'

The signer handles the Ed25519 signature. The response is the same as POST /v1/orders on the gateway.

5. Read Market Data

Query the gateway directly — no API key needed for read endpoints:

# All markets with prices
curl ${GATEWAY_URL}/v1/markets

# All events (multi-outcome groups)
curl ${GATEWAY_URL}/v1/events

# Order book
curl ${GATEWAY_URL}/v1/markets/${MARKET_ID}/book

# Trade history
curl ${GATEWAY_URL}/v1/markets/${MARKET_ID}/trades?limit=50

# Candles
curl ${GATEWAY_URL}/v1/markets/${MARKET_ID}/candles?interval=5m

# User balance
curl ${GATEWAY_URL}/v1/balance/${PUBLIC_KEY}

# User position
curl ${GATEWAY_URL}/v1/position/${MARKET_ID}/${PUBLIC_KEY}

# User trade history
curl ${GATEWAY_URL}/v1/trades/${PUBLIC_KEY}

Signer API Reference

All builder endpoints require X-Api-Key header.

Endpoint Method Description
/v1/keys POST Get or create delegated keypair for a user
/v1/sign POST Sign an order message (returns signature only)
/v1/submit POST Sign and submit order to gateway
/v1/deposit/address POST Get deposit address via deposit service
/health GET Health check

Admin Endpoints

Require X-Admin-Key header.

Endpoint Method Description
/v1/admin/builders POST Register new builder
/v1/admin/builders GET List all builders

Cancel Orders

Use the gateway directly with the user's public key:

# Cancel single order
curl -X POST ${GATEWAY_URL}/v1/orders/cancel \
  -d '{"market_id": "abc...", "order_id": 42, "user": "7yQ...", "signature": "..."}'

# Cancel all orders for user
curl -X POST ${GATEWAY_URL}/v1/orders/cancel-all \
  -d '{"user": "7yQ...", "market_id": "abc...", "signature": "deadbeef...", "nonce": 1}'

For cancel operations, use the signer's /v1/sign endpoint to get the signature, then submit to the gateway yourself.

Real-Time Data

Connect to the WebSocket server directly:

const ws = new WebSocket(`${WS_URL}/v1/ws`)

ws.onopen = () => {
  // Subscribe to book updates (includes yes/no prices)
  ws.send(JSON.stringify({ action: 'subscribe', channel: `book:${marketId}` }))
  // Subscribe to trades
  ws.send(JSON.stringify({ action: 'subscribe', channel: `trades:${marketId}` }))
  // Subscribe to user-specific fills
  ws.send(JSON.stringify({ action: 'subscribe', channel: `user:${publicKey}` }))
}

See WebSocket Guide for full event documentation.

Creating Markets

Builders can create markets/events via the gateway (requires admin key in production):

# Binary market (Yes/No)
curl -X POST ${GATEWAY_URL}/v1/events \
  -H "X-Admin-Key: ${ADMIN_KEY}" \
  -d '{
    "title": "Will BTC reach $200k?",
    "category": "crypto",
    "outcomes": ["Yes"],
    "resolution_source": "price_oracle",
    "expiry": 1798761600,
    "creator": "7yQ..."
  }'

# Multi-outcome event
curl -X POST ${GATEWAY_URL}/v1/events \
  -H "X-Admin-Key: ${ADMIN_KEY}" \
  -d '{
    "title": "Who will win the Super Bowl?",
    "category": "sports",
    "outcomes": ["Chiefs", "Eagles", "49ers", "Other"],
    "resolution_source": "api_oracle",
    "expiry": 1798761600,
    "creator": "7yQ..."
  }'

Market creators earn 10% of all trading fees collected on their markets.

Rate Limiting

Requests are rate-limited via a token bucket keyed by API key (IP as fallback). Default 10 req/s, configurable via RATE_LIMIT_RPS env on the signer. Exceeding the limit returns HTTP 429 with a JSON error ({"error": "rate limit exceeded"}). Admin-authenticated endpoints (via X-Admin-Key) bypass the limit.

Security Model

  • API keys identify and rate-limit builders
  • Delegated keypairs are managed by the signer server — builders never see private keys
  • The signer cannot withdraw funds — it only signs order messages
  • Users deposit USDC to their own proxy wallets on-chain
  • The signer is stateless for order signing (keys are persisted to disk)

Service URLs

Service Purpose Auth
Gateway REST API (markets, orders, balances) Public reads, admin writes
WebSocket Real-time market data Public
Signer Order signing for builders X-Api-Key
Deposit Funding (deposit/withdraw) Public
Swagger Interactive API docs {gateway_url}/swagger-ui/