Skip to main content
Everything in the API follows a small set of shared conventions. Read this once and the rest of the reference reads consistently.

Base URL

All endpoints are served over HTTPS and share one base:
Plain HTTP is not supported.

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:
On success 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 returns status: "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 an Idempotency-Key header (any unique string, such as a UUID or your own deal id):
Retrying with the same key and the same body returns the original result instead of acting twice. Reusing a key with a different body returns 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 get 429 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 has data: 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.

Error codes