Skip to content

Request conventions

ElementConvention
Base URLhttps://api.expreci.com/v1
AuthenticationAuthorization: Bearer YOUR_API_TOKEN
IdempotencyIdempotency-Key required for retryable writes
Request tracingX-Request-Id accepted and returned when valid
VersioningMajor version in path; additive fields permitted

Endpoint index

MethodResourcePurpose
GET/v1/marketsList normalized markets and resolution metadata.
GET/v1/markets/{market_id}/bookReconstruct one book at a timestamp or sequence.
GET/v1/markets/{market_id}/eventsRead ordered snapshots, deltas, and gap records.
GET/v1/streams/bookEstablish a resumable real-time book event stream.
POST/v1/portfolios/valuateValue a supplied portfolio snapshot under one market state.
POST/v1/scenarios/evaluateEvaluate user-supplied joint outcomes and assumptions.

List markets

GET /v1/markets

Returns normalized market definitions with cursor pagination. Filters include status, close-time range, outcome count, and source market identifier.

Request
curl --request GET \
  --url 'https://api.expreci.com/v1/markets?status=open&limit=2' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Accept: application/json'
200 response
{
  "data": [
    {
      "market_id": "mkt_01K2F7Y9AT4B",
      "question": "Will the policy rate be below 4% on 2026-09-30?",
      "status": "open",
      "close_time": "2026-09-30T16:00:00Z",
      "asset_ids": ["ast_01K2F7Z1CN8Q", "ast_01K2F7Z41D5X"]
    }
  ],
  "next_cursor": "cur_01K2FA1P8M2D",
  "request_id": "req_01K2FA2GX7J9"
}

Reconstruct a historical book

GET /v1/markets/{market_id}/book

Returns a materialized book for one asset at an exact sequence or the latest valid state at or before a timestamp. The response carries reconstruction provenance and does not silently return a complete-looking book across a known sequence gap.

Query parameters

FieldTypeRequiredDescription
asset_idstringyesOutcome asset whose book should be reconstructed.
at_sequenceintegerconditionalExact source sequence; mutually exclusive with time.
at_timetimestampconditionalExchange timestamp boundary in UTC.
depthintegernoPrice levels per side; maximum 1,000.
200 response
{
  "data": {
    "market_id": "mkt_01K2F7Y9AT4B",
    "asset_id": "ast_01K2F7Z1CN8Q",
    "as_of_sequence": 18422091,
    "exchange_timestamp": "2026-06-01T14:02:09.481Z",
    "reconstruction": {
      "engine_version": "0.3.0",
      "starting_snapshot_sequence": 18421950,
      "complete": true,
      "gap_ids": []
    },
    "bids": [
      { "price": "0.6200", "size": "1450.00", "order_count": 8 }
    ],
    "asks": [
      { "price": "0.6300", "size": "980.00", "order_count": 5 }
    ]
  },
  "request_id": "req_01K2F9G3M4P7"
}

Read ordered market events

GET /v1/markets/{market_id}/events

Reads a cursor-paginated sequence of normalized book_snapshot, book_delta, and sequence_gap events. Filters would include asset, event type, sequence range, exchange-time range, and capture region. Consumers must tolerate additive event types and retain the cursor only after processing the full page.

Streaming concept

The real-time interface uses a WebSocket transport with the same normalized event envelope as the historical API. A connection starts with an authenticated upgrade, then one or more explicit subscriptions. The acknowledgement fixes the ordering scope, starting sequence, and heartbeat interval. Every data event carries a durable resume cursor.

  1. Request market and asset subscriptions with the last durable cursor, if one exists.
  2. Receive a subscription acknowledgement followed by a snapshot or explicit continuity marker before applying deltas.
  3. Persist cursor and events atomically on the consumer side.
  4. On reconnect, resume from the durable cursor. If retention has expired, fetch the missing interval through the historical event endpoint and resubscribe from the recovered cursor.
Subscription message
{
  "action": "subscribe",
  "channels": [
    {
      "name": "book",
      "market_ids": ["mkt_01K2F7Y9AT4B"],
      "depth": 50
    }
  ],
  "resume_cursor": "cur_01K2FC1V4H8B"
}
Book event
{
  "type": "book_delta",
  "event_id": "evt_01K2FC4Q7N5Z",
  "cursor": "cur_01K2FC4S9R1M",
  "market_id": "mkt_01K2F7Y9AT4B",
  "asset_id": "ast_01K2F7Z1CN8Q",
  "sequence": 18422091,
  "exchange_timestamp": "2026-06-01T14:02:09.481Z",
  "received_timestamp": "2026-06-01T14:02:09.497Z",
  "changes": [
    { "side": "bid", "price": "0.6200", "size": "1450.00" }
  ]
}

Evaluate a scenario

POST /v1/scenarios/evaluate

Evaluates user-defined terminal states against a supplied portfolio snapshot. It calculates conditional values; it does not estimate the state's probability or recommend a portfolio action.

Request
POST /v1/scenarios/evaluate
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json

{
  "portfolio": {
    "base_currency": "USD",
    "positions": [
      {
        "asset_id": "ast_01K2F7Z1CN8Q",
        "quantity": "25000.00",
        "average_cost": "0.5800"
      }
    ]
  },
  "states": [
    {
      "label": "policy-easing-no-soft-landing",
      "outcomes": {
        "mkt_01K2F7Y9AT4B": "yes",
        "mkt_01K2F8A12Y6N": "no"
      }
    }
  ]
}
200 response
{
  "data": {
    "valuation_id": "val_01K2FB5D8T3R",
    "portfolio_value_before": "184250.00",
    "states": [
      {
        "label": "policy-easing-no-soft-landing",
        "terminal_value": "121600.00",
        "change": "-62650.00",
        "constraint_status": "valid",
        "position_attribution": [
          {
            "asset_id": "ast_01K2F7Z1CN8Q",
            "terminal_value": "25000.00",
            "change": "9500.00"
          }
        ]
      }
    ],
    "advisory": false
  },
  "request_id": "req_01K2FB6J9W4Q"
}

Error format

Non-2xx responses use a stable machine code, human-readable message, structured details when safe, and a request identifier. Clients must branch on error.code, not message text.

409 response
{
  "error": {
    "code": "BOOK_SEQUENCE_GAP",
    "message": "A complete book cannot be reconstructed at the requested point.",
    "details": {
      "market_id": "mkt_01K2F7Y9AT4B",
      "missing_from_sequence": 18422040,
      "missing_to_sequence": 18422044
    },
    "documentation_url": "https://www.expreci.com/docs/api#errors"
  },
  "request_id": "req_01K2FB8N2A6V"
}
HTTPExample codeMeaning
400INVALID_REQUESTMalformed or semantically invalid input.
401AUTHENTICATION_REQUIREDCredential absent, expired, or invalid.
404RESOURCE_NOT_FOUNDResource does not exist or is outside the caller scope.
409BOOK_SEQUENCE_GAPRequested reconstruction cannot be declared complete.
429RATE_LIMITEDResource budget exhausted; inspect Retry-After.

Rate limits and pagination

Response headers are RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. Historical collections return an opaque next_cursor; clients must not parse or construct cursors.