- Credential issuance. A signature proves control of a wallet once, and returns an API key and secret.
- Request signing. Every call carries an HMAC signature computed with that secret.
Choosing a wallet
Every order is signed by the wallet that holds the collateral, because on-chain settlement checks that the order signature recovers to the trading wallet. The signing key must therefore be the key to the funds.- A dedicated wallet
- A Noise app wallet
Generate or use an EOA whose private key is already held locally, fund it with USDC on Base, and configure the client against it.This is the recommended setup. The wallet is separate from the Noise app account, so a compromise of the client is contained to the capital held in that wallet.
Minting a credential
Sign an EIP-712NoiseAuth attestation with the wallet and POST /keys.
This route and POST /keys/rotate are the only authenticated routes that take no HMAC headers. The attestation signature is the authorization, which it must be, since no key exists yet.
The domain, where chainId is exchange.attestationChainId from GET /status (configured separately from the order chain, even when the two match):
message field must be exactly this string:
existing:
existing: true. A retry after a dropped response is therefore safe, and re-signing the same attestation recovers a lost secret.
Scopes
trade implies read, because a client must reconcile its own fills. A read key suits accounting or dashboards; a read key that attempts to submit receives 403 FORBIDDEN.
Rotation and revocation
Rotate withPOST /keys/rotate and a fresh attestation at nonce + 1. Rotating invalidates the old secret. When the current nonce is unknown, submit any nonce and read the NONCE_CONFLICT error, which names the nonce to use.
Revoke with DELETE /keys/{apiKey}. A revoked key also closes any open WebSocket with code 4001.
Restricting a key by source address
BothPOST /keys and POST /keys/rotate accept an optional ipAllowlist of up to 20 entries, enforced on both HTTP and the WebSocket.
Matching is exact, so pass individual addresses, because a CIDR range is rejected rather than silently matching nothing. Omitting the field on rotate leaves an existing allowlist in place; passing an empty array clears it.
Signing requests
Every authenticated request carries these headers:
The canonical message is four parts concatenated with no separators:
timestampis the same value as the header.METHODis uppercased, for examplePOST.pathincludes the query string, for example/api/trader/v1/account/orders?limit=50.bodyis the raw request body exactly as sent, or an empty string for GET.
401: an HTTP client that reorders keys or alters whitespace invalidates the signature.
Clock drift presents as a
401. Where auth fails intermittently under load, check NTP on the
calling machine before anything else, and raise x-noise-recv-window where latency to the API is
genuinely high.