Send a bannered test transactional email when BTCPay UI test events arrive instead of failing on a missing invoice API lookup. Co-authored-by: Cursor <cursoragent@cursor.com>
78 lines
2.0 KiB
Markdown
78 lines
2.0 KiB
Markdown
# BTCPay webhook reference
|
||
|
||
## Endpoint
|
||
|
||
```
|
||
POST https://mailer.nxtgroup.org/btcpay-webhook
|
||
```
|
||
|
||
No query-string token. BTCPay signs each request with the **webhook secret** from the store webhook settings.
|
||
|
||
## Authentication
|
||
|
||
BTCPay sends header `BTCPAY-SIG`:
|
||
|
||
```
|
||
sha256=<hmac-sha256-hex>
|
||
```
|
||
|
||
The HMAC is computed over the **raw request body bytes** using the webhook **Secret** shown in BTCPay (same value as `BTCPAY_WEBHOOK_SECRET` in Portainer).
|
||
|
||
## Disable quickly
|
||
|
||
1. **BTCPay** → Store → **Webhooks** → delete or disable the webhook.
|
||
2. **Portainer** → Stacks → `btcpaymailer` → stop/remove the stack.
|
||
|
||
## Event subscribed
|
||
|
||
Only **`InvoiceReceivedPayment`** is processed. Other events return `200` with `"ignored"` (silent unless `DEBUG=true`).
|
||
|
||
## Webhook body (BTCPay → mailer)
|
||
|
||
```json
|
||
{
|
||
"deliveryId": "abc123",
|
||
"webhookId": "wh_xyz",
|
||
"isRedelivery": false,
|
||
"type": "InvoiceReceivedPayment",
|
||
"timestamp": 1717843200,
|
||
"storeId": "your-store-id",
|
||
"invoiceId": "invoice-id-here"
|
||
}
|
||
```
|
||
|
||
The app then fetches the full invoice:
|
||
|
||
```
|
||
GET {BTCPAY_URL}/api/v1/stores/{storeId}/invoices/{invoiceId}
|
||
```
|
||
|
||
## Send conditions
|
||
|
||
1. Valid `BTCPAY-SIG` signature
|
||
2. `type == InvoiceReceivedPayment`
|
||
3. BTCPay API returns invoice
|
||
4. `status == "New"`
|
||
5. `0 < amountPaid < amount`
|
||
6. `metadata.buyerEmail` is set
|
||
|
||
## BTCPay UI test events
|
||
|
||
Invoice IDs containing `__test__` (BTCPay’s “Send test” button) skip the API fetch and trigger a Postmark test email to `WEBHOOK_TEST_EMAIL`, or the first `BCC_EMAIL` address if unset. The email includes a red **THIS IS A TEST TRANSACTIONAL EMAIL, PLEASE IGNORE.** banner.
|
||
|
||
## Response codes
|
||
|
||
| Code | Meaning |
|
||
|------|---------|
|
||
| `401` | Missing or invalid `BTCPAY-SIG` |
|
||
| `400` | Partial payment but no `buyerEmail` |
|
||
| `500` | BTCPay API or Postmark failure |
|
||
| `200` | Ignored, or email sent |
|
||
|
||
## Logging
|
||
|
||
| `DEBUG` | Container logs |
|
||
|---------|----------------|
|
||
| `false` | Evaluation + send result for payment events only |
|
||
| `true` | Full payload and every decision step |
|