Skip to main content

Strike Webhooks

Payment notifications travel in two hops. Understanding the split matters, because you configure one of them and Lightning Enable handles the other for you.

Strike  ──(1)──▶  Lightning Enable  ──(2)──▶  Your callback URL
HopWho configures itWhat it carries
1. Strike → Lightning EnableLightning Enable, automaticallyA thin notification with an entity ID
2. Lightning Enable → youYou, in the dashboardFull payment detail, HMAC signed

Hop 1: Strike to Lightning Enable

You do not configure this hop. Lightning Enable registers a webhook subscription against your Strike account automatically, the first time it creates a payment for you. That is why your API key needs the partner.webhooks.manage scope.

Lightning Enable stores the resulting subscription ID and a per-merchant signing secret so it can verify that incoming notifications genuinely came from Strike.

Strike Webhooks Are Thin

A Strike webhook carries an entity ID, not the payment itself. Lightning Enable calls the Strike API to fetch the full details before acting on it. This is the main behavioral difference from OpenNode, whose webhooks carry the full payload.

The endpoint that receives these notifications is POST /api/webhooks/strike. It is public by necessity — Strike must reach it — and it authenticates every request by signature rather than by API key.

Hop 2: Lightning Enable to Your Platform

This is the hop you configure. Set a callback URL and Lightning Enable posts signed payment events to it.

Set Your Callback URL

In the dashboard, go to Settings and set your callback URL. Or use the merchant API:

curl -X PUT https://api.lightningenable.com/api/merchant/webhook-url \
-H "X-API-Key: your-merchant-api-key" \
-H "Content-Type: application/json" \
-d '{ "webhookUrl": "https://your-platform.example.com/webhooks/lightning-enable" }'

Your endpoint must accept POST, be reachable over HTTPS, and return a 2xx status quickly. Do the slow work after you respond.

Verify the Signature

Every forwarded webhook carries an X-LightningEnable-Signature header:

X-LightningEnable-Signature: t=1735689600,v1=5257a869e7bcd6742a1f2c...

t is a Unix timestamp and v1 is an HMAC-SHA256 signature over {t}.{raw_body}.

Follow the reference implementations in Verifying Webhooks. That page is the single source of truth for this procedure and carries working Node.js, C#, and Python verifiers, plus the exact freshness window under Replay Protection. This page deliberately does not repeat them — a second copy of a security-critical routine drifts out of sync with the first.

Three things are worth calling out because they are the common ways a verifier goes wrong:

  • Enforce timestamp freshness. Signature validity alone does not stop a replay. Reject requests whose t falls outside the tolerance given under Replay Protection.
  • Compare in constant time. Use CryptographicOperations.FixedTimeEquals or your language's equivalent. A plain == returns on the first mismatched byte and leaks the expected signature to anyone measuring response times.
  • Parse the header defensively. Do not index into split(',') positionally. A malformed or hostile header should be rejected, not throw an unhandled exception out of your public endpoint.

Use the Raw Body

Compute the signature over the exact bytes you received. If your framework parses the JSON and you re-serialize it, key order or whitespace can change and the signature will not match. Capture the raw body before parsing.

Idempotency

Retries and network conditions mean the same event can arrive more than once. Key your handler on the payment or invoice identifier and make repeat deliveries a no-op. Do not assume exactly-once delivery.

Troubleshooting

No Webhooks Arrive from Strike

  1. Confirm your Strike API key has the partner.webhooks.manage scope
  2. Check the Strike dashboard for a webhook subscription
  3. Create another payment — registration retries on payment creation
  4. Re-save your Strike key, which forces re-registration

Webhooks Arrive but Signature Checks Fail

  1. Confirm you are hashing the raw body, not a re-serialized version
  2. Confirm the signed payload is {timestamp}.{body}, not the body alone
  3. Confirm you are using your Lightning Enable webhook secret, not your Strike API key
  4. Compare the hex encoding — the signature is lowercase hex, not Base64

Your Endpoint Times Out

Return 2xx first and process afterward. Slow handlers look like failures and trigger retries.

Next Steps