Receiving (USD Line of Credit)
Receiving Payments with USD Line of Credit
This guide explains how to receive Bitcoin (BTC) payments into a USD-denominated wallet using the Voltage Payments API. With a USD wallet (backed by a line of credit), incoming BTC is automatically converted to USD. You present Lightning invoices or on-chain addresses for payment in BTC, while your wallet balance is credited in USD.
For Development testing, choose Mutinynet USD. Payments arrive over Bitcoin or Lightning while the wallet and line of credit are denominated in USD. Mutinynet Bitcoin and Voltage Cash are not the correct wallets for this workflow.
Prerequisites
- A Voltage account with an active USD wallet (credit-backed wallet with an associated USD line of credit)
- An Environment API key with access to the wallet's environment
- Line of credit enabled with access to the Quotes API
- The UUIDs for your organization, environment, wallet, and line_of_credit_id
Workflow Overview
Receiving funds into a USD wallet is a multi-step process:
- Get a quote – Use POST /quotes to lock in the BTC→USD conversion rate for the amount you expect to receive
- Create a receive payment request – Use POST /payments to generate a Lightning invoice, on-chain address, or BIP21 URI, including the quote_id
- Retrieve payment details – Fetch the payment to get the actual invoice/address to present to the payer
- Monitor status – Wait for the payment to be received and credited
USD wallets do not support "any-amount" invoices because a specific quote (fixed amount) is required.
Key Data Shapes
Amount Object
{
"amount": 1000,
"currency": "usd",
"unit": "cents"
}- USD: smallest unit is cents (1000 cents = $10.00)
- BTC: smallest unit is millisatoshis (150000 msats = 1500 sats)
Receive Statuses
- generating – Invoice/address is being created
- receiving – Invoice/address generated and waiting for payment
- completed – Fully received and credited
- expired – Invoice expired before being paid
- failed – Could not be generated or completed
Step 1: Get a Quote for BTC→USD Conversion
Before creating the receive payment, obtain a quote to lock in the conversion rate.
Endpoint
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/quotesHeaders
x-api-key: your-api-key
Content-Type: application/jsonExample Request
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/quotes' \
--request POST \
--header 'x-api-key: your-api-key' \
--header 'Content-Type: application/json' \
--data '{
"id": "87654321-4321-8765-cba9-fed987654321",
"line_of_credit_id": "{line_of_credit_id}",
"network": "mainnet",
"amount": {
"amount": 100000,
"currency": "btc",
"unit": "msats"
},
"to": "usd"
}'Request Fields
- id – A client-generated UUID for the quote
- line_of_credit_id – Your USD line of credit ID
- network – The Bitcoin network
- amount – The BTC amount you expect to receive (in msats)
- to – Target currency for conversion ("usd")
Save the quote_id from the response for Step 2.
Quotes are short-lived (typically 2 minutes) to account for BTC price volatility. Use a fresh quote when creating the payment.
Step 2: Create a Receive Payment
With a quote ready, create the receive payment request.
Endpoint
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/paymentsHeaders
x-api-key: your-api-key
Content-Type: application/json2.1 Receive a Lightning (Bolt11) Payment
Create a Lightning invoice that, when paid in BTC, credits your USD wallet.
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": "{usd_wallet_id}",
"currency": "usd",
"payment_kind": "bolt11",
"quote_id": "87654321-4321-8765-cba9-fed987654321",
"amount": {
"amount": 1000,
"currency": "usd",
"unit": "cents"
},
"description": "Receive BTC, convert to $10.00",
"expiration": 3600
}'Request Fields
- id – A client-generated UUID for the payment
- wallet_id – Your USD wallet ID
- currency – "usd" (must match the wallet's currency)
- payment_kind – "bolt11" to create a Lightning invoice
- quote_id – The quote ID from Step 1 (required for USD wallets)
- amount – The USD amount you wish to receive (e.g., 1000 cents = $10.00)
- description – Optional memo to attach to the invoice (appears as memo in the response)
- expiration – Optional expiration in seconds (default: 3600, max: 86400)
The API will calculate the corresponding BTC amount using the quote's rate and generate a Lightning invoice for that BTC amount.
2.2 Receive an On-Chain Bitcoin Payment
Generate a Bitcoin address tied to your USD wallet.
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": "{usd_wallet_id}",
"payment_kind": "onchain",
"quote_id": "87654321-4321-8765-cba9-fed987654321",
"amount": {
"amount": 1000,
"currency": "usd",
"unit": "cents"
},
"currency": "usd",
"description": "Receive BTC on-chain, convert to $10.00"
}'Request Fields
- payment_kind – "onchain" to generate an on-chain BTC address
- quote_id – The quote ID (required for USD wallets)
- amount – The USD amount you aim to receive
- currency – "usd"
- description – Optional description for your records
The response will include:
- A Bitcoin address in data.address
- data.receipts entries as the transaction confirms
Generate a new receive payment (with a new quote) for each separate on-chain payment you expect. The quote locks the rate for that specific amount and timeframe.
If an on-chain payment arrives after the quote expires, the payment may fail or be rejected. Always ensure the payer sends funds promptly within the quote validity window (typically 2 minutes).
2.3 Receive a Unified BIP21 Payment
Create a BIP21 URI that includes both a Lightning invoice and an on-chain address, giving the payer flexibility.
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": "{usd_wallet_id}",
"payment_kind": "bip21",
"quote_id": "87654321-4321-8765-cba9-fed987654321",
"amount": {
"amount": 1000,
"currency": "usd",
"unit": "cents"
},
"currency": "usd",
"description": "Receive BTC via BIP21, convert to $10.00",
"expiration": 3600
}'Request Fields
- payment_kind – "bip21" for a unified payment request
- quote_id – The quote ID (required)
- amount – USD amount to receive
- expiration – Optional expiration for the Lightning invoice portion (the on-chain address doesn't expire, but the quote's rate may not hold if significantly delayed)
- description – Optional note
The generated data.address will be a BIP21 URI the payer can scan. Whether they pay via Lightning or on-chain, your wallet will be credited in USD at the locked rate.
Step 3: Retrieve Payment Details
After creating a receive payment, fetch it to get the actual invoice or address.
Endpoint
GET https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}Example
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}' \
--header 'x-api-key: your-api-key'Example Response
{
"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": "usd",
"type": "bolt11",
"data": {
"payment_request": "lntbs1500n1pn66qv...",
"amount": {
"amount": 1000,
"currency": "usd",
"unit": "cents"
},
"memo": "Receive BTC, convert to $10.00",
"expiration": 3600,
"market_quote": {
"from": "btc",
"to": "usd",
"rate": "25000.00",
"quoted_at": "2025-02-12T20:16:14Z"
}
},
"requested_amount": {
"amount": 1000,
"currency": "usd",
"unit": "cents"
},
"status": "receiving",
"error": null,
"frozen": [],
"exchanges": []
}Key Response Fields
- direction – "receive" for incoming payments
- type – bolt11 | onchain | bip21
- data.payment_request – The Lightning invoice string (for bolt11/bip21)
- data.address – The Bitcoin address (for onchain/bip21)
- data.market_quote – The exchange rate used for conversion
- requested_amount – The USD amount you originally requested
- status – Current receive state
- error – Structured error info if something failed
- frozen – Parts of the payment frozen for compliance
- exchanges – Currency exchange details
Listing Incoming Payments
List and filter payments, including only receive-direction ones.
Endpoint
GET https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/paymentsQuery Parameters
- direction=receive – Only incoming payments
- wallet_id={wallet_id} – Specific wallet
- statuses[]=receiving&statuses[]=completed – Filter by status
- offset, limit – Pagination
Example
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'Viewing Payment History
See the lifecycle of a receive payment:
GET https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}/historyThe response contains ordered events with timestamps and errors (if any), useful for debugging and audits.
Monitoring Receive Status
Typical state transitions:
- generating → Payment being set up
- receiving → Invoice/address generated, waiting for funds
- completed → Funds received and credited
- expired → Invoice expired before payment
- failed → An error occurred
You can monitor by:
- Polling GET /payments/{payment_id} until status is terminal (completed, expired, or failed)
- Webhooks (recommended)
Webhooks for Receive Events
Create a webhook to get real-time notifications when receive payments are generated, completed, expired, etc.
Create a Webhook
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/webhooksInclude in the request:
- 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.
Test a Webhook
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/webhooks/{webhook_id}/testWebhook Payload
Receive webhook payloads include:
- type – "receive"
- detail.data – Full Payment object
- detail.event – Event type (generated, refreshed, expired, succeeded, completed, failed)
Error Handling
HTTP Status Codes
- 202 – Receive payment creation accepted
- 200 – Successful retrieval/list/history
- 400 – Invalid request (bad IDs, missing fields, invalid quote, etc.)
- 403 – Authentication/authorization error
- 404 – Payment not found
- 500 – Server error
Receive Errors
Within the payment object, the error field may contain:
- receive_failed
- expired
- rejected
For USD conversions, data.market_quote and exchanges help you understand which rate was used.