# Authentication ## Quick summary - **Auth type:** HMAC-SHA256 - **Header:** `Authorization: Bearer API_KEY:SIGNATURE:NONCE` - **Nonce:** Unix timestamp (ms), unique per request - **Signature:** Hex-encoded HMAC-SHA256 of a newline-separated string ### String to sign ```text POST /eapi/v0/ramps 1741220905019 {"subPartnerId":null,"identityReference":"926553-1732538-7235638-6352926","source":{"crypto":{"id":"USDT","blockchain":"ETH","walletAddress":"0xc292474673cf1a96a96e8c56ec4f45ecf2e0b448","walletAddressMemo":null},"amount":"100"},"target":{"fiat":{"id":"AUD","method":"payid-bank-transfer","instructions":{"accountName":"Foo Bar","accountNumber":"12345678","bsb":"063123"}}}}} ``` ## Base URL All requests must be sent to: > [https://api.banxa.com/eapi/v0/](https://api.banxa.com/eapi/v0/) Authentication is handled exclusively via your API key and secret. ## Authorization Header Every request must include the following header: `Authorization: Bearer API_KEY:SIGNATURE:NONCE` - **API_KEY**: Public API key provided during onboarding - **SIGNATURE**: Hex-encoded HMAC-SHA256 signature - **NONCE**: Unix timestamp in milliseconds ## Building the Signature The signature is generated from a newline-separated string: 1. HTTP method (`GET`, `POST`) 2. Request path **including query string if present** 3. Nonce (Unix timestamp in ms) 4. JSON body *(POST requests only, compact, no whitespace)* **Examples**: ``` 'GET' + '\n' + '/eapi/v0/price' + '\n' + '1612391416' 'POST' + '\n' + '/eapi/v0/ramps' + '\n' + '1612391416' + '\n' + '{"identityReference":"example_01"}' ``` ## Sample Code Below is a Python example. ``` PythonJavaPHPNode.jsSwiftRuby import requests import time import hmac url = 'https://api.banxa-sandbox.com/eapi/v0/ramps' key = '[YOUR_MERCHANT_KEY]' secret = '[YOUR_MERCHANT_SECRET]' def generateHmac(payload, nonce): hmacCode = hmac.digest(secret, payload.encode('utf8'), 'SHA256') print(payload) print(hmacCode.hex()) return key + ':' + hmacCode.hex() + ':' + str(nonce) ``` ## Common Authentication Errors | Code | Error message | Likely cause / fix | | --- | --- | --- | | 40001 | Invalid nonce | Nonce is not a valid timestamp | | 40002 | Expired nonce | System clock out of sync | | 40003 | Nonce reused | Generate a new nonce per request | | 40100 | Invalid API key | Wrong key or environment | | 40101 | Malformed header | Must be `Bearer API_KEY:SIGNATURE:NONCE` | | 40102 | Missing header | Authorization header not sent | | 40103 | Signature mismatch | Check path, newlines, JSON compaction | ## Best Practices - Generate a **new nonce for every request** - Keep your system clock in sync (e.g. NTP) - Always sign **compact JSON** - Use the **request path only** (never the full URL) - Log `request_id` from error responses for debugging If issues persist, contact your Banxa Account Manager.