# 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= ``` 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 |