Webhooks
TEDR Pay sends webhook notifications to the address you put on your API key. Two fields drive this: webhookUrl is where the notifications go, and webhookSecret is the value TEDR Pay signs them with.
Both fields live on the key itself, so you set and replace them through the API key endpoints, not through a separate webhook API.
Don't treat a webhook as proof of payment.
The scheme for verifying a webhook signature is not published yet, so your endpoint has no way to tell a genuine callback from a forged one. Until it is, confirm the state with a request back to us — GET /invoices/:id or GET /invoices/:id/payments.
Confirming payments
Use the callback only as a signal that something may have changed, and let the API answer decide what actually happened. Both read routes accept an API key signature, so your backend can call them without a dashboard session:
GET /invoices/:id— the invoice itself.GET /invoices/:id/payments— the payments recorded against it.
Both are documented on the Invoices page.
The webhook URL
webhookUrl is optional when you create a key and can be set or changed later. The address has to be reachable from the public internet, so it is validated:
- The scheme must be
https. - The host must be a domain name containing a dot.
localhostand127.0.0.1are rejected.
An address that fails any of these is refused with 400 VALIDATION_ERROR when you create or update the key.
The webhook secret
webhookSecret is whsec_<32 random bytes, base64url>. It is returned only in the create and rotate responses — a read of the key never includes it, and there is no way to fetch it again. Store it the moment you see it.
Two signatures, two keys
Signing is easy to mix up here, because it happens in both directions with two different keys from the same API key row.
| Signature | Key | Direction | Scheme |
|---|---|---|---|
| Your API requests | secretKey | Your backend to TEDR Pay | HMAC over the timestamp, the URL and the body — see Authentication. |
| Webhooks we send you | webhookSecret | TEDR Pay to your endpoint | Not published yet. |
Only the first of the two is something you can implement today. The second is what the callout at the top of this page is about.
Revoking and rotating
Revoking and rotating a key do different things to the webhooks already in flight.
| Action | What happens to the key material | Webhooks for invoices that are still open |
|---|---|---|
| Revoke | Soft delete — the row itself stays. | Still signed with the webhookSecret the key had when the invoice was created. |
| Rotate | privateKey, secretKey and webhookSecret are all replaced in the same row; id, name, webhookUrl and createdAt stay. | Signed with the new webhookSecret immediately. |
Rotation takes effect immediately.
After a rotation, invoices that are still open are notified with the new webhookSecret. A revoke is the opposite: the old value survives along with the row, so invoices created while the key was active keep using it.
