Base URL
All endpoints are served over HTTPS and share one base:Authentication
Every request carries your API key as a Bearer token. The key prefix selects the environment:mk_live_ for production, mk_test_ for sandbox. The same endpoints serve both. See Authentication for the full details.
Response envelope
Every endpoint returns the same envelope:data is populated and error is null. On failure data is null and error carries a machine-readable code, a human-readable message, and optional details. meta carries request context such as the data source. Branch on error.code, not on the message text.
Amounts and rates
Monetary amounts are in USDC unless a field name says otherwise (fields ending in_usd or _usdc). Exchange rates are decimal numbers in quote currency per USDT - a price of 1620.5 on USDTNGN means 1,620.5 naira per USDT. Timestamps are ISO-8601 in UTC.
Asynchronous actions
Opening, adding to, reducing, and closing a Hedge are asynchronous. The call returnsstatus: "submitted" with a transaction hash, and the position settles on-chain shortly after. You poll GET /hedges/{id} (or GET /positions) for the result. There are no webhooks yet.
Idempotency
Opening, adding, reducing, and closing are state-changing, so make them safe to retry with anIdempotency-Key header (any unique string, such as a UUID or your own deal id):
409 idempotency_key_reuse. A key whose request is still in flight returns 409 idempotency_in_flight. Keys are scoped per environment, so sandbox and production never collide.
Rate limits
Requests are rate limited per API key. If you exceed the limit you get429 rate_limited; back off and retry. Read endpoints (markets, prices, account, positions) are safe to poll at a steady cadence; there’s no need to poll faster than every second or two.
Errors
Every error response hasdata: null and a populated error with a stable code, a human-readable message, and optional details. Branch on code. 4xx codes are your request to fix; 5xx codes are transient, so retry with backoff.

