Start by checking whether you need auth at all
A surprising amount of product needs no credentials:
If you only read, skip authentication entirely and go straight to
rate limits to size your polling. Anonymous callers
get 60 reads a minute per IP, and streaming costs nothing against that.
Live data without polling
GET /v1/realtime/stream is a Server-Sent Events endpoint. Pass a
comma-separated topics list. These topics are public, so no session is
needed:
Last-Event-ID header (or ?lastEventId=) and the stream replays what you
missed, falling back to a reset signal if you were away too long to replay. Pair
that with an HTTP catch-up read so a long outage still converges.
Signed-in sessions add private topics for your own wallet:
user:{address}:orders, :fills, :parlays, and :notifications. Requesting
someone else’s is rejected, not silently emptied.
Authenticating a bot
Use a bearer token rather than a cookie jar. The full flow, including a dependency-free Python implementation of the signing scheme, is in Authentication. The short version: request a challenge, sign it with your Alephium key, exchange it for a session withissueToken: true, then send
Authorization: Bearer <token> on everything afterwards. No cookies, and no
x-csrf-token.
Tokens last 30 days with no refresh. Because re-authenticating costs one
signature, the simplest correct design is to catch a 401, run the challenge
flow again, and retry once.
Placing orders
Writes never hand Aura your key.POST /v1/tx/* returns an unsigned
transaction that you sign locally and submit to any Alephium node, so the flow is
always build, sign, submit. See Build-tx flow for
the response shape and a worked example.
Three things catch people out:
One order per transaction. There is no batch place or batch cancel endpoint.
Each order and each cancellation is its own build, signature, and submission,
which means a two-sided quote across five price levels is 10 writes to place and
10 to cancel. At the standard 60 writes a minute that’s roughly three full
refresh cycles per minute, so size your quoting loop accordingly or ask about
elevated limits.
Transactions from one wallet compete for the same coins. If you build
several transactions from the same wallet and submit them together, all but one
are typically rejected, because each was built against the same unspent outputs.
Submit and confirm in sequence, or use your node’s chained-transaction endpoint
to have the outputs threaded for you.
Quantities are lot-aligned. quantity must be a multiple of 10000000
(1e7). The builder rejects anything else up front rather than letting it fail
on chain.
Acting for other users
/v1/tx/* enforces that the transaction’s signer equals the session’s wallet, so
a session for wallet A can never build a transaction spending from wallet B. That
holds even for a signed request with someone else’s signerAddress in the body.
If you’re building a copy-trading service, a portfolio manager, or any product
that transacts on behalf of others, each user needs their own session and signs
their own transactions. There is no delegation or operator model, and designing
around one will not work.
Error handling worth getting right
429carriesRateLimit-RemainingandRateLimit-Reset. Back off on the header rather than a fixed sleep.401on a previously working token means it expired. Re-authenticate and retry once, then give up rather than looping.502means the Alephium node refused to build your transaction, and is usually transient. Retry with backoff.409is a state conflict rather than a transport failure. Retrying the same request unchanged will not fix it.
POST /v1/tx/* is always safe, since those endpoints build transactions
and never submit them. The returned unsignedTx can differ between calls as
your unspent outputs change, and only the one you actually sign and submit
matters.
Full status and code tables are in Errors.
Generating a client
The spec at/openapi.json is OpenAPI
3.1, generated from the live route definitions, so it never drifts from the
implementation. Point any generator at it:
me in the path rather than an address,
for example GET /v1/users/me, GET /v1/referrals/me/summary, and
GET /v1/users/me/pending-reveals. Endpoints that take {address} return
public data and work for any wallet.

