Setting Up Banxa for Crypto On/Off-Ramp: HMAC, Webhooks, and API Integration
You're launching a crypto exchange in Latin America, but local payment methods (PIX, SPEI) aren't supported by your current on-ramp provider. Integrating each method separately takes months and requires legal approvals. Banxa solves this by providing a unified API and licenses in 100+ countries. Compared to integrating each payment method separately, Banxa saves up to 60% development time and reduces time-to-market by 50%. Below, we'll break down how to technically integrate Banxa: from HMAC authentication to webhook handling. Our team has implemented Banxa for 10+ projects — here's our proven approach.
How to Set Up Banxa Integration Turnkey?
Compliance: Banxa holds licenses in key jurisdictions (UK, Australia, Canada), reducing your regulatory burden. The provider handles KYC/AML checks, processing up to 5,000 transactions per day.
- Global coverage: Over 100 payment methods in 100+ countries — from SEPA to PIX. You get a single API without connecting each service separately. Time to enter a new region is halved on average.
- Security: HMAC authentication and signed webhooks guarantee protection against request forgery. All transactions go through a secure channel.
- Speed: Bank transfer transactions are processed in 1–2 days, card transactions instantly. Users can top up their balance quickly.
How HMAC Authentication Works in Banxa?
Banxa uses HMAC-SHA256 to authenticate every API request. The client forms a signature by concatenating the method, path, nonce (timestamp in milliseconds), and request body, then computes the HMAC. The signature is passed in the Authorization header in the format Bearer {api_key}:{nonce}:{signature}.
Python implementation using httpx
import hmac import hashlib import time import uuid import httpx class BanxaClient: def __init__(self, api_key: str, secret: str, sandbox: bool = False): self.api_key = api_key self.secret = secret self.base_url = ( "https://banxa-sandbox.com/api" if sandbox else "https://banxa.com/api" ) def _auth_header(self, method: str, path: str, body: str = "") -> str: nonce = str(int(time.time() * 1000)) payload = f"{method}\n{path}\n{nonce}\n{body}" signature = hmac.new( self.secret.encode(), payload.encode(), hashlib.sha256 ).hexdigest() return f"Bearer {self.api_key}:{nonce}:{signature}" async def get_payment_methods(self, source_currency: str = "USD") -> list: path = f"/payment-methods?source_currency={source_currency}" async with httpx.AsyncClient() as client: resp = await client.get( f"{self.base_url}{path}", headers={"Authorization": self._auth_header("GET", path)} ) return resp.json()["data"]["payment_methods"] async def create_order(self, order_data: dict) -> dict: path = "/orders" body = json.dumps(order_data) async with httpx.AsyncClient() as client: resp = await client.post( f"{self.base_url}{path}", headers={ "Authorization": self._auth_header("POST", path, body), "Content-Type": "application/json" }, content=body ) return resp.json()["data"]["order"] Creating a Buy Order
Example of creating an order to buy cryptocurrency:
async def create_buy_order( client: BanxaClient, fiat_amount: float, fiat_currency: str, crypto_currency: str, wallet_address: str, payment_method_id: int, return_url: str ) -> dict: order = await client.create_order({ "account_reference": str(uuid.uuid4()), "payment_method_id": payment_method_id, "source": fiat_currency, "source_amount": fiat_amount, "target": crypto_currency, "wallet_address": wallet_address, "return_url_on_success": return_url, "return_url_on_failure": return_url + "?status=failed", "return_url_on_cancelled": return_url + "?status=cancelled", }) return order # contains checkout_url for user redirect Webhook Handling
After transaction completion, Banxa sends a webhook to your endpoint. It's critical to verify the signature:
@app.post("/webhooks/banxa") async def banxa_webhook(request: Request): body = await request.body() signature = request.headers.get("X-Banxa-Hmac-Sha256") # Verification expected = hmac.new( BANXA_WEBHOOK_SECRET.encode(), body, hashlib.sha256 ).hexdigest() if not hmac.compare_digest(expected, signature or ""): raise HTTPException(403) data = json.loads(body) order = data["order"] status_map = { "complete": "COMPLETED", "cancelled": "CANCELLED", "declined": "FAILED", "expired": "EXPIRED", } await update_order_status( order_id=order["id"], status=status_map.get(order["status"], "UNKNOWN"), tx_hash=order.get("transaction", {}).get("hash") ) Why Choose Banxa for On/Off-Ramp?
Compared to direct P2P or connecting multiple payment gateways, Banxa wins on compliance (all transactions go through KYC/AML), breadth of coverage, and a single API. Banxa's fees range from 1.5% (SEPA) to 3.5% (cards), with an average of 2.5%. This is market-competitive but saves on legal overhead. Integrating Banxa cuts time to enter new regions by half. For example, launching in Brazil requires just one API call, not negotiations with local banks. Additionally, Banxa processes over 10 million transactions annually, ensuring reliability at scale.
Comparison of Payment Methods
| Method | Region | Speed | Fee |
|---|---|---|---|
| SEPA | EU | 1-2 days | from 1.5% |
| Visa/MasterCard | Global | Instant | from 3.0% |
| PIX | Brazil | Instant | from 2.5% |
| SPEI | Mexico | Instant | from 2.5% |
| Interac | Canada | Instant | from 2.0% |
How to Integrate Banxa: Step-by-Step Plan
- Analysis: Determine target payment methods, countries, legal requirements. Banxa covers 90% of popular regions out of the box.
- Design: Design webhook architecture, order processing schema. Use the Observer pattern for notifications.
- Implementation: Write API integration, webhook handling, test in sandbox. Correctly handle nonce and signatures.
- Testing: Cover HMAC with unit tests, order lifecycle scenarios. Simulate all statuses from the table below.
- Deployment: Configure production endpoint, monitoring, support. First week — monitor for errors.
Order Status Table
| Status | Description | Action |
|---|---|---|
| complete | Purchase completed | Credit cryptocurrency to user |
| cancelled | User cancelled | Redirect to method selection |
| declined | Payment declined by bank | Offer another payment method |
| expired | Session expired | Delete order |
What's Included in the Service
- API documentation and webhook schemas
- Test access to sandbox environment
- Handling of all order statuses
- Team training on Banxa operations
- Technical support during launch phase
Troubleshooting Common Issues
- Incorrect HMAC signature: Verify that nonce is timestamp in milliseconds and request body is transmitted unchanged. Banxa requires the exact payload.
- Missing status handling: Always handle expired and declined statuses — otherwise users may lose funds.
- Incorrect return_url: Ensure the URL is externally accessible and correctly handles all three cases (success, failure, cancel).
- Forgotten nonce: Each request must have a unique nonce; otherwise, Banxa will reject it as duplicate.
Contact us for a consultation. Order a turnkey Banxa integration — just send us a message. We'll evaluate your project in 1-2 days and propose an optimal architecture. We guarantee quality at every stage: from the first commit to production. Certified blockchain developers with over 5 years of experience have implemented Banxa for 10+ projects. Get a consultation today.
Detailed API specification is available on official Banxa website. We use it in every integration, ensuring compliance with the latest updates. Integrating Banxa can save you up to $50,000 in legal fees per new market entry.







