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, URL-decoded (see Query strings)
  • 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"}

Query strings

Banxa URL-decodes the query string before it checks the signature, so sign the decoded form. Send the URL itself encoded as normal.

You sendYou sign
/eapi/v0/identities/customer-123?email=user%40example.com/eapi/v0/identities/[email protected]

In the query string:

In the URL you sendIn the string you sign
%40@
%20 or +a space
%2B+

Only the query string is decoded. Sign the path before the ? exactly as you send it. If you sign the encoded query string, any request with an encoded character in it fails with 401.

In the code examples below, pass the path and the decoded query string as path.


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.