# Sending (USD Line of Credit)

# Sending Payments with USD Line of Credit

This guide explains how to send Lightning Network and on-chain Bitcoin payments from a USD-denominated wallet using the Voltage Payments API. USD wallets leverage a line of credit to convert USD to BTC at the time of payment.

:::note
For Development testing, choose **Mutinynet USD**. Payments move 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 **API key** with access to the environment (from the "API Keys" page in your dashboard)
- The **Quotes API** enabled, and a valid `line_of_credit_id` for your USD wallet's line of credit
- The target Lightning invoice or Bitcoin address you intend to pay

## Workflow Overview

Sending from a USD wallet involves three steps:

1. **Determine the BTC amount** – If paying a Lightning invoice, decode it to extract the payment amount in millisatoshis. For on-chain payments where you already know the amount, skip to Step 2.
2. **Obtain a conversion quote** – Use the `POST /quotes` endpoint to get a quote for converting USD to BTC. This locks in an exchange rate and returns a `quote_id`.
3. **Create the payment** – Call the `POST /payments` endpoint with your USD wallet, including the `quote_id` and payment details.

## Step 1: Determine the BTC Amount from a Lightning Invoice

To create a quote, you need the BTC amount in millisatoshis (msats). When paying a Lightning invoice, the amount is encoded in the invoice string itself and must be extracted before you can request a quote.

:::note
The Voltage API does not currently provide an invoice decoding endpoint. You will need to decode the invoice client-side using a BOLT-11 decoding library.
:::

### JavaScript / TypeScript

Using [`light-bolt11-decoder`](https://www.npmjs.com/package/light-bolt11-decoder):

```bash
npm install light-bolt11-decoder
```

```javascript
import { decode } from 'light-bolt11-decoder';

const invoice = 'lnbc1500n1p...';
const decoded = decode(invoice);

const amountSection = decoded.sections.find(s => s.name === 'amount');
const amountMsats = amountSection ? Number(amountSection.value) : null;

if (!amountMsats) {
  throw new Error('Invoice does not contain an amount');
}

console.log(`Amount: ${amountMsats} msats`);
// Use amountMsats as the "amount" in your quote request (Step 2)
```

### Python

Using [`bolt11`](https://pypi.org/project/bolt11/):

```bash
pip install bolt11
```

```python
import bolt11

invoice = "lnbc1500n1p..."
decoded = bolt11.decode(invoice)

amount_msats = decoded.amount_msat
if not amount_msats:
    raise ValueError("Invoice does not contain an amount")

print(f"Amount: {amount_msats} msats")
# Use amount_msats as the "amount" in your quote request (Step 2)
```

:::caution
For on-chain or BIP21 payments where you already know the amount you want to send, you can skip this step and go directly to Step 2.
:::

## Step 2: Get a Quote for USD→BTC Conversion

Before creating a payment from a USD wallet, you must get a quote to convert the payment amount into BTC. Use the amount you decoded in Step 1 (or the amount you already know for on-chain payments).

### Endpoint

```text
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/quotes
```

### Headers

```text
x-api-key: your-api-key
Content-Type: application/json
```

### Example Request

```bash
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": 150000,
      "currency": "btc",
      "unit": "msats"
    },
    "to": "usd"
  }'
```

### Request Fields

- `id` – A client-generated UUID for the quote (for idempotency)
- `line_of_credit_id` – Your USD line of credit ID
- `network` – The Bitcoin network ("mainnet", "testnet", "signet", or "mutinynet")
- `amount` – The BTC amount you need to send (in msats). When paying a Lightning invoice, this is the amount decoded in Step 1.
- `to` – Target currency for conversion ("usd")

The API will respond with a quote object containing an exchange rate and a `quote_id`. Use that `quote_id` in Step 3.

:::caution
Quotes are time-limited. Use the quote promptly before it expires.
:::

## Step 3: Create a Payment from the USD Wallet

With a valid quote in hand, create the payment using the `POST /payments` endpoint.

### Endpoint

```text
POST https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments
```

### Headers

```text
x-api-key: your-api-key
Content-Type: application/json
```

### 3.1 Send a Lightning (Bolt11) Payment

To pay a Lightning invoice from a USD wallet, provide the invoice in the `payment_request` field.

```bash
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": "68d00852-8dd8-4c71-94d2-91c84695da78",
    "wallet_id": "{usd_wallet_id}",
    "currency": "usd",
    "quote_id": "12345678-1234-5678-9abc-def012345678",
    "type": "bolt11",
    "data": {
      "payment_request": "lnbc1500n1p...",
      "amount": {
        "currency": "btc",
        "amount": 150000,
        "unit": "msats"
      },
      "max_fee": {
        "currency": "btc",
        "amount": 1000,
        "unit": "msats"
      }
    }
  }'
```

### Request Fields

- `id` – A client-generated UUID for the payment (for idempotency)
- `wallet_id` – The UUID of your USD wallet
- `currency` – "usd" (the wallet's currency)
- `quote_id` – The UUID of the quote obtained in Step 2 (**required for USD wallets**)
- `type` – "bolt11" for a Lightning payment
- `data.payment_request` – The BOLT-11 Lightning invoice string (cannot be empty)
- `data.amount` – Optional BTC amount object. Required if the invoice has no amount encoded; must match if the invoice has a fixed amount
- `data.max_fee` – Optional maximum routing fee in BTC (defaults to 1% of payment or 1,000 msats, whichever is greater)

### 3.2 Send an On-Chain Bitcoin Payment

To send BTC on-chain from a USD wallet, provide the Bitcoin address and amount.

```bash
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": "2ec1e783-19b4-4c10-8181-66336a6232bd",
    "wallet_id": "{usd_wallet_id}",
    "currency": "usd",
    "quote_id": "12345678-1234-5678-9abc-def012345678",
    "type": "onchain",
    "data": {
      "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
      "amount": {
        "currency": "btc",
        "amount": 15000000,
        "unit": "msats"
      },
      "max_fee": {
        "currency": "btc",
        "amount": 1000000,
        "unit": "msats"
      },
      "description": "Payment for services"
    }
  }'
```

### Request Fields

- `type` – "onchain" for an on-chain BTC payment
- `data.address` – The recipient's Bitcoin address
- `data.amount` – The amount to send in BTC (msats). Example: 15,000,000 msats = 15,000 sats
- `data.max_fee` – Optional maximum miner fee in msats
- `data.description` – Optional memo for your records

### 3.3 Send a Unified BIP21 Payment

A BIP21 URI can include both an on-chain address and an embedded Lightning invoice. The API will parse the URI and execute the payment via Lightning or on-chain as appropriate.

```bash
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": "3e84b6c5-5bbe-4e0f-9fb3-f1198330f6fa",
    "wallet_id": "{usd_wallet_id}",
    "currency": "usd",
    "quote_id": "12345678-1234-5678-9abc-def012345678",
    "type": "bip21",
    "data": {
      "address": "bitcoin:bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh?label=Example%20Store&message=Payment%20for%20services&lightning=lnbc1500...qpz",
      "payment_request": "lnbc1500n1p...",
      "amount": {
        "currency": "btc",
        "amount": 150000,
        "unit": "msats"
      },
      "max_fee": {
        "currency": "btc",
        "amount": 1000,
        "unit": "msats"
      },
      "description": "Payment for services"
    }
  }'
```

### Request Fields

- `type` – "bip21" for a unified Bitcoin payment
- `data.address` – The BIP21 URI string (required)
- `data.payment_request` – Optional Lightning invoice if you have it separately
- `data.amount` – Optional BTC amount object (can be omitted if URI contains amount)
- `data.max_fee` – Optional max Lightning fee in msats
- `data.description` – Optional memo (independent of any invoice memo)

## Monitoring Payment Status

After initiating a payment, monitor its status using:

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

### Example

```bash
curl 'https://voltageapi.com/v1/organizations/{organization_id}/environments/{environment_id}/payments/{payment_id}' \
  --header 'x-api-key: your-api-key'
```

### Payment States

- **sending** – Payment is in progress
- **completed** – Payment was successful and funds have been delivered
- **failed** – Payment failed (check the `error` field for details)

### Response Fields for USD Payments

For completed USD payments, the response includes:

- `data.market_quote` – The exchange rate used for USD/BTC conversion
- `data.amount` – The amount in USD that was debited from your wallet

## Error Handling

### HTTP Status Codes

- **200** – Success
- **400** – Invalid request (missing fields, expired/invalid quote, etc.)
- **403** – Authentication or permissions error
- **404** – Resource not found
- **500** – Server error

### Common Errors

- **Missing quote\_id** – USD wallet payments require a valid `quote_id`
- **Expired quote** – Quotes are time-limited; obtain a new one
- **Invalid invoice** – The Lightning invoice is malformed or expired
- **Insufficient balance** – Your USD wallet doesn't have enough funds

When a payment fails, the `status` will be "failed" and the `error` object will contain details about the failure reason.
