Skip to content

Developer Guide

Receiving (BTC Line of Credit)

Receiving Payments with Bitcoin Line of Credit

Section titled “Receiving Payments with Bitcoin Line of Credit”

This guide explains how to receive Lightning, on-chain Bitcoin, and BIP21 unified payments into a BTC-denominated wallet using the Voltage Payments API.

  • A Voltage account with an active BTC wallet (wallet associated with a Bitcoin line of credit)
  • An Environment API key (x-api-key) from your dashboard

Receiving a payment is a two-step process:

  1. Create a receive payment request (invoice/address/URI)
  2. Retrieve the payment to get the invoice details and monitor status
{
"amount": 150000,
"currency": "btc",
"unit": "msats"
}

BTC amounts use millisatoshis (msats) as the smallest unit.

Legacy fields amount_msats and amount_sats are still accepted but deprecated. Prefer the amount object.

  • bolt11 – Lightning invoice
  • onchain – On-chain Bitcoin address
  • bip21 – Unified BIP21 URI (on-chain + optional Lightning)
  • taprootasset – Taproot Asset invoice (not covered in this guide)
  • generating – Invoice/address is being created
  • receiving – Invoice/address created and waiting for payment
  • completed – Fully received and credited
  • expired – Invoice expired before being paid
  • failed – Could not be generated or completed
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments
x-api-key: your-api-key
Content-Type: application/json

Receive a Fixed-Amount Lightning (BOLT11) Payment

Section titled “Receive a Fixed-Amount Lightning (BOLT11) Payment”
Terminal window
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments' \
--request POST \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
"id": "11ca843c-bdaa-44b6-965a-39ac550fcef7",
"wallet_id": "{wallet_id}",
"currency": "btc",
"payment_kind": "bolt11",
"amount": {
"amount": 150000,
"currency": "btc",
"unit": "msats"
},
"description": "test payment",
"expiration": 3600
}'
  • id – Your unique idempotent ID (UUID recommended)
  • wallet_id – Wallet that will receive funds
  • currency – “btc” (must match the wallet’s currency)
  • payment_kind – “bolt11”
  • amount – Amount object for the requested amount
  • description – Memo/description (appears as memo in the response)
  • expiration – Invoice expiry in seconds (default: 3600, max: 86400 for Lightning)

Receive a Lightning Invoice with Any Amount

Section titled “Receive a Lightning Invoice with Any Amount”

BTC wallets support “pay any amount” invoices. Simply omit the amount field:

Terminal window
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments' \
--request POST \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
"id": "b3e12e2f-5e80-4fb6-9c37-0a2d9af6c1f0",
"wallet_id": "{wallet_id}",
"currency": "btc",
"payment_kind": "bolt11",
"description": "donation (any amount)",
"expiration": 3600
}'

Creates a new on-chain address and tracks the payment:

Terminal window
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments' \
--request POST \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
"id": "11ca843c-bdaa-44b6-965a-39ac550fcef8",
"wallet_id": "{wallet_id}",
"currency": "btc",
"payment_kind": "onchain",
"amount": {
"amount": 150000000,
"currency": "btc",
"unit": "msats"
},
"description": "on-chain deposit"
}'

The response will include:

  • A Bitcoin address in data.address
  • data.receipts entries as the transaction confirms

Receive a BIP21 Unified Payment (On-Chain + Lightning)

Section titled “Receive a BIP21 Unified Payment (On-Chain + Lightning)”

Creates a BIP21 URI that can embed both an on-chain address and a Lightning invoice:

Terminal window
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments' \
--request POST \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
"id": "11ca843c-bdaa-44b6-965a-39ac550fcef9",
"wallet_id": "{wallet_id}",
"currency": "btc",
"payment_kind": "bip21",
"amount": {
"amount": 150000,
"currency": "btc",
"unit": "msats"
},
"description": "Payment for services",
"expiration": 3600
}'

The resulting data will include:

  • payment_request (optional BOLT11)
  • address (BTC address)
  • receipts for completed on-chain or Lightning parts
GET https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}
Terminal window
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}' \
--header 'x-api-key: your-api-key'
{
"direction": "receive",
"id": "11ca843c-bdaa-44b6-965a-39ac550fcef7",
"wallet_id": "{wallet_id}",
"organization_id": "{organization_id}",
"environment_id": "{environment_id}",
"created_at": "2025-02-12T20:16:14.095785Z",
"updated_at": "2025-02-12T20:16:14.807961Z",
"currency": "btc",
"type": "bolt11",
"data": {
"payment_request": "lntbs1500n1pn66qv...",
"amount": {
"amount": 150000,
"currency": "btc",
"unit": "msats"
},
"amount_msats": 150000,
"memo": "test payment",
"expiration": 3600,
"market_quote": null
},
"requested_amount": {
"amount": 150000,
"currency": "btc",
"unit": "msats"
},
"status": "receiving",
"error": null,
"frozen": [],
"exchanges": []
}
  • direction – Always “receive” for incoming payments
  • type – bolt11 | onchain | bip21 | taprootasset
  • data.payment_request / data.address / data.receipts depending on type
  • requested_amount – What you originally requested
  • status – Current receive state
  • error – Structured error info if something failed
  • frozen – Parts of the payment frozen for compliance (e.g., OFAC)
GET https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments
  • direction=receive – Only incoming payments
  • wallet_id={wallet_id} – Specific wallet
  • statuses[]=receiving&statuses[]=completed – Filter by status
  • offset, limit – Pagination
Terminal window
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments?direction=receive&wallet_id={wallet_id}&limit=50' \
--header 'x-api-key: your-api-key'

See the lifecycle of a receive payment:

GET https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}/history

The response contains ordered events with timestamps and errors (if any), helpful for debugging or audits.

Typical state transitions:

  1. generating → Payment being set up (invoice/address generation)
  2. receiving → Invoice/address generated, waiting for funds
  3. completed → Funds received and credited
  4. expired → Invoice expired before payment
  5. failed → An error occurred (see error field for details)

You can monitor by:

  • Polling GET /payments/{payment_id} until status is terminal (completed, expired, or failed)
  • Webhooks (recommended)

Create a webhook to get real-time notifications when receive payments are generated, completed, expired, etc.

POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/webhooks

Include:

  • id – A client-generated UUID for the webhook registration; the create response returns this same value
  • url – Your HTTPS endpoint
  • name – Webhook name
  • events – Array of event types, e.g.:
[
{ "receive": "generated" },
{ "receive": "completed" },
{ "receive": "expired" },
{ "receive": "failed" }
]

The create response also returns a one-time shared_secret. Store it for signature verification; it is not included in callbacks. In a receive callback, detail.data.id is the payment ID supplied when the payment was created, not the webhook ID or organization ID. See Webhooks for the complete payload and identifier map.

POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/webhooks/{webhook_id}/test
  • type – “receive”
  • detail.data – Full Payment object
  • detail.event – Event type (generated, refreshed, expired, succeeded, completed, failed)
  • 202 – Receive payment creation accepted (invoice/address generation started)
  • 200 – Successful retrieval/list/history
  • 400 – Invalid request (bad IDs, missing fields, etc.)
  • 403 – Authentication/authorization error
  • 404 – Payment not found in this organization + environment
  • 500 – Server error

Within the payment object, the error field may contain:

  • receive_failed
  • expired
  • rejected