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.

ProductionSandbox
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
Start in the SandboxCreate a sandbox account, generate testnet API keys, and build your integration without risking real funds. Switch the base URL to production when you're ready.

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

FieldTypeRequiredDescription
amountnumberYesAmount in USD (e.g. 49.99). Minimum 0.00000001
emailstringYesCustomer's email — receives the payment link
notestringNoOptional 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

ParameterTypeRequiredDescription
storeIdstringYesYour store ID (e.g. BIX_ST1219113445631461) — found in store settings
amountnumberYesAmount in USD
emailstringNoCustomer email (query param only)
notestringNoOrder 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

FieldTypeRequiredDescription
amountnumberYesAmount in USD
emailstringNoCustomer email for payment notification
notestringNoOrder 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
Security Note — Never expose your API key in client-side code. Always make API calls from your backend. Use the HTML Form or Direct URL methods for browser-facing integrations.

Webhooks

Receive real-time payment status updates at your server. Configure a webhook URL from the Developers page when generating an API key.

Events

EventDescriptionTrigger
payment.paidBlockchain payment detectedIncoming transaction received from network
payment.completedPayment fully confirmedTransaction meets confirmation threshold
payment.expiredPayment window closedTimer ran out — customer did not pay
payment.cancelledPayment cancelledCustomer 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 seconds1 minute5 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

CodeMeaning
200OK — request succeeded (status check, list, cancel, store info)
201Created — payment generated successfully
400Bad Request — missing or invalid parameters
401Unauthorized — invalid or missing API key
403Forbidden — store is disabled and not accepting payments
404Not Found — payment or store does not exist
422Unprocessable — validation failed or payment cannot be cancelled
429Too Many Requests — rate limit exceeded
500Server Error — something went wrong on our side

Rate Limits

The API is rate-limited to prevent abuse. Limits are applied per API key:

LimitWindowApplies To
2FA Resend3 per 5 minutesLogin verification code resend
Webhook TestUnlimitedTest 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.