Reliability, retries, and troubleshooting
Acknowledge quickly
Your endpoint should return a2xx response quickly after verifying and safely recording the event.
Recommended pattern:
- Verify signature.
- Parse event.
- Check idempotency / dedupe.
- Record event receipt.
- Return
200. - Process side effects asynchronously.
Delivery success
Brale treats2xx responses as successful delivery acknowledgements.
If your endpoint returns a non-2xx response or times out, Brale may retry delivery.
Idempotency
Webhook delivery is at-least-once. Your application must handle duplicate deliveries. Recommended database pattern:Local development
Use a public tunnel:Testing checklist
Before testing a real event:- Your server is running.
- Your public tunnel reaches your local server.
- Your subscription URL ends with your webhook path.
- Your application has the correct
sharedSecret. - Your server was restarted after updating environment variables.
- Your endpoint reads the raw body.
- Your handler returns
2xxfor valid events. - Your handler returns
401for invalid signatures. - Your handler deduplicates repeated event IDs / idempotency keys.
Troubleshooting
401 invalid_signature
Likely causes:
- Wrong
sharedSecret - Server not restarted after secret change
- Using a secret from another subscription
- Verifying parsed JSON instead of raw request body
- Request body mutated by middleware
- Test script signing different bytes than it sends
No webhook received
Check:- Is the subscription active?
- Does the subscription URL match your current tunnel URL?
- Is the event type subscribed?
- Did the transfer/payment actually reach the state that emits the event?
- Do delivery logs show an attempt?
- Did your endpoint return non-
2xx? - Did your tunnel expire or restart?
Duplicate delivery received
This can happen. Deduplicate by eventid and/or idempotency-key.
Return 2xx for duplicates after confirming you already processed the event.
sharedSecret lost
Archive the old subscription and create a new subscription. Brale does not return the secret again after creation.
Old API key does not work with webhook endpoints
Create a new API credential or OAuth application with webhook scopes:webhooks:readwebhooks:write