API Overview¶
The Sera API is a versioned REST API for trading, balance queries, and transaction-building flows.
Base URL¶
Content Type¶
All request and response bodies use JSON.
Authentication¶
| Method | Used For | How It Is Sent |
|---|---|---|
| API Key | Read endpoints and transaction-building helpers | Authorization: Bearer {api_key}:{api_secret} |
| EIP-712 Signature | Trading mutations, cancellations, withdrawals, API-key management | Signature fields in the request body or query string |
See Authentication for the EIP-712 domain, typed-data payloads, and uuid_int rules.
Rate Limits¶
Public per-client limits can also be configured at the edge proxy/CDN; check the limits published for your environment.
Requests authenticated with an API key are additionally rate limited per wallet inside the application:
| Group | Typical Endpoints | Limit |
|---|---|---|
read | GET /orders, GET /balances, GET /fills | 10 req/s |
trade | POST /orders, POST /swap | 5 req/s |
cancel | POST /orders/cancel, POST /orders/cancel-all | 2 req/s |
transfer | Deposit, approve, withdraw, transfer, and tx-broadcast helpers | 2 req/s |
quote | POST /swap/quote, POST /swap/quote/batch, Exact Output quotes | 50 quotes/s |
Access Scope¶
Customer endpoints support external integrations and retain the API-key, wallet-signature or signed-transaction requirements documented for each operation. “None” in the table means no trading API key is required; it does not mean unrestricted access. Credential verification still requires the credentials being verified. Use the features and ingress provided for your environment.
Operational probes are for deployment, load balancing and monitoring and should be accessed through restricted operational ingress. They are outside the customer trading flow. Documenting their paths does not require exposing them to the public internet.
Endpoints¶
System¶
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | None | Service health, executor_id, and signature readiness |
| GET | /system/time | None | Server timestamp for signature deadlines |
| GET | /tokens | None | Whitelisted token registry |
| GET | /markets | None | Active markets with token metadata |
| GET | /fx/rate | None | Aggregated FX rate for an ISO currency pair plus 24h delta |
| GET | /permit/metadata | API Key | EIP-2612 permit domain, nonce, and allowance probe |
| GET | /config | None | Public chain and contract bootstrap config |
| POST | /verify-signature | None | Verify an EIP-712 order signature |
Trading¶
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /swap/quote | None | Get a swap quote and signed route_params payload |
| POST | /swap/quote/batch | None | Up to 50 independent quotes |
| POST | /orders/preview | None | Canonical values and EIP-712 Order preview |
| POST | /swap | EIP-712 | Execute a signed swap quote |
| POST | /orders | EIP-712 | Place a limit order |
| POST | /orders/cancel | EIP-712 | Cancel a single order |
| POST | /orders/cancel-all | API Key + EIP-712 | Cancel all open orders |
| POST | /orders/vl/batch | EIP-712 | Place a Virtual Liquidity batch |
| POST | /orders/vl/cancel | EIP-712 | Cancel a full Virtual Liquidity batch |
Orders And Fills¶
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /orders/{order_id} | API Key | Get one order by ID |
| GET | /orders | API Key | List orders for one account |
| GET | /fills/{order_id} | API Key | List fills for one order |
| GET | /fills | API Key | List fills across all orders |
Account And Funds¶
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /balances | API Key | Wallet + vault balances |
| POST | /balances/sync | API Key | Request balance synchronization |
| POST | /approve | API Key | Build unsigned ERC-20 approve(spender, amount) tx |
| POST | /deposit | API Key | Build unsigned depositFund or depositFundWithPermit tx |
| POST | /tx/send | API Key | Broadcast a signed approve/deposit tx |
| POST | /withdraw | EIP-712; optional API key | Request executor co-signature for instant withdraw |
| POST | /withdraw/build | User + executor signatures; optional API key | Build unsigned executeInstantWithdrawDualSig tx |
| POST | /withdraw/send | Signed transaction; optional API key | Broadcast a signed withdrawal tx |
| POST | /transfer | API Key | Build unsigned ERC-20 transfer tx |
| POST | /transfer/send | API Key | Broadcast a signed transfer tx |
API Key Management¶
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api-keys | EIP-712 | Create an API key |
| GET | /api-keys | EIP-712 | List API keys for one wallet (signed query parameters) |
| POST | /api-keys/list | EIP-712 | List API keys for one wallet (signed JSON body) |
| DELETE | /api-keys | EIP-712 | Revoke an API key (signed query parameters) |
| POST | /api-keys/revoke | EIP-712 | Revoke an API key (signed JSON body) |
| POST | /api-keys/revoke-all | EIP-712 | Bulk-revoke every active API key for one wallet in a single signature |
| POST | /api-keys/self-revoke | API Key | Revoke the API key currently being used |
| POST | /api-keys/verify | Key/secret in body | Verify the API key/secret pair supplied in the request body |
Additional API Versions and Services¶
| Method | Full Path | Auth | Reference |
|---|---|---|---|
| POST | /api/v2/orders | EIP-712 | Integer API |
| GET | /api/v2/orders/{order_id} | API Key | Integer API |
| GET | /api/v2/orders | API Key | Integer API |
| GET | /api/v2/fills/{order_id} | API Key | Integer API |
| GET | /api/v2/fills | API Key | Integer API |
| GET | /api/v2/balances | API Key | Integer API |
| POST | /api/v2/balances/sync | API Key | Request balance synchronization |
| POST | /api/v1/swap/exact-output/quote | None | Exact Output |
| POST | /api/v1/swap/exact-output | EIP-712 | Exact Output |
| GET | /api/v1/swap/exact-output/{quote_uuid} | API Key | Exact Output |
| GET | /api/v1/swap/exact-output | API Key | Exact Output, quote_uuid query parameter |
v1 and v2 coexist; v2 changes amounts, status interpretation and pagination. Use the complete versioned paths above. The Address Screening API is a separate service with its own host and response contracts. System endpoints also document GET /api/v1/livez, /api/v1/warmz, /api/v1/readyz, /api/v1/policy-readyz, /api/v1/traffic-readyz and /api/v1/screening/status.
Operational Probes¶
These endpoints are for operators. Their handlers do not require a trading API key; deployment ingress should restrict access separately. Absence of an API-key requirement does not establish public-ingress protection.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /livez | None | Process liveness |
| GET | /warmz | None | Warm-up dependencies |
| GET | /readyz | None | Policy-readiness compatibility alias |
| GET | /policy-readyz | None | Trading and screening policy readiness |
| GET | /traffic-readyz | None | Traffic-serving readiness |
| GET | /screening/status | None | Screening provider status; does not query an address |
Error Responses¶
Most errors return a JSON body with a detail field:
Most handler-side 5xx failures return 503 with {"detail":"Service temporarily unavailable; please retry"} and Retry-After: 1. Startup gates may return a different detail. See the client handling notes below for structured errors and safe retries.
Common Status Codes¶
| Code | Meaning |
|---|---|
| 200 | Success |
| 202 | Accepted; execution or balance synchronization is pending |
| 201 | Resource created |
| 400 | Bad request or signature mismatch |
| 401 | Missing or invalid API key |
| 403 | Authenticated wallet does not match requested owner |
| 404 | Resource not found |
| 409 | Conflict, such as replayed signature or self-match rejection |
| 410 | Quote expired, already consumed, or not found |
| 413 | Whole request body exceeds the deployment limit |
| 422 | Validation failure |
| 429 | Rate limit or cancel cooldown hit |
| 503 | Service temporarily unavailable; retry after the Retry-After header |
Code Examples¶
import requests
# Public endpoint
tokens = requests.get("https://api.testnet.sera.cx/api/v1/tokens").json()
# Authenticated endpoint
headers = {"Authorization": "Bearer sera_abc123:secret456"}
orders = requests.get(
"https://api.testnet.sera.cx/api/v1/orders",
params={"owner_address": "0x..."},
headers=headers,
).json()
// Public endpoint (no auth)
const tokens = await fetch("https://api.testnet.sera.cx/api/v1/tokens")
.then(r => r.json());
// Authenticated endpoint (API key)
const orders = await fetch(
"https://api.testnet.sera.cx/api/v1/orders?owner_address=0x...",
{ headers: { "Authorization": "Bearer sera_abc123:secret456" } },
).then(r => r.json());
Client Handling Notes¶
Quote and order-entry endpoints use an application-level public throttle; production-like environments require its 429 enforcement. Do not assume every anonymous endpoint uses the same limits. Batch quotes consume one slot per quote, not per HTTP request. API-key wallet limits still apply. Use X-RateLimit-Limit, X-RateLimit-Remaining and Retry-After when returned.
Most handler 5xx errors are replaced by a generic 503 with Retry-After: 1. Startup gates can return a different 503 detail while caches are warming. X-Sera-Retry-Safe: true explicitly marks selected failures before admission; without that marker, do not infer that a write had no effect. Query its order/quote identity before replacing an uncertain execution.
| Error field | Examples / client action |
|---|---|
detail.error_code | INVALID_PRECISION, INVALID_DECIMAL_FORMAT: use preview and sign canonical values |
detail.error_code | DUPLICATE_ORDER_ID: query that ID; use a new ID only for a distinct order |
detail.error_code | WITHDRAW_UNAVAILABLE: refresh balances and orders |
detail.error_code | COMPLIANCE_BLOCKED: protected action denied |
detail.code | Quote-specific codes such as AMOUNT_BELOW_MIN and Exact Output conflicts |
Top-level error_code with ok:false | Order-preview business rejection |
error.code | Separate screening service errors |
Do not assume detail is always a string or that every 422 contains Pydantic field details. Request-model errors use { "detail": "Invalid request" }. New flows also use 202 (execution pending), 304 (unchanged market response, no body), and 406 (unacceptable encoding). Unknown error codes should remain failures and retain the request ID for support.
Examples illustrate request/response shapes. Replace placeholder addresses and historic timestamps before sending requests; obtain current chain/contract values from /config and current seconds from /system/time. A path being documented does not establish that a particular deployment has enabled it.
Request body size¶
The trading API defaults to a 64 KiB (65,536 byte) limit on the complete request body; the target deployment may set another limit. The limit also applies to streamed bodies. Batch item counts and per-signature limits do not override the aggregate limit. HTTP 413 returns {"detail":"Request body too large"}; reduce the request size instead of retrying it unchanged. Screening has its own body and error rules. Its protocol/429 errors need not contain schema_version or error.retryable; do not require those fields for every error.