Skip to main content
This document outlines Ekiden’s API design conventions and standards. These ensure consistency, developer-friendliness, and compatibility across all REST and WebSocket interfaces.

1. Base URLs and Environments

Ekiden provides separate base URLs for each environment:
All API calls must use HTTPS.

2. Versioning

We use URI-based versioning:
  • Format: /v1/
  • Example: GET /v1/market/tickers
Backward-incompatible changes will trigger a new version (e.g., /v2/).

3. RESTful Design

MethodDescription
GETFetch resources (e.g., market data)
POSTCreate resources or perform actions (e.g., place or amend an order)
DELETECancel or remove resources
PUTReplace or update resources where applicable (e.g., whitelist management)
  • Endpoints are organized by resource

4. WebSocket Protocol

Endpoints:
  • Mainnet: (Coming Soon)
  • Testnet Beta:
    • Public data: wss://api.cnt.ekiden.fi/ws/public
    • Private data: wss://api.cnt.ekiden.fi/ws/private
  • Devnet:
    • Public data: wss://api.canton.ekiden.fi/ws/public
    • Private data: wss://api.canton.ekiden.fi/ws/private
Messages use an op field with snake_case values. Optional req_id lets you correlate requests/responses.

Topics

  • Public (Market-scoped):
    • orderbook.<depth>.<symbol> (e.g., orderbook.1.BTC-USDC)
    • trade.<symbol>
    • ticker.<symbol>
    • kline.<interval>.<symbol>
  • Private (User-scoped, only over /ws/private after auth):
    • order
    • position
    • execution
    • account_balance

Subscribe

Client → Server
{
  "op": "subscribe",
  "args": ["orderbook.1.BTC-USDC", "ticker.BTC-USDC"],
  "req_id": "optional-id"
}
Server → Client
{
  "op": "subscribed",
  "args": ["orderbook.1.BTC-USDC", "ticker.BTC-USDC"],
  "req_id": "optional-id"
}

Unsubscribe

{
  "op": "unsubscribe",
  "args": ["orderbook.1.BTC-USDC"]
}

Event delivery

{
  "op": "event",
  "topic": "ticker.BTC-USDC",
  "server_ts_ms": 1731541800000,
  "data": { /* snapshot or update payload */ }
}

Authenticate (private WS only)

Send your JWT (see REST auth below) over /ws/private: Client → Server
{ "op": "auth", "bearer": "<jwt>", "req_id": "optional-id" }
Server → Client
{ "op": "auth", "success": true, "user_id": "<user_id>", "req_id": "optional-id" }

5. Authentication (REST)

Private REST and private WebSocket use a short-lived JWT issued by the gateway, or API Key authentication.

JWT Authentication

  1. Request a token via POST /api/v1/authorize
{
  "public_key": "<Canton Party ID>",
  "signature": "",
  "timestamp_ms": 1731541800000,
  "nonce": "random-unique-string"
}
Response:
{ "token": "<jwt>", "user_id": "<user_id>" }
  1. Use the token with Bearer auth for private endpoints:
Authorization: Bearer <jwt>

API Key Authentication

Gateway supports API-key auth via headers:
  • X-API-KEY: Your API public key
  • X-SIGNATURE: Ed25519 signature over EKIDEN_API|{method}|{uri}|{timestamp_ms}|{nonce}
  • X-TIMESTAMP-MS: Current Unix timestamp in milliseconds
  • X-NONCE: Random unique string

6. Numerical Precision

  • All token quantities and prices are strings
  • Up to 18 decimal places
  • Use big number or decimal libraries — avoid floats
"2.000000000000000000"

7. Timestamps

We use explicit units depending on the field name and context:
  • timestamp (REST resources like orders, fills, positions): Unix seconds since epoch (int). Example: 1718000000.
  • timestamp_ms (REST authorize flow, API Key headers): Unix milliseconds since epoch (int). Example: 1718000000000.
  • server_ts_ms (WebSocket event envelope): Unix milliseconds since epoch (int).
  • ts (WebSocket ticker snapshots and ping/pong client_ts/server_ts):
    • For ticker ts: Unix milliseconds since epoch (int). Example: 1718000000000.
    • For WS ping/pong client_ts/server_ts: Unix milliseconds since epoch (int). Example: 1718000000000.
When an ISO 8601 string appears (e.g., funding endpoints), it is explicitly documented in the schema, e.g. "2025-05-10T12:34:56Z".

8. Error Handling

Error response format

{
  "code": "UNAUTHORIZED",
  "message": "Unauthorized"
}

Common Error Codes

CodeMeaning
BAD_REQUESTInvalid request parameters
UNAUTHORIZEDAuthentication failed or token expired
FORBIDDENInsufficient permissions (scopes)
RateLimitExceededToo many requests
NOT_FOUNDResource not found
SERVICE_UNAVAILABLEBackend service down or lagging
INTERNALUnexpected server error
HTTP status codes (400, 401, 403, 404, 429, 500, 503) are used appropriately.

9. Rate Limits

  • Public REST endpoints: 60 requests/minute
  • Private REST endpoints: 30 requests/minute per token

Example response on limit exceeded

{
  "code": "RateLimitExceeded",
  "message": "Rate limit exceeded"
}

10. Pagination

Offset-style pagination with page counters:
  • Query params: page (default 1), per_page (default 20)
GET /api/v1/trade/executions?symbol=BTCUSDC&page=1&per_page=20
Responses generally return arrays for list endpoints (see schema in the API reference).

11. Field Naming

  • All JSON keys use snake_case
  • All numeric values are strings (except timestamps and page counters)

12. WebSocket Heartbeats

Application-level ping/pong

  • Client may send:
{ "op": "ping", "req_id": "optional-id", "ts": 1718000000000 }
  • Server replies:
{ "op": "pong", "req_id": "optional-id", "client_ts": 1718000000000, "server_ts": 1718000001000 }
Timestamps are Unix milliseconds.

WebSocket-level ping/pong (keepalive)

  • The server periodically sends WebSocket-level pings and expects pongs.
  • If the server does not see a pong within the timeout window (~30s by default), it will close the connection.
Clients should automatically answer WS-level pings and may also send periodic app-level ping messages if desired.
For detailed endpoint specifications and integration examples, continue to the API reference.