Lightning ↔ PIX

End-to-end flow — issue a Lightning invoice; once paid, settle BRL via PIX in seconds.

What this flow does

A payer anywhere in the world pays a BOLT11 Lightning invoice. Hodle receives the sats and settles BRL via PIX to the recipient you chose when creating the invoice. End-to-end median is under 30 seconds.

Use this when:

  • You're building a remittance product paying out to Brazil.
  • A foreign customer pays for a Brazilian-merchant invoice in BTC.
  • A user wants to off-ramp Lightning balance to a bank account.

Sequence

1. POST /api/lightning/invoice    → invoice (bolt11) + transactionId + expiresAt
2. (off-chain) payer pays the invoice before expiresAt
3. Hodle receives the sats and sends the PIX
4. Webhook PAYOUT_SUCCESSFUL       → PIX settled

You own step 1, getting the invoice paid, and listening for the webhook. Step 3 happens inside Hodle.

Step 1 — Issue the invoice

curl -X POST https://api.hodle.com.br/api/lightning/invoice \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "value": 10000,
    "pixKey": "[email protected]",
    "pixKeyType": "EMAIL"
  }'
const res = await fetch('https://api.hodle.com.br/api/lightning/invoice', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.HODLE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    value: 10000,
    pixKey: '[email protected]',
    pixKeyType: 'EMAIL',
  }),
})
const { transactionId, invoice, expiresAt } = await res.json()
import os, requests

res = requests.post(
    "https://api.hodle.com.br/api/lightning/invoice",
    headers={
        "Authorization": f"Bearer {os.environ['HODLE_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "value": 10000,
        "pixKey": "[email protected]",
        "pixKeyType": "EMAIL",
    },
)
data = res.json()

value is what the recipient receives, in BRL cents (min R$ 5.00, max R$ 3,000.00 by default). The invoice is priced at value + fee, quoted in satoshis at the moment of creation.

200 OK
{
  "success": true,
  "transactionId": "65f1a8b2c3d4e5f6a7b8c9d1",
  "trackId": "3dbbb785-8a1d-41c4-9d15-171e0ddc7c3d",
  "invoice": "lnbc1020n1p5u2g2qsp5...",
  "expiresAt": "2026-09-26T13:18:29.000Z",
  "valueInSatoshis": 28172,
  "pixKey": "[email protected]",
  "qrCode": null,
  "valueInBrl": 102,
  "fee": 2,
  "quote": {
    "brlAmount": 102,
    "btcAmount": 0.00028172,
    "satoshis": 28172,
    "btcToBrlRate": 362069.04
  }
}

Store transactionId against your order. Show the invoice string as a QR code or "copy to clipboard" — any Lightning wallet can pay it. Full field list, limits and errors: Lightning Invoice.

Step 2 — Payer pays the invoice

The invoice is payable for 1 hour (expiresAt). After that it cannot be paid and no webhook fires; issue a new one.

Step 3 — Settlement (transparent)

Once the sats arrive, Hodle converts them and sends the PIX to the key or QR code from step 1. You don't need to model any of this.

Step 4 — Listen for PAYOUT_SUCCESSFUL

Configure a webhook for PAYOUT_SUCCESSFUL in API Keys → Webhooks (it shows as "Payout confirmado" in the dashboard). It fires when the PIX settles — there is no separate "invoice paid" event.

{
  "event": "PAYOUT_SUCCESSFUL",
  "data": {
    "success": true,
    "transactionId": "65f1a8b2c3d4e5f6a7b8c9d1",
    "trackId": "3dbbb785-8a1d-41c4-9d15-171e0ddc7c3d",
    "status": "COMPLETED",
    "asset": "LIGHTNING",
    "network": "lightning",
    "valueInBrl": "100.00",
    "fee": "2.00",
    "pixKey": "[email protected]",
    "endToEndId": "E12345678202609261314abcdef123456",
    "invoice": "lnbc1020n1p5u2g2qsp5...",
    "txHash": "lnbc1020n1p5u2g2qsp5...",
    "valueInSatoshis": 28172
  }
}

Match it to the invoice by data.transactionId (or data.invoice, the same BOLT11 from step 1). This is the "book closed" event — surface "Settled" in your UI now. Full payload: Webhooks.

Failure modes

FailureWhere it surfacesWhat to do
Invoice expires unpaidNo webhook fires.Show "expired" after expiresAt. Re-issue if needed.
PIX could not be sentPAYOUT_FAILEDMark the order as failed and contact support.
Settled PIX reversedPAYOUT_REFUNDEDMark the order as refunded.
Value above your limits403 on step 1Read errorCode and limit; see Lightning Invoice.

Webhook signatures

Every delivery is signed. See Webhooks for the verification snippet.