Webhooks let you receive real-time notifications when events occur in Cula, such as when
a new sink is verified. The implementation follows the
Standard Webhooks specification, using signatures
for secure verification.
Setting Up Your Endpoint
Before creating a webhook, prepare an HTTPS endpoint on your server that can:
- Accept POST requests with a JSON payload.
- Verify the signature using your webhook secret.
- Respond with a 2xx status code within 10 seconds to acknowledge receipt.
Example endpoint structure:
app.post('/webhooks/cula', (req, res) => {
const signature = req.headers['webhook-signature'];
const id = req.headers['webhook-id'];
const timestamp = req.headers['webhook-timestamp'];
const body = req.body;
// Verify signature using the webhook secret
if (!verifySignature(signature, id, timestamp, body)) {
return res.status(401).send('Invalid signature');
}
// Process event
console.log('Event received:', body.type, body.data);
res.status(200).send('Event received');
});
Creating a Webhook
Create a webhook by specifying your endpoint URL and the events you want to listen for:
curl -X POST https://api.demo.cula.earth/tracking/v1/webhooks \
-H "Authorization: Bearer your_access_token_here" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.com/webhooks/cula",
"events": ["sink.verified"],
"description": "Production webhook for sink updates"
}'
Response:
{
"id": "wbh_5ZTPGQX00HOLKUNM",
"url": "https://your-domain.com/webhooks/cula",
"events": ["sink.verified"],
"description": "Production webhook for sink updates",
"secret": "whsec_...",
"created_at": "2025-10-10T21:03:58Z",
"updated_at": "2025-10-10T21:03:58Z"
}
Save the secret (prefixed with whsec_) — you need it to verify webhook
signatures. It is only returned when the webhook is created.
Available Events
sink.verified — triggered when a sink is verified.
Every webhook request includes three standard headers:
| Header | Description | Example |
|---|
webhook-id | Unique identifier for this message | evt_2KWPBgLlAfxdpx2AI54pPJ85f4W |
webhook-timestamp | Unix timestamp (seconds since epoch) of the attempt | 1674087231 |
webhook-signature | Signature in Standard Webhooks format | v1,hnO3f9T8Y... |
Event Payload
When an event occurs, Cula sends a POST request to your endpoint:
{
"type": "sink.created",
"timestamp": "2025-10-10T21:03:58.000Z",
"data": {
"sink_id": "snk_7RMH0MQ22YHDBMZF"
}
}
Verifying Signatures
Webhook signatures must be verified to ensure authenticity. The verification process
follows the Standard Webhooks specification.
Security considerations:
- Verify the
webhook-timestamp is within an acceptable tolerance (for example, 5
minutes) to prevent replay attacks.
- Use the
webhook-id as an idempotency key to prevent processing the same event
multiple times.
- Store processed webhook IDs temporarily (for example, in Redis for 24 hours) to
detect duplicates.
For implementation, use the official
Standard Webhooks libraries,
available for multiple languages, which handle signature verification automatically.