Webhooks: Real-Time Event Delivery in Calmony Pay
Webhooks: Real-Time Event Delivery in Calmony Pay
v1.0.8 · Webhook Event Dispatch System
Calmony Pay now supports webhooks — a mechanism for your application to receive real-time HTTP notifications when events occur in your account. This enables you to react to payment completions, subscription changes, invoice generation, and other lifecycle events without polling the API.
How Webhooks Work
When an event occurs in Calmony Pay, the platform:
- Constructs a signed event payload
- Queues delivery via Inngest
- POSTs the payload to every registered endpoint for your account
- Retries automatically on failure with exponential backoff
All delivery happens asynchronously and does not block the originating API request.
Managing Endpoints
Register an Endpoint
POST /v1/webhook_endpoints
Content-Type: application/json
Authorization: Bearer <api_key>
{
"url": "https://your-app.example.com/webhooks/calmony"
}
The response includes a secret field. Store this securely — it is used to verify incoming webhook signatures and will not be shown again.
List Registered Endpoints
GET /v1/webhook_endpoints
Authorization: Bearer <api_key>
Returns an array of registered endpoint objects for your account.
Remove an Endpoint
DELETE /v1/webhook_endpoints/:id
Authorization: Bearer <api_key>
Once removed, no further events will be delivered to that URL.
Event Envelope
Every webhook delivery uses the following standardised payload structure:
{
"id": "evt_01j...",
"type": "payment_intent.succeeded",
"created": 1718000000,
"data": {
"object": {
// The full resource object related to this event
}
}
}
| Field | Type | Description |
|---|---|---|
id | string | Unique event ID with evt_ prefix |
type | string | Dot-notation event type (e.g. invoice.created) |
created | integer | Unix timestamp of when the event was created |
data.object | object | The full resource associated with this event |
Verifying Signatures
Every request from Calmony Pay includes an X-Calmony-Signature header containing an HMAC-SHA256 digest of the raw request body, signed with the endpoint's secret.
Verification Example (Node.js)
import crypto from 'crypto';
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
const expectedSig = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expectedSig)
);
}
Important: Always verify the signature before processing any webhook payload. Reject requests that fail verification with a
400or401response.
Retry Behaviour
If your endpoint does not return a 2xx HTTP status within 10 seconds, the delivery is considered failed and Calmony Pay will retry automatically:
| Attempt | Delay after previous failure |
|---|---|
| 1st retry | 5 seconds |
| 2nd retry | 30 seconds |
| 3rd retry | 5 minutes |
After three failed retries, the event is marked as undelivered. No further attempts are made.
Best Practices for Reliable Receipt
- Respond quickly. Return
200 OKas soon as you receive the request, then process asynchronously. - Make handlers idempotent. The same event may be delivered more than once (e.g. if your server returns
200but crashes before finishing). Use theidfield to deduplicate. - Do not rely on delivery order. Events may arrive out of sequence under retry conditions.
Delivery Infrastructure
Webhook dispatch is powered by Inngest, which provides a durable, queue-backed event delivery system. This ensures events are never lost due to transient failures and that retries are managed independently of the main API process.