System Endpoints¶
Health Check¶
Authentication: None
Returns service health plus the live executor_id and whether signature verification is ready.
{
"status": "healthy",
"version": "v1",
"timestamp": "2026-04-15T08:00:00+00:00",
"executor_id": 0,
"relayer_executor_id": 0,
"signature_ready": true
}
Notes:
statusishealthywhen signature verification is ready and the locally resolvedexecutor_idmatches the chain-side probe.statusisdegradedwhen signature verification is not yet ready, or whenexecutor_idandrelayer_executor_iddisagree (an active mismatch surfaces drift before any order is rejected).relayer_executor_idmay benullwhen the chain-side probe is temporarily unavailable. Anullvalue alone is not a degradation signal; only an active disagreement withexecutor_idis.- Use
executor_idwhen generating compositeuuid_intvalues. - The route returns
503if a backing dependency is unavailable.
Server Time¶
Authentication: None
Use this value to set expiration and deadline fields for signed payloads.
Token Registry¶
Authentication: None
{
"tokens": [
{
"currency": "USD",
"symbol": "USDC",
"address": "0xDcaEcdd8Db64f4316A11917Ad0162DEBD935285b",
"decimals": 6,
"min_trade_amount_raw": "8800000",
"min_trade_amount": "8.800000"
},
{
"currency": "EUR",
"symbol": "EURC",
"address": "0xd3BdB2CE9cD98566EFc2e2977448c40578371779",
"decimals": 6,
"min_trade_amount_raw": "0",
"min_trade_amount": "0"
}
]
}
The response shape is an object with a tokens array.
min_trade_amount_raw mirrors the on-chain minAmount stored per token on the Sera contract — the minimum from-token amount (in raw units) that a match will accept. A submission whose input falls below this floor is rejected pre-flight with HTTP 400 and detail.code = "AMOUNT_BELOW_MIN" on both /swap/quote and /orders. "0" means no floor. The decimal companion min_trade_amount is min_trade_amount_raw / 10^decimals.
Market Registry¶
Authentication: None
Returns the active markets with quote/base metadata.
{
"markets": [
{
"symbol": "EURC/USDC",
"base_symbol": "EURC",
"quote_symbol": "USDC",
"base_address": "0xd3BdB2CE9cD98566EFc2e2977448c40578371779",
"quote_address": "0xDcaEcdd8Db64f4316A11917Ad0162DEBD935285b",
"tick_precision": 4,
"quantity_precision": 2,
"base_decimals": 6,
"quote_decimals": 6,
"min_ask_amount_raw": "0",
"min_ask_amount": "0",
"min_bid_quote_amount_raw": "8800000",
"min_bid_quote_amount": "8.800000"
}
]
}
base_address and quote_address are the ERC-20 contract addresses that uniquely identify the pair. base_symbol / quote_symbol are the display tickers and match the symbol string. Pair orientation is canonicalised server-side so that base_address < quote_address bytewise (lowercased).
min_ask_amount_raw / min_bid_quote_amount_raw derive from the per-token on-chain minimum (see /tokens → min_trade_amount_raw):
- ASK floor is the base-token minimum — price-independent. A sell order rejects if
qty * 10^base_decimals < min_ask_amount_raw. - BID floor is surfaced on the quote side because the effective base minimum depends on price:
min_base(P) = min_bid_quote_amount / P. A buy order rejects ifqty * price * 10^quote_decimals < min_bid_quote_amount_raw.
Decimal companions (min_ask_amount, min_bid_quote_amount) are the raw values scaled by the respective token's decimals for display.
FX Rate¶
Authentication: None
Aggregated FX rate for an ISO currency pair plus the day-over-day delta. The endpoint reads the same provider-quote pipeline that swap pricing uses (time-cluster + outlier filter + median across providers), without applying the swap-pricing post-aggregation freshness gate — the actual as_of timestamp is returned so the caller can judge freshness.
Query Parameters¶
| Name | Type | Required | Description |
|---|---|---|---|
base | string | yes | ISO currency code (e.g. USD). Case-insensitive, alphabetic only. |
quote | string | yes | ISO currency code (e.g. SGD). Case-insensitive, alphabetic only. |
Response¶
{
"pair": "USD/SGD",
"rate": "1.2843",
"as_of": 1777372800.12,
"rate_24h_ago": "1.2901",
"as_of_24h_ago": 1777286400.05,
"change_pct": "-0.4496"
}
pairalways reflects the requested orientation (base/quote), regardless of which direction the underlying provider data came from.rateis the median across providers within the configured time-cluster- outlier-filter window.
as_ofis the unix timestamp of the newest provider quote in the cluster.rate_24h_ago,as_of_24h_ago, andchange_pctare nullable when no quote was found within ±1h of T-24h. The endpoint still returns 200 in that case — coverage gaps are not a freshness failure.change_pctis signed and rendered to 4 decimal places.
Auto-Inversion¶
When only the inverse pair has data at the current anchor (e.g. the caller asks for SGD/USD but the scraper only stores USD/SGD), the rate is computed as 1 / inverse_rate and quantised to 8 decimal places. The historic anchor is locked to the same direction — orientations are never mixed across the two anchors.
Same Currency¶
?base=USD"e=USD returns rate=1, rate_24h_ago=1, change_pct=0 without querying the data store.
Status Codes¶
| Code | Meaning |
|---|---|
| 200 | Success — rate is always present; historic fields may be null. |
| 400 | base/quote missing or non-alphabetic. |
| 503 | No provider data for either direction within the current-anchor recency window (default 4h). |
Permit Metadata¶
Authentication: API Key required
Query parameters:
token: ERC-20 token addressowner: wallet that may sign the permitspender: allowance target, typically the livesor_addressorvault_addressfromGET /configamount(optional): raw uint256 amount to compare against current allowance
Example response for a supported token:
{
"token": "0xDcAEcdd8Db64f4316A11917Ad0162DEBD935285b",
"owner": "0x...",
"spender": "0x...",
"current_allowance_raw": "0",
"required": true,
"permit_supported": true,
"nonce": 4,
"domain": {
"name": "USD Coin",
"version": "2",
"chainId": 11155111,
"verifyingContract": "0xDcAEcdd8Db64f4316A11917Ad0162DEBD935285b"
}
}
Unsupported tokens return permit_supported: false and omit nonce / domain. The optional required flag is only present when you supply amount.
Public Config¶
Authentication: None
Returns the public bootstrap values needed for signing and transaction building.
{
"chain_id": 11155111,
"sera_address": "0xd0fc92d8eF9bE26D7288fCa1D6458f675e72B83a",
"vault_address": "0x5d6ffA9b9710C7Ab69105496a0fD8C48DfF40110",
"sor_address": "0xAfDb9f6071feD09941930246E78ce301DF7d1ace",
"domain_separator": "0x...",
"eip712_domain": {
"name": "Sera",
"version": "1",
"chainId": 11155111,
"verifyingContract": "0xd0fc92d8eF9bE26D7288fCa1D6458f675e72B83a"
},
"limits": {
"vl_batch": { "min": 2, "max": 50 }
}
}
This endpoint intentionally stays available even during partial startup. Missing values are returned as null; clients should retry rather than treating null fields as a hard failure.
limits carries public API caps that may vary per deployment. Read the active values at runtime via GET /config instead of hardcoding. Today this contains limits.vl_batch.{min,max} (VL batch placement size); future caps will live under additional sub-keys.
Verify Signature¶
Authentication: None
Useful for testing EIP-712 order signatures before placing an order.
Request Body¶
{
"owner_address": "0x...",
"side": "bid",
"amount": "1000.0",
"price": "1.085",
"from_address": "0x...",
"to_address": "0x...",
"order_id": "00000000-0000-4000-8000-000000000001",
"uuid_int": "6427948336465191935941739505432058208337171677044006212075520",
"signature": "0x...",
"expiration": 1713254400
}
from_address is the market base token and to_address is the market quote token. expiration is required and must satisfy the same bounded future rule as POST /orders.