Authentication

HMAC-SHA256 signing rules, nonce-based replay protection, and the three credentials you receive at onboarding.

Every authenticated request carries three headers: X-API-KEY, X-API-SIGN, X-API-NONCE. Sign the exact bytes you send — that’s the whole rule. Same in bash, Python, Node; see the worked example below, or jump to the signing template.

Required headers

HeaderRequiredDescription
X-API-KEYYesPublic partner key. May carry an optional code segment: apiKey.codeName— see /api/v1/codes.
X-API-SIGNYesHex signature of the raw request body, keyed by your apiSecret. The recipe is in the worked example below.
X-API-NONCEYesUnique per request (UUID or 16-byte hex). Reusing a nonce returns code 3 AUTH_INVALID.

Signing rules

  • Sign the exact bytes you put on the wire.
  • For GET /api/v1/codes the request has no body. Sign the empty string "": same HMAC primitive, zero input bytes. DELETE /api/v1/codes carries a JSON body {"code":"<code>"}. Sign that exact body, not the empty string.
  • Bad signature, unknown key, replayed nonce, and malformed envelope all collapse to the same response: { code: 3, msg: "AUTH_INVALID" }. You learn whether you got in, never which check failed.

Replay protection

Nonces are tracked server-side. Use a fresh random value per request, 16 to 64 characters. A UUID without hyphens is 32; with hyphens, 36; 64-char hex is also valid. Reuse, under-16, or over-64 all return { code: 3, msg: "AUTH_INVALID" }. There is no timestamp header; caller and server clocks are never compared.

Unauthenticated endpoints

/api/v1/currencies, /api/v1/pairs, and /api/v1/price accept unsigned requests for catalog and un-attributed quoting. Unsigned traffic runs on a separate public bucket and never charges a partner budget. Signed /api/v1/price calls receive partner-specific markup. Public limits are on the Rate limits page.

End-to-end example

POST /api/v1/price in three languages. The signature is computed over the exact JSON body bytes you send.

# Request a quote for 0.01 BTC -> USDT (Tron) with a 0.5% partner markup.
APIKEY="rWqZ...your-api-key...Rg"
APISECRET="G1JV...your-api-secret...n4"
NONCE=$(openssl rand -hex 16)
BODY='{"type":"float","fromCcy":"btc","toCcy":"usdt_trc20","direction":"from","amount":"0.01","afftax":50}'
SIGN=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$APISECRET" | sed 's/^.* //')

curl -sS -X POST "https://0trace.io/api/v1/price" \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: $APIKEY" \
  -H "X-API-SIGN: $SIGN" \
  -H "X-API-NONCE: $NONCE" \
  --data "$BODY"

Common mistakes

  • Re-serialising the body before sending. If your HTTP client pretty-prints or sorts keys before transmission, the body on the wire differs from the bytes you signed. Always sign the exact bytes you POST.
  • Mixing keys across requests. The X-API-KEY header and the secret you HMAC with are a pair, issued together at onboarding. The header itself is not part of the HMAC input; only the raw request body is. Use the apiSecret that was provisioned alongside the apiKey you send.
  • Stale, short, or oversized nonces. Generate a fresh random nonce per request, 16–64 characters inclusive. Reusing a value, sending an empty or under-16-character nonce, or sending an over-64-character nonce all return the same X-API-NONCE AUTH_INVALID envelope.

Credential provisioning

You get three secrets, and they are always available in your cabinet — reveal them whenever you need:

Your credential bundle
{
  "apiKey": "rWqZ...your-public-key...Rg",
  "apiSecret": "G1JV...your-signing-secret...n4",
  "webhookSecret": "Lh2P...your-webhook-secret...8K"
}

Need a fresh secret? Contact us and we'll issue a new one — the previous value is invalidated immediately on our side.

Partner API.
Same engine as 0trace.

A private partner integration surface. Signed quotes, server-side pricing, webhook delivery, multiple reference codes, and a self-serve cabinet — all backed by the production exchange engine.

Need help?

Questions? Answers.

A partner integration surface on top of the same exchange engine that powers 0trace.io. You connect with a signed REST contract, query quotes, open orders, and receive webhook notifications. Our liquidity, our pricing, our payouts. You focus on your product.
No. The API is private and invite-only, aligned with the privacy posture of 0trace itself. There is no KYC, no identity collection, and no source-of-funds reporting required of partners or their end users.
Submit a request through our partner application form at 0trace.io/api/contact-sales and we’ll reply within three business days.
Traffic is encrypted in transit (TLS). Every request is signed with HMAC-SHA256 over the exact request body bytes and gated by a nonce-based replay window. Pricing, fees, and payout amounts are computed server-side. Payouts run on an isolated service that re-verifies each transfer against the on-chain deposit before broadcasting.
A per-partner sliding-window weight budget, default 2500 wu/min (≈50 creates/minute). Endpoint weights: /api/v1/create is 50, /api/v1/qr is 5, every other endpoint is 1. XML feeds run on a separate public bucket. Exceeding the budget returns 429 with a Retry-After header. To raise your cap, send your projected per-endpoint call rate to your operator contact.
Two ways to earn. Revenue share: send us traffic with your referral link and earn a share of our service fee on every order — the visitor sees our live rate. Markup: integrate through the API and add your own margin on top of our rate, shown in your own interface. Use either, or both.
Yes. 0trace operates its own liquidity pool across every supported asset and network. Quotes are recomputed server-side at order creation against the live feed. Payouts are direct, with no third-party intermediary.
Bitcoin, Ethereum, BSC, Solana, Tron, Monero, and Arbitrum One — covering native coins plus the major stablecoins on each network (USDT, USDC, USDC.e).
Yes. We push signed events for order.status_changed and partner.paid_out; you subscribe to the ones you want in your cabinet.

Follow us on X for the latest updates.

Subscribe