API Documentation
Everything you need to integrate crypto payments into your application. Bitfra Test is a self-hosted, multi-chain payment gateway — no intermediaries, no platform fees.
Introduction
Base URL
All API calls are made to your Bitfra Test instance. Use the sandbox URL during development and switch to production for live traffic.
# Production
https://bixmerchant.com/api/v1/payments
# Sandbox (for testing)
https://sandbox.bixmerchant.com/api/v1/payments
Environments
Bitfra Test runs in two separate environments. Use the Sandbox for integration testing — it only supports testnet tokens (Sepolia ETH, etc.) and no real funds move. Switch to Production when you're ready to accept real payments.
| Production | Sandbox | |
|---|---|---|
| URL | https://bixmerchant.com |
https://sandbox.bixmerchant.com |
| Networks | Bitcoin, Ethereum, LTC, BSC, Polygon, TRON | Sepolia (Ethereum testnet) only |
| Funds | Real cryptocurrency — sent to your wallet | Testnet coins — no monetary value |
| API Keys | Generated on production dashboard | Generated on sandbox dashboard — not interchangeable |
| Registration | bixmerchant.com/register | sandbox.bixmerchant.com/register |
| Purpose | Live payments from real customers | Build and test your integration before going live |
Authentication
Generate an API key from the Developers page in your dashboard. Pass it via the X-API-Key header:
X-API-Key: bix-xxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx
REST API POST
Create a payment request with a single API call. The customer receives an email with a payment link where they choose their preferred cryptocurrency.
Endpoint
POST https://test.bitfra.net/api/v1/payments
Request
curl -X POST https://test.bitfra.net/api/v1/payments \
-H "X-API-Key: bix-xxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 49.99,
"email": "customer@example.com",
"note": "Order #1234"
}'
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| amount | number | Yes | Amount in USD (e.g. 49.99). Minimum 0.00000001 |
| string | Yes | Customer's email — receives the payment link | |
| note | string | No | Optional note or order reference (max 500 chars) |
Response 201 Created
{
"payment_id": "pay_m77jheovz6euejk145te36fo",
"payment_link": "https://test.bitfra.net/payments/pay_m77jheovz6euejk145te36fo",
"status": "PENDING",
"expires_at": "2026-06-06T14:30:00Z"
}
Check Payment Status GET
GET https://test.bitfra.net/api/v1/payments/{payment_id}
Response 200 OK
{
"payment_id": "pay_m77jheovz6euejk145te36fo",
"amount": 49.99,
"amount_usd": 49.99,
"chain": "SEPOLIA",
"address": "0x1679d7...6271382e",
"status": "PAID",
"tx_id": "btx_123456789",
"tx_amount": 0.20603780,
"created_at": "2026-06-06T12:00:00+00:00",
"expires_at": "2026-06-06T14:00:00+00:00",
"updated_at": "2026-06-06T12:05:30+00:00"
}
List Payments GET
GET https://test.bitfra.net/api/v1/payments
GET https://test.bitfra.net/api/v1/payments?status=PAID&per_page=50
Response 200 OK
{
"data": [
{
"payment_id": "pay_...",
"amount": 49.99,
"amount_usd": 49.99,
"chain": "ETH",
"status": "PAID",
"created_at": "2026-06-06T12:00:00+00:00",
"expires_at": "2026-06-06T14:00:00+00:00"
}
],
"meta": {
"current_page": 1,
"last_page": 3,
"per_page": 25,
"total": 67
}
}
Cancel Payment POST
POST https://test.bitfra.net/api/v1/payments/{payment_id}/cancel
Response 200 OK
{
"payment_id": "pay_m77jheovz6euejk145te36fo",
"status": "CANCELLED",
"message": "Payment cancelled."
}
Store Info GET
Get your store's current configuration — accepted tokens, status, and currency.
GET https://test.bitfra.net/api/v1/store
Response 200 OK
{
"store_id": "BIX_ST1219113445631461",
"name": "My Store",
"status": "ACTIVE",
"currency": "USD",
"tokens": ["ETH", "BTC", "SEPOLIA_ETH"],
"created_at": "2026-05-01T10:00:00+00:00"
}
Direct URL GET
Generate a payment link instantly — no API key, no code. Just construct a URL. Ideal for checkout buttons, email campaigns, or manual invoicing.
URL Path Format
https://test.bitfra.net/pay/{storeId}/{amount}
Query Parameter Format
https://test.bitfra.net/pay/{storeId}?amount=30&email=customer@example.com
Embed in an Anchor Tag
<a href="https://test.bitfra.net/pay/BIX_ST.../30">
Pay $30 with crypto
</a>
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| storeId | string | Yes | Your store ID (e.g. BIX_ST1219113445631461) — found in store settings |
| amount | number | Yes | Amount in USD |
| string | No | Customer email (query param only) | |
| note | string | No | Order reference (query param only) |
HTML Form POST
Drop a plain HTML form on any page. The customer is redirected to the crypto checkout automatically. No JavaScript required.
<form method="POST" action="https://test.bitfra.net/pay/BIX_ST...">
<label>Amount (USD)</label>
<input type="number" name="amount"
step="0.01" required />
<label>Email (optional)</label>
<input type="email" name="email" />
<button type="submit">Pay with Crypto</button>
</form>
Form Fields
| Field | Type | Required | Description |
|---|---|---|---|
| amount | number | Yes | Amount in USD |
| string | No | Customer email for payment notification | |
| note | string | No | Order reference or memo |
API Keys
API keys authenticate your server-to-server requests. Generate them from the Developers page in your dashboard.
Key Format
bix-xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys use the bix- prefix followed by two 28-character hex segments. The full key is shown only once at generation time — store it securely.
Passing the Key
Include the API key in the X-API-Key header on every request:
X-API-Key: bix-xxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx
Webhooks
Receive real-time payment status updates at your server. Configure a webhook URL from the Developers page when generating an API key.
Events
| Event | Description | Trigger |
|---|---|---|
| payment.paid | Blockchain payment detected | Incoming transaction received from network |
| payment.completed | Payment fully confirmed | Transaction meets confirmation threshold |
| payment.expired | Payment window closed | Timer ran out — customer did not pay |
| payment.cancelled | Payment cancelled | Customer or admin cancelled the payment |
Payload
All events include these fields plus event-specific data:
{
"event": "payment.paid",
"payment_id": "pay_m77jheovz6euejk145te36fo",
"store_id": "BIX_ST1219113445631461",
"amount": 0.20603780,
"amount_usd": 322.00,
"chain": "SEPOLIA",
"address": "0x1679d7...6271382e",
"status": "PAID",
"updated_at": "2026-06-06T14:30:00+00:00"
}
Verifying Signatures
Every webhook request includes an X-Bixmerchant-Signature header. Verify it to ensure the request came from Bitfra Test and wasn't tampered with.
Header Format
X-Bixmerchant-Signature: t=1719345678,v1=abc123def456...
PHP Verification
// 1. Parse the header
preg_match('/t=(\d+),v1=(\S+)/', $_SERVER['HTTP_X_BIXMERCHANT_SIGNATURE'], $matches);
$timestamp = $matches[1];
$received = $matches[2];
// 2. Recompute the signature
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', "{$timestamp}.{$body}", $yourWebhookSecret);
// 3. Compare
if (!hash_equals($expected, $received)) {
http_response_code(400);
die('Invalid signature');
}
http_response_code(200);
JavaScript / Node.js Verification
const crypto = require('crypto');
// 1. Parse header
const [, timestamp, received] = req.headers['x-bixmerchant-signature']
.match(/t=(\d+),v1=(\S+)/);
// 2. Recompute
const raw = JSON.stringify(req.body);
const expected = crypto.createHmac('sha256', secret)
.update(`${timestamp}.${raw}`)
.digest('hex');
// 3. Compare
if (expected !== received) return res.status(400).send('Bad signature');
res.status(200).send('OK');
Retry Policy
If your server returns a non-2xx response, Bitfra Test retries up to 3 times with exponential backoff: 10 seconds → 1 minute → 5 minutes. You can also manually retry failed deliveries from the Developers page.
Testing
When saving a webhook URL, use the Test button to send a test.handshake event. Your server will receive:
{
"event": "test.handshake",
"timestamp": "2026-06-06T12:00:00+00:00",
"data": { "message": "Bixmerchant webhook test — connection successful." }
}
Response Codes
| Code | Meaning |
|---|---|
| 200 | OK — request succeeded (status check, list, cancel, store info) |
| 201 | Created — payment generated successfully |
| 400 | Bad Request — missing or invalid parameters |
| 401 | Unauthorized — invalid or missing API key |
| 403 | Forbidden — store is disabled and not accepting payments |
| 404 | Not Found — payment or store does not exist |
| 422 | Unprocessable — validation failed or payment cannot be cancelled |
| 429 | Too Many Requests — rate limit exceeded |
| 500 | Server Error — something went wrong on our side |
Rate Limits
The API is rate-limited to prevent abuse. Limits are applied per API key:
| Limit | Window | Applies To |
|---|---|---|
| 2FA Resend | 3 per 5 minutes | Login verification code resend |
| Webhook Test | Unlimited | Test handshake endpoint |
If you exceed the rate limit, you'll receive a 429 Too Many Requests response. The Retry-After header tells you how many seconds to wait.