Skip to content

System Endpoints

Health Check

GET /health

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:

  • status is healthy when signature verification is ready and the locally resolved executor_id matches the chain-side probe.
  • status is degraded when signature verification is not yet ready, or when executor_id and relayer_executor_id disagree (an active mismatch surfaces drift before any order is rejected).
  • relayer_executor_id may be null when the chain-side probe is temporarily unavailable. A null value alone is not a degradation signal; only an active disagreement with executor_id is.
  • Use executor_id when generating composite uuid_int values.
  • The route returns 503 if a backing dependency is unavailable.

Server Time

GET /system/time

Authentication: None

{
  "timestamp": 1713168000
}

Use this value to set expiration and deadline fields for signed payloads.

Token Registry

GET /tokens

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": "0xef64d15ed6c371545eb6dcd6c026c17dfb6c440f",
      "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 AMOUNT_BELOW_MIN (detail.code for quotes; detail.error_code for orders) 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

GET /markets

Authentication: None

Returns the active markets with quote/base metadata.

{
  "markets": [
    {
      "symbol": "USDC/EURC",
      "base_symbol": "USDC",
      "quote_symbol": "EURC",
      "base_address": "0x965d4b4546716e416e950bc30467d128455d2d0e",
      "quote_address": "0xef64d15ed6c371545eb6dcd6c026c17dfb6c440f",
      "tick_precision": 6,
      "quantity_precision": 6,
      "amount_step": "0.000001",
      "price_step": "0.000001",
      "rounding_mode": "reject_extra_precision",
      "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 if qty * 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

GET /fx/rate

Authentication: None.

Query Parameters

Parameter Required Description
base Yes Three ASCII letters; case-insensitive ISO currency code, e.g. USD
quote Yes Three ASCII letters; case-insensitive ISO currency code, e.g. SGD

Response

{
  "pair": "USD/SGD",
  "rate": "1.2843",
  "as_of": 1777372800.12,
  "source": "market_oracle",
  "observation_date": null,
  "rate_24h_ago": "1.2901",
  "as_of_24h_ago": 1777286400.05,
  "change_pct": "-0.4496"
}
Field Description
pair Requested base/quote orientation
rate Positive decimal-string rate
as_of Unix timestamp of the selected source data; not necessarily the request time
source identity, market_oracle or ecb_reference
observation_date ECB observation date (YYYY-MM-DD); null for the other sources
rate_24h_ago, as_of_24h_ago Available comparison rate and timestamp; nullable
change_pct Signed percentage change as a decimal string with four decimal places; nullable

Source and Freshness

  • identity: the same currency on both sides returns rate 1, comparison rate 1, change 0.0000 and no observation date, without querying the data store.
  • market_oracle: aggregates provider quotes using time clusters, outlier filtering and a median. It can select the inverse pair and calculate 1 / inverse_rate to eight decimal places. The historical lookup uses the same orientation; missing history around T-24h (default ±1 hour) leaves comparison fields null while the current rate still returns 200.
  • ecb_reference: when neither market direction yields usable data, an available, deployment-enabled ECB source can return a daily reference rate. Its comparison fields describe available reference observations. This fallback is used only by public FX lookup; it does not become a Swap execution price. Always inspect source, as_of and observation_date before displaying a rate as current.

Status Codes

HTTP Meaning
200 Current rate available; comparison fields may be null
400 Supplied currency code fails the three-letter ASCII check
422 Missing required parameter or query-schema validation failure
429 Public throttle, when enforced
503 Market data and optional ECB fallback are unavailable, or dependencies are not ready

Permit Metadata

GET /permit/metadata

Authentication: API Key required

Query parameters:

  • token: ERC-20 token address
  • owner: wallet that may sign the permit
  • spender: allowance target, typically the live sor_address or vault_address from GET /config
  • amount (optional): raw uint256 amount to compare against current allowance

Example response for a supported token:

{
  "token": "0x965d4b4546716e416e950bc30467d128455d2d0e",
  "owner": "0x...",
  "spender": "0x...",
  "current_allowance_raw": "0",
  "required": true,
  "permit_supported": true,
  "nonce": 4,
  "domain": {
    "name": "USD Coin",
    "version": "2",
    "chainId": 11155111,
    "verifyingContract": "0x965d4b4546716e416e950bc30467d128455d2d0e"
  }
}

Unsupported tokens return permit_supported: false and omit nonce / domain. The optional required flag is only present when you supply amount.

Public Config

GET /config

Authentication: None

Returns the public bootstrap values needed for signing and transaction building.

{
  "chain_id": 11155111,
  "sera_address": "0x83475A1bD98a8DC2DCd507A747e4DC85da241D6e",
  "vault_address": "0x3c7945840bAE0d7e7f3824Ebccef1962629250F0",
  "sor_address": "0x83c1368110B640A729f3810De5FBe94b99aa5668",
  "domain_separator": "0x...",
  "eip712_domain": {
    "name": "Sera",
    "version": "1",
    "chainId": 11155111,
    "verifyingContract": "0x83475A1bD98a8DC2DCd507A747e4DC85da241D6e"
  },
  "limits": {
    "vl_batch": { "min": 2, "max": 50 },
    "withdraw": { "cosignature_max_ttl_seconds": 600 }
  },
  "capabilities": {
    "balances": { "sync_enabled": true },
    "deposits": { "enabled": true, "restriction_reason": null },
    "withdrawals": { "instant_enabled": false },
    "orders": { "time_in_force": ["GTC"] }
  }
}

The config handler returns known fields and uses null for unknown values. Startup admission can still return 503 while the service or registries are not ready. Retry and validate required fields before signing.

Read limits.vl_batch.{min,max} and limits.withdraw.cosignature_max_ttl_seconds at runtime. The former is deployment-tunable; the co-signature ceiling is 600 seconds.

Account capabilities

capabilities.balances.sync_enabled controls whether balance synchronization is accepted. capabilities.deposits.enabled and nullable capabilities.deposits.restriction_reason describe deposit availability; deposit_accounting_paused means clients must pause deposit building/broadcasting. capabilities.withdrawals.instant_enabled describes instant withdrawal availability. Read the current values instead of copying this example. Capability flags do not replace per-request authentication, balance or eligibility checks.

Verify Signature

POST /verify-signature

Authentication: None

Useful for testing EIP-712 order signatures before placing an order.

fee_bps is optional, defaults to 0 and is reconstructed as signed feeBps; send the same value used when signing. A valid=true response verifies the signature only. It does not prove canonical order precision, minimum amounts, funds, UUID binding or placement admission; use order preview and the final order response for those checks.

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.

Response

{
  "valid": true,
  "recovered_address": "0x...",
  "expected_address": "0x...",
  "error": null
}

Precision, Caching and Capabilities

Current markets use quantity_precision = base_decimals and tick_precision = quote_decimals. amount_step, price_step and rounding_mode="reject_extra_precision" describe order entry; use preview before signing. For a below-minimum order, inspect detail.error_code="AMOUNT_BELOW_MIN"; Swap quote errors can use detail.code instead.

GET /markets supports ETag / If-None-Match: an unchanged representation returns 304 with no body. Decode JSON only after a 200. The endpoint supports gzip, sets Vary: Accept-Encoding, and returns 406 if the client rejects all available encodings.

GET /config also returns limits.withdraw.cosignature_max_ttl_seconds (600) and capabilities.orders.time_in_force (["GTC"]). Use the withdrawal limit for a co-signature deadline. Public order-entry capabilities do not describe Swap's separate execution flow.

Readiness and Screening Status

These endpoints support deployment, load balancing and monitoring and should be accessed through restricted operational ingress. Customer integrations do not need to poll them. Some probes query downstream dependencies and return runtime status; listing them here does not recommend direct public exposure.

Authentication: The application handlers do not require a trading API key; deployment ingress controls access. Paths below include the full version prefix.

Method Path Response and purpose
GET /api/v1/livez { "status": "alive" }; process liveness only
GET /api/v1/warmz status="warm", screening, registry and order-accounting readiness; can succeed before trading activation
GET /api/v1/readyz Compatibility alias for /policy-readyz
GET /api/v1/policy-readyz status="ready"; includes screening policy and active trading dependencies
GET /api/v1/traffic-readyz status="ready", scope="traffic", policy_readiness; checks serving dependencies without requiring screening to be available
GET /api/v1/screening/status provider, capability, state, ready, can_screen

Use /traffic-readyz for runtime traffic admission and /policy-readyz when policy readiness is required. Dependency failures return 503. A process can be alive while not ready; a traffic-ready service still applies screening separately to protected actions. ecb_fx in readiness responses is informational.

For screening status, ready=true does not always mean a decision was probed: a configured third-party provider can have can_screen=null, and a disabled development provider has can_screen=false. This endpoint does not screen a particular wallet. Use the separate Address Screening API for address queries.