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>
2.0 KiB
2.0 KiB
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
- BTCPay → Store → Webhooks → delete or disable the webhook.
- 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)
{
"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
- Valid
BTCPAY-SIGsignature type == InvoiceReceivedPayment- BTCPay API returns invoice
status == "New"0 < amountPaid < amountmetadata.buyerEmailis 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 |