Environments and base URLs
The same API runs in two environments; pick the base URL for the environment your credentials belong to (keys are not shared between them):
All paths in this reference are relative to the base URL. Requests and
responses are identical in both environments, with one exception:
POST /fund (the faucet) is sandbox-only and returns 404 on production,
where wallets are funded by real on-chain deposits instead.
Authentication
Protected endpoints accept either credential; theAuthorization header wins
when both are present:
403 session_required when called with an API key: password change, TOTP and
passkey management, key create/revoke, and wallet export. Each is labeled in
its endpoint page. Background in
Authentication.
The response envelope
Every endpoint (except the flat Sandbox probes) wraps its result:error.code for specifics;
the full catalog is in Errors.
Conventions
Write bodies must be application/json
Write bodies must be application/json
POST/PATCH/DELETE requests with bodies require
Content-Type: application/json; anything else is rejected with
415 unsupported_media_type. (This doubles as CSRF protection.)Amounts are decimal strings
Amounts are decimal strings
Human units, string-typed:
"125.50" means 125.5 tokens. No wei, no base
units, no floats. The one exception: GET /gas additionally reports wei
strings for precision-sensitive tooling.IDs are opaque strings
IDs are opaque strings
Wallets, transactions, keys, and passkeys use cuid-style IDs. IDs from
another account read as
404 not_found; ownership is enforced on every
access.Timestamps are ISO 8601 UTC
Timestamps are ISO 8601 UTC
e.g.
"2026-08-13T09:30:00.000Z".Pagination is page-based
Pagination is page-based
GET /transactions takes page (default 1) and pageSize (default 20,
max 100) and returns items, page, pageSize, total.Money movement is asynchronous
Money movement is asynchronous
/fund, /mint, /transfer, /redeem validate the request, record the
transaction, and return 201 immediately with the transaction in status
QUEUED (txHash: null). A background worker then submits it to the
chain (PENDING, txHash set) and tracks it to a terminal state. Poll
GET /transactions/{id} until status is CONFIRMED, SETTLED, or
FAILED; reads are plain database reads and never block on the chain.
Execution failures surface as status: "FAILED" with error and
errorCode on the transaction, not as an HTTP error on the POST. See
Transactions.Rate limits
30 writes and 120 reads per minute per principal; 10 login attempts per 15 minutes per IP. Exceeding a limit returns429 rate_limited. Details and
patterns in Rate limits.
Sandbox endpoints
GET /sandbox (status probe) and POST /sandbox (JSON echo) are unauthenticated
connectivity checks with a flat response shape (no data envelope):
Try it here
Every endpoint page in this reference has an interactive playground: select the server (production or sandbox), authenticate with the matchingaro_sk_…
key, and requests run against the live environment. Prefer the sandbox while
exploring; production calls move real funds. A good first call is
GET /auth/session (under Auth in the sidebar): it echoes back who you
are and which credential authenticated.