Skip to main content
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:
  1. Accept POST requests with a JSON payload.
  2. Verify the signature using your webhook secret.
  3. 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.

Webhook Headers

Every webhook request includes three standard headers:
HeaderDescriptionExample
webhook-idUnique identifier for this messageevt_2KWPBgLlAfxdpx2AI54pPJ85f4W
webhook-timestampUnix timestamp (seconds since epoch) of the attempt1674087231
webhook-signatureSignature in Standard Webhooks formatv1,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.