Skip to main content
Every API request must include your API key and a freshness proof — either a plain timestamp or a signed one: Which endpoints require the signature:
  • Missing/invalid x-api-key401 Unauthorized.
  • Missing/malformed x-timestamp (with no x-signature), or a value outside the ±5-minute window → 400 Bad Request ("Request timestamp outside valid window (5 minutes)").
  • Missing or invalid x-signature on a disbursement endpoint → 401 Unauthorized.
  • Holding clients cannot use the payment/payout API → 403 Forbidden.

Signing a request

Signing uses your Signing Secret — a 64-character hex string issued with your API credentials (view it in the dashboard under API credentials; regenerating credentials rotates it together with your API key and Callback Secret).
  1. Serialize your request data once to JSON — call the result body. For GET requests, body is the empty string.
  2. Take the current Unix time in milliseconds, as a string — call it t.
  3. Build the payload to sign: payloadToSign = t + "." + body
  4. Compute HMAC_SHA256( payloadToSign, SigningSecret ) and encode it as lowercase hex — call it sig.
  5. Send the header x-signature: t=<t>,v1=<sig> — and send the same body string as the HTTP body. Do not re-serialize it; the server verifies the exact bytes it receives.
Signed requests must not use Content-Encoding (compression), and the body is capped at 1 MiB. The t in the signature must be within ±5 minutes of server time — reuse the same t in the signed payload and the header.

Testing your signature

POST /api/v3/debug/signature-check Runs the exact same verification pipeline as the enforcing endpoints, but always returns 200 with a field-by-field diagnostic instead of an opaque 401. Use it to validate your signing implementation before calling business endpoints. It never takes any business action, whatever the payload. Send any JSON body, signed exactly as you would a real request (only x-api-key is required; omitting x-signature is allowed and reports missing_signature_header):

Response

For security, the response never includes the server-computed signature — you hold the secret, so recompute HMAC_SHA256( signed_payload_string, SigningSecret ) locally and compare it with your own v1. The endpoint is rate-limited to 20 requests/minute per client (429 beyond that).