Documentation

Payment API

Create checkout links with your API key.

Programmatically create checkout links on api.firewallet.sh, share them with customers on pay.firewallet.sh, and receive signed webhooks when payments are created or updated.

Base URL

https://api.firewallet.sh

All endpoints live under /api/v1/.

Authentication

Every request must include your account API key:

Authorization: Bearer fw_xxxxxxxx

Generate or rotate the key in Settings → API. Keys start with fw_. Store them securely; the full key is only shown once when rotated.

Invalid or missing keys return 401 with code UNAUTHORIZED.

Endpoints

Method Path Description
GET /api/v1/payments List your API-created payments
POST /api/v1/payments Create a payment checkout
GET /api/v1/payments/:id Get one payment by numeric id
PATCH /api/v1/payments/:id Update amount, methods, metadata, or webhook

Successful responses use the standard Firewallet JSON envelope (success: true, data: { ... }).

Create a payment

POST /api/v1/payments

{
  "amount": 42.5,
  "devis": "eur",
  "whitelabel": false,
  "paymentMethods": ["tron"],
  "data": {
    "orderId": "ORD-1001",
    "customerEmail": "buyer@example.com"
  },
  "webhook": "https://your-app.example/webhooks/firewallet"
}

Request fields

Field Required Description
amount yes Fiat amount (positive number, rounded to 2 decimals)
devis yes eur or usd
whitelabel yes true = customer picks a coin on checkout; false = exactly one paymentMethods entry
paymentMethods yes Asset ids with an active receive address on your account (see below)
data no String key-value metadata echoed in API responses and webhooks
webhook no HTTPS URL for payment lifecycle events
webhookSecret no Your signing secret (16–64 chars). If webhook is set and this is omitted, Firewallet generates wh_... and returns it once in the response
successRedirectUrl no HTTPS URL for non-whitelabel checkouts. After on-chain confirmation, the payer is redirected here from the pay page

Payment method ids

Use the asset id from your wallet (same ids as the dashboard):

  • bitcoin (BTC)
  • litecoin (LTC)
  • ethereum (ETH)
  • usdt_erc20 (USDT on Ethereum)
  • tron (TRX)
  • usdt_trc20 (USDT on Tron)
  • solana (SOL)
  • monero (XMR)

Each method must map to an available API wallet slot for that asset. Otherwise the API returns 400 with INVALID_PAYMENT.

Confirmed API payments follow the same automatic swap rules as dashboard deposits when automation is enabled under Payment settings (toMonero). Funds on API wallet slots (BTC, LTC, and other supported inbound coins) are converted to Monero once they pass your EUR threshold. Monero API deposits are already XMR and skip the inbound swap; outbound routing still applies from your shield settings. Open payments are never swapped until they confirm or expire.

Whitelabel vs single-method

  • whitelabel: false — paymentMethods must contain exactly one id. Checkout shows that coin only.
  • whitelabel: true — paymentMethods may list several ids. The customer chooses one on the pay page.

Example response

{
  "success": true,
  "data": {
    "payment": {
      "id": 12,
      "slug": "pl_xYz123",
      "amount": 42.5,
      "devis": "eur",
      "whitelabel": false,
      "paymentMethods": ["tron"],
      "data": { "orderId": "ORD-1001" },
      "webhook": "https://your-app.example/webhooks/firewallet",
      "checkoutUrl": "https://pay.firewallet.sh/pl_xYz123",
      "status": "pending",
      "timeLeftSeconds": 3600,
      "detectionTimeLeftSeconds": 1800,
      "paidCoinId": null,
      "paidAmount": null,
      "paidTxId": null,
      "confirmations": null,
      "successRedirectUrl": "https://your-app.example/payment/success",
      "createdAt": 1710000000000,
      "updatedAt": 1710000000000
    },
    "webhookSecret": "wh_a1b2c3d4e5f6..."
  }
}
`

Share `checkoutUrl` with the payer. API-created links use the same neutral public slug style as regular payment links.

## Update a payment

`PATCH /api/v1/payments/:id`

Send only fields you want to change. The same validation rules apply (for example, non-whitelabel payments still require exactly one payment method when `paymentMethods` is sent).

Updating a payment triggers a `payment.updated` webhook when a webhook URL is configured.

## List and get

- `GET /api/v1/payments` — returns `{ payments: [...] }` for the authenticated account.
- `GET /api/v1/payments/:id` — returns `{ payment }` or `404 NOT_FOUND`.

## Webhooks

When `webhook` is set on create or update, Firewallet sends a `POST` with JSON body:

```json
{
  "event": "payment.created",
  "payment": { "...": "same shape as API payment object" },
  "emittedAt": 1710000000000
}

Events:

Event When
payment.created Payment request created
payment.updated Payment fields updated via API
payment.detected Incoming funds detected (mempool or unconfirmed)
payment.confirmed Payment confirmed on-chain
payment.expired No payment detected within 30 minutes, or not confirmed before the 60-minute window ends

The backend watches allocated API wallet addresses for up to 60 minutes. The payer UI waits up to 30 minutes for first detection, then shows a confirmation state until the payment is confirmed or expires.

Headers

Header Meaning
X-Firewallet-Event Event name
X-Firewallet-Signature Hex HMAC-SHA256 of the raw body using your webhookSecret
X-Firewallet-Delivery Unique delivery id (for logging)

Verify the signature

Compute HMAC-SHA256 of the raw request body with your webhookSecret and compare it to X-Firewallet-Signature (use a constant-time compare).

Node.js example:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verifyFirewalletWebhook(rawBody, headers, secret) {
  const signature = headers['x-firewallet-signature'];
  if (!signature) return false;

  const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(signature);
  const b = Buffer.from(expected);
  return a.length === b.length && timingSafeEqual(a, b);
}

Use the raw request body bytes (before JSON parsing) when verifying.

Webhook delivery is best-effort: failed HTTP calls do not roll back the payment operation.

Errors

HTTP Code Typical cause
401 UNAUTHORIZED Missing or invalid API key
400 INVALID_PAYMENT Validation failed (amount, methods, missing address, etc.)
404 NOT_FOUND Unknown payment id
422 — Request body failed schema validation

Dashboard vs automation API

Dashboard (firewallet.sh) Automation API (api.firewallet.sh)
Auth Session cookie Authorization: Bearer API key
Creates Payment links in the UI Same underlying payment links, via JSON
Checkout pay.firewallet.sh/{slug} Same pay site; API returns checkoutUrl

The internal session API under firewallet.sh/api/account/payment-links is separate from this external automation API.

Quick test with curl

curl -sS -X POST 'https://api.firewallet.sh/api/v1/payments' \
  -H 'Authorization: Bearer fw_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "amount": 10,
    "devis": "eur",
    "whitelabel": false,
    "paymentMethods": ["tron"]
  }'