Webhooks
Webhook subscription management and event fan-out. Register HTTPS endpoints to receive real-time notifications when events happen in your project — KV changes, channel messages, job completions, and more.
topics. When a matching event fires, SaaSignal POSTs a signed JSON payload to your url. Failed deliveries are retried with exponential backoff. You can inspect delivery history and manually retry failures.Available Topics
Topics support exact match, * wildcard (all events), and prefix wildcards (e.g. jobs.* matches jobs.completed, jobs.failed, jobs.dead).
kv.setkey, value, ttl, expires_atkv.deletekeychannels.publishedchannel, event, event_id, deliveredjobs.completedjob_id, name, run_id, attempt, resultjobs.failedjob_id, name, run_id, attempt, error, retry_atjobs.deadjob_id, name, run_id, attempt, error, max_attemptsai.operation.completedoperation_id, model, kindai.operation.failedoperation_id, model, reasonai.index.createdindex_id, name, dimensionsai.index.deletedindex_idlogistics.geo.createdentity_id, type, namelogistics.geo.updatedentity_idlogistics.geo.deactivatedentity_idlogistics.geofence.createdfence_id, name, typelogistics.geofence.deletedfence_idlogistics.geofence.enteredentity_id, fence_id, fence_name, lat, lnglogistics.geofence.exitedentity_id, fence_id, fence_name, lat, lnglogistics.eta_fence.createdfence_id, name, dest_lat, dest_lng, threshold_minlogistics.eta_fence.deletedfence_idlogistics.eta_fence.breachentity_id, fence_id, fence_name, eta_min, threshold_min, lat, lng, dest_lat, dest_lnglogistics.eta_fence.clearedentity_id, fence_id, fence_name, eta_min, threshold_min, lat, lnglogistics.pingentity_id, lat, lng, speed, headingdelivery.driver.onlinedriver_id, namedelivery.driver.offlinedriver_id, namedelivery.order.assignedorder_id, driver_iddelivery.order.acceptedorder_id, driver_iddelivery.order.in_transitorder_id, driver_iddelivery.order.picked_uporder_id, driver_iddelivery.order.deliveredorder_id, driver_iddelivery.order.failedorder_id, driver_id, reasondelivery.order.cancelledorder_iddelivery.zone.createdzone_id, namedelivery.zone.updatedzone_iddelivery.zone.deletedzone_iddelivery.hub.updatedhub_id, namedelivery.hub.deletedhub_idcustom.*POST /infra/webhooks/publishtest.pingmessagePayload envelope
All payloads are wrapped: { event_id, topic, timestamp, data: { ...fields } }. Deliveries include an HMAC-SHA256 signature in the X-Saasignal-Signature: sha256={hex} header.
Publish Event
Publish a custom event to trigger matching webhooks. Topics must start with custom. (e.g. custom.order.created). Payload data is capped at 64 KB. Base publish cost is charged up front; each downstream delivery attempt is billed separately and varies slightly with payload size.
curl -X POST https://api.saasignal.saastemly.com/infra/webhooks/publish \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"topic":"...","data":{"key":"value"}}'
{ "status": "ok" }
await ss.infra.webhooks.publish('custom.order.created', {
order_id: 'ord_123',
customer: 'cust_456',
})
- Use the SDK or API to publish custom events
- Topics must start with
custom.(e.g.custom.order.created) - All webhooks subscribed to a matching topic pattern will receive the event
topic requiredcustom. (e.g. custom.order.created). Max 256 chars.^[\w.:@-]+$data requiredCreate Webhook
Register a webhook subscription for event topics. Topics: kv.set, kv.delete, channels.published, jobs.completed, jobs.failed, jobs.dead, logistics.* (geo/geofence/tracking events), or * for all. Supports prefix wildcards (e.g. jobs.*).
curl -X POST https://api.saasignal.saastemly.com/infra/webhooks \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"example","url":"https://app.acme.com/webhooks/saasignal","topics":["kv:write"]}'
{ "status": "ok" }
await ss.infra.webhooks.create({
name: 'order-events',
url: 'https://app.acme.com/webhooks/saasignal',
topics: ['kv.set', 'jobs.*'],
secret: 'whsec_...',
})
- Open Dashboard and select your project
- Go to Webhooks in the sidebar
- Click Add Webhook
- Enter a name, endpoint URL, and select the topics to subscribe to
- Click Create
name requiredurl requiredtopics requiredsecretenabledtrue.List Webhooks
List all webhooks for the project.
curl https://api.saasignal.saastemly.com/infra/webhooks \
-H "Authorization: Bearer sk_live_..."
{ "status": "ok" }
await ss.infra.webhooks.list()
- Open Dashboard and select your project
- Go to Webhooks to see all registered webhooks with their status and topics
limit25.25cursorenabledtrue, falseGet Webhook
Retrieve a single webhook with delivery stats.
curl https://api.saasignal.saastemly.com/infra/webhooks/{webhook_id} \
-H "Authorization: Bearer sk_live_..."
{ "status": "ok" }
await ss.infra.webhooks.get('wh_01JNXS...')
- Open Dashboard and select your project
- Go to Webhooks and click on any webhook to view its details, secret, and delivery history
webhook_id requiredUpdate Webhook
Update webhook fields.
curl -X PATCH https://api.saasignal.saastemly.com/infra/webhooks/{webhook_id} \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{}'
{ "status": "ok" }
await ss.infra.webhooks.update('wh_01JNXS...', { enabled: false })
- Open Dashboard and select your project
- Go to Webhooks and click on the webhook
- Edit the URL, topics, or toggle enabled/disabled
- Click Save
webhook_id requirednameurltopicssecretenabledDelete Webhook
Permanently delete a webhook and its delivery history.
curl -X DELETE https://api.saasignal.saastemly.com/infra/webhooks/{webhook_id} \
-H "Authorization: Bearer sk_live_..."
await ss.infra.webhooks.delete('wh_01JNXS...')
- Open Dashboard and select your project
- Go to Webhooks and click on the webhook
- Click Delete to remove it
webhook_id requiredTest Webhook
Send a test ping to the webhook URL and return the response status.
curl -X POST https://api.saasignal.saastemly.com/infra/webhooks/{webhook_id}/test \
-H "Authorization: Bearer sk_live_..."
{ "status": "ok" }
await ss.infra.webhooks.test('wh_01JNXS...')
- Open Dashboard and select your project
- Go to Webhooks and click on the webhook
- Click Test to send a
test.pingevent
webhook_id requiredtest.ping event toList Deliveries
Paginated delivery log for a webhook.
curl https://api.saasignal.saastemly.com/infra/webhooks/{webhook_id}/deliveries \
-H "Authorization: Bearer sk_live_..."
{ "status": "ok" }
await ss.infra.webhooks.listDeliveries('wh_01JNXS...')
- Open Dashboard and select your project
- Go to Webhooks and click on a webhook
- The Deliveries tab shows all delivery attempts with status, timing, and response codes
webhook_id requiredlimit25.25cursorstatussuccess or failedRetry Delivery
Re-dispatch a failed webhook delivery.
curl -X POST https://api.saasignal.saastemly.com/infra/webhooks/{webhook_id}/deliveries/{delivery_id}/retry \
-H "Authorization: Bearer sk_live_..."
{ "status": "ok" }
await ss.infra.webhooks.retryDelivery('wh_01JNXS...', 'dlv_01JNXS...')
- Open Dashboard and select your project
- Go to Webhooks → click on a webhook → Deliveries
- Click Retry next to a failed delivery
webhook_id requireddelivery_id required