Request conventions
| Element | Convention |
|---|---|
| Base URL | https://api.expreci.com/v1 |
| Authentication | Authorization: Bearer YOUR_API_TOKEN |
| Idempotency | Idempotency-Key required for retryable writes |
| Request tracing | X-Request-Id accepted and returned when valid |
| Versioning | Major version in path; additive fields permitted |
Endpoint index
| Method | Resource | Purpose |
|---|---|---|
GET | /v1/markets | List normalized markets and resolution metadata. |
GET | /v1/markets/{market_id}/book | Reconstruct one book at a timestamp or sequence. |
GET | /v1/markets/{market_id}/events | Read ordered snapshots, deltas, and gap records. |
GET | /v1/streams/book | Establish a resumable real-time book event stream. |
POST | /v1/portfolios/valuate | Value a supplied portfolio snapshot under one market state. |
POST | /v1/scenarios/evaluate | Evaluate 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.
curl --request GET \
--url 'https://api.expreci.com/v1/markets?status=open&limit=2' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--header 'Accept: application/json'{
"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
| Field | Type | Required | Description |
|---|---|---|---|
asset_id | string | yes | Outcome asset whose book should be reconstructed. |
at_sequence | integer | conditional | Exact source sequence; mutually exclusive with time. |
at_time | timestamp | conditional | Exchange timestamp boundary in UTC. |
depth | integer | no | Price levels per side; maximum 1,000. |
{
"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.
- Request market and asset subscriptions with the last durable cursor, if one exists.
- Receive a subscription acknowledgement followed by a snapshot or explicit continuity marker before applying deltas.
- Persist cursor and events atomically on the consumer side.
- 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.
{
"action": "subscribe",
"channels": [
{
"name": "book",
"market_ids": ["mkt_01K2F7Y9AT4B"],
"depth": 50
}
],
"resume_cursor": "cur_01K2FC1V4H8B"
}{
"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.
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"
}
}
]
}{
"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.
{
"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"
}| HTTP | Example code | Meaning |
|---|---|---|
| 400 | INVALID_REQUEST | Malformed or semantically invalid input. |
| 401 | AUTHENTICATION_REQUIRED | Credential absent, expired, or invalid. |
| 404 | RESOURCE_NOT_FOUND | Resource does not exist or is outside the caller scope. |
| 409 | BOOK_SEQUENCE_GAP | Requested reconstruction cannot be declared complete. |
| 429 | RATE_LIMITED | Resource 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.