Webhooks/Overview

Webhooks overview

Webhooks let your application react when your Phoenixd node receives a payment. Instead of repeatedly checking for payments, provide an HTTPS endpoint and Nodana will send it a signed JSON POST request.

Each node supports one webhook endpoint. Nodana forwards the Phoenixd event body and adds headers you can use to verify the request and identify the delivery. Your application must verify the signature before acting on an event.

Set up your endpoint

  1. Create a server endpoint that accepts JSON POST requests. Follow Receiving webhooks for a runnable Node.js example.
  2. Deploy it at a public HTTPS URL, such as https://example.com/webhooks/nodana. Nodana rejects HTTP URLs, URLs with embedded credentials, and destinations that resolve to private or local network addresses. For local development, use a public HTTPS tunnel that forwards to your receiver.
  3. Open your node in the Nodana dashboard, select Webhooks, and click Add endpoint.
  4. Enter your endpoint URL and an optional description, then click Add endpoint.
  5. Copy the signing secret shown after creation. It is only shown once. Store it on your server, for example in the NODANA_WEBHOOK_SECRET environment variable, and configure your receiver to use it.

The signing secret begins with whsec_. It belongs to this webhook endpoint and is separate from your Nodana API key and Phoenixd passwords. Use the entire secret, including the prefix, as the HMAC key. Keep it out of browser code and source control. If you lose it, delete and recreate the endpoint, then update your receiver with the new secret.

What Nodana sends

Every delivery has these headers:

HeaderPurpose
Content-Type: application/jsonThe request body is JSON.
X-Nodana-SignatureHex-encoded HMAC-SHA256 of the exact request body, using your endpoint's signing secret.
X-Nodana-Event-IdDelivery identifier. It stays the same across retries of this delivery.
X-Nodana-Event-TypeThe Phoenixd event type, such as payment_received.

The JSON body is the original Phoenixd payload, without a Nodana wrapper. For example, these fields describe a received payment; actual events may include additional fields:

{
  "type": "payment_received",
  "amountSat": 1000,
  "paymentHash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
}

Handle payment_received in your application and tolerate additional fields. Acknowledge verified event types that your application does not use with a 2xx response. The receiver guide shows how to verify the signature using the raw request body.

Delivery and retries

Return a 2xx status once you have safely accepted the event. Nodana allows up to 10 seconds for the request to complete and does not follow redirects. Use the final HTTPS destination URL directly.

Network errors, timeouts, and all non-2xx responses count as failed attempts. Nodana makes up to four attempts in total: the initial attempt, then retries after approximately 1 minute, 5 minutes, and 30 minutes following each failure. A successful 2xx response ends retries.

Your receiver may see the same delivery more than once, for example if it processes a payment but the response is lost. Store X-Nodana-Event-Id in a durable database with a uniqueness constraint. Also make payment processing idempotent using paymentHash for the node, so separate events for the same payment cannot trigger duplicate fulfilment. Do not rely on delivery order.

Check deliveries

The node's Webhooks tab shows recent deliveries, their payloads, attempt counts, response statuses, and errors. Delivery states are pending, retrying, delivered, failed, or cancelled. The history shows up to 50 recent deliveries; records older than 3 days are removed by an hourly cleanup job.

Disabling an endpoint cancels pending deliveries. Events received while there is no enabled endpoint are not queued for later delivery, and re-enabling an endpoint does not replay them. Deleting an endpoint removes its delivery history. Keep your own records and reconcile payments with your node if your integration has been unavailable or deliveries exhaust their retries.

Next step

Build and test your receiver with Receiving webhooks.

On this page