Skip to content
Last updated

Authentication

For the complete documentation index, see llms.txt. Append .md to any page URL for its markdown version.

Quick summary

  • Auth type: HMAC-SHA256
  • Header: Authorization: Bearer API_KEY:SIGNATURE:NONCE
  • Nonce: Unix timestamp in microseconds (16 digits), unique per request
  • Signature: Hex-encoded HMAC-SHA256 of a newline-separated canonical string

Important notice on Native API access

The Native API is not enabled by default and is not self-serve. Access is granted per account under a signed agreement with Banxa that covers headless integration.

Integrating the Native API without a signed agreement will lead to delays going live.

If you do not have Native API enabled in the Partner Dashboard, contact your Banxa Account Manager to enquire about our approval process.


Base URL

EnvironmentBase URL
Sandboxhttps://api.banxa-sandbox.com/eapi/v0/
Productionhttps://api.banxa.com/eapi/v0/

Authorization header

Every request must include:

Authorization: Bearer API_KEY:SIGNATURE:NONCE
ComponentDescription
API_KEYPublic API key provided during onboarding
SIGNATUREHex-encoded HMAC-SHA256 signature
NONCEUnix timestamp in microseconds (16 digits)

Building the signature

Construct a newline-separated canonical string, then sign it with HMAC-SHA256 using your API secret.

GET request:

METHOD\nPATH_WITH_QUERY_STRING\nNONCE

POST request:

METHOD\nPATH\nNONCE\nCOMPACT_JSON_BODY

Rules:

  • Use the request path only — never the full URL with domain
  • Include the query string in the path for GET requests
  • JSON body must be compact — no whitespace between elements
  • Generate a new nonce for every request
Nonce precision

Use microseconds (16 digits). Seconds (10 digits) and milliseconds (13 digits) are also accepted, but millisecond precision causes nonce collisions under concurrent load: two requests generated in the same millisecond produce the same nonce, and the second is rejected as reused (40003).

Generate the nonce from a clock with genuine sub-millisecond resolution. Multiplying a millisecond timestamp by 1000 pads it to 16 digits without adding precision and does not prevent collisions.

Examples:

GET\n/eapi/v0/price\n1785804345837761

POST\n/eapi/v0/ramps\n1785804345837761\n{"identityReference":"example_01"}

Code examples

import hmac
import time

key = '[YOUR_API_KEY]'
secret = '[YOUR_API_SECRET]'

def generate_hmac(method, path, payload=None):
    nonce = str(int(time.time() * 1_000_000))
    parts = [method, path, nonce]
    if payload:
        parts.append(payload)
    data = '\n'.join(parts)
    signature = hmac.new(secret.encode('utf-8'), data.encode('utf-8'), 'sha256').hexdigest()
    return f'{key}:{signature}:{nonce}', nonce

Authentication errors

CodeCause
40001Nonce is not a valid Unix timestamp — must be 10, 13, or 16 digits (seconds, milliseconds, or microseconds)
40002Nonce is too old — check your system clock is in sync
40003Nonce already used — generate a new nonce per request
40100API key not recognised — check you are using the correct environment key
40101Authorization header is malformed — format must be Bearer API_KEY:SIGNATURE:NONCE
40102Authorization header is missing
40103Signature mismatch — check path, newline separators, compact JSON, and correct secret

Best practices

  • Generate a new nonce for every request
  • Use microsecond precision for the nonce — millisecond timestamps collide under concurrent load
  • Keep your system clock in sync (NTP)
  • Always serialize JSON with no whitespace before signing
  • Use the request path only — never the full URL with domain
  • Log the request_id from error responses for debugging

If issues persist, contact your Banxa Account Manager.