Webhook API
List endpoints, inspect deliveries, and manage webhook subscriptions via the REST API.
List endpoints
Authorization: Bearer sty_live_your_api_key[
{
"id": "wh_ep_abc123",
"url": "https://your-app.com/webhooks/styrar",
"description": "Production CRM sync",
"enabled": true,
"eventTypes": ["link.clicked", "link.created"],
"secretPrefix": "whsec_l",
"companyId": "cmxyz_company",
"userId": null,
"disabledAt": null,
"createdAt": "2026-06-22T12:00:00.000Z",
"updatedAt": "2026-06-22T12:00:00.000Z"
}
]Receive an event on your server
When a subscribed event fires, Styrar POSTs to your endpoint URL. This is the payload your handler receives:
Content-Type: application/json
Styrar-Event-Id: evt_outbox_abc123
Styrar-Event-Type: link.clicked
Styrar-Signature: t=1719052800,v1=8f4b2c1a9e0d3f7b6a5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3
User-Agent: Styrar-Webhooks/1.0
{
"id": "evt_outbox_abc123",
"type": "link.clicked",
"api_version": "2026-06-22",
"created_at": "2026-06-22T12:00:00.000Z",
"workspace": {
"type": "company",
"company_id": "cmxyz_company"
},
"data": {
"object": {
"id": "clink_abc123",
"link_id": "clink_abc123",
"short_code": "summer",
"title": "Summer sale",
"country": "NL",
"city": "Amsterdam",
"device": "mobile",
"browser": "Chrome",
"os": "iOS",
"referrer": "https://instagram.com/",
"routing_rule_id": null,
"experiment_variant_id": null,
"clicked_at": "2026-06-22T12:00:00.000Z"
}
}
}{
"received": true
}Your response body can be empty. Return any 2xx status after you verify the signature and accept the event. Styrar retries on non-2xx responses.
Test ping payload
A Send test action delivers webhook.test with a smaller payload:
Content-Type: application/json
Styrar-Event-Id: evt_test_abc123
Styrar-Event-Type: webhook.test
Styrar-Signature: t=1719052800,v1=...
{
"id": "evt_test_abc123",
"type": "webhook.test",
"api_version": "2026-06-22",
"created_at": "2026-06-22T12:00:00.000Z",
"workspace": {
"type": "company",
"company_id": "cmxyz_company"
},
"data": {
"object": {
"endpoint_id": "wh_ep_abc123",
"message": "Styrar webhook test ping"
}
}
}List recent deliveries
Authorization: Bearer sty_live_your_api_key[
{
"id": "wh_del_abc123",
"endpointId": "wh_ep_abc123",
"outboxEventId": "wh_out_abc123",
"eventType": "link.clicked",
"status": "delivered",
"attemptCount": 1,
"lastStatusCode": 200,
"lastError": null,
"durationMs": 142,
"nextAttemptAt": null,
"deliveredAt": "2026-06-22T12:00:01.000Z",
"createdAt": "2026-06-22T12:00:00.500Z"
}
]Managing endpoints
GET /v1/webhooks/endpoints?companyId={id}
POST /v1/webhooks/endpoints
GET /v1/webhooks/endpoints/:id
PATCH /v1/webhooks/endpoints/:id
DELETE /v1/webhooks/endpoints/:id
POST /v1/webhooks/endpoints/:id/test
POST /v1/webhooks/endpoints/:id/rotate-secret
| Field | Description |
|---|---|
url | HTTPS callback URL |
description | Optional label |
eventTypes | Array of subscribed event types; empty means all events |
enabled | Default true |
The signing secret (whsec_live_… / whsec_test_…) is returned exactly once on create and on rotate-secret. You can register up to 25 endpoints per workspace scope.
Deliveries
GET /v1/webhooks/deliveries?endpointId={id}
GET /v1/webhooks/deliveries/:id
POST /v1/webhooks/deliveries/:id/retry
Each delivery row tracks status, attemptCount, nextAttemptAt, lastStatusCode, lastError, and deliveredAt. Inspect failures in the dashboard under Settings → Webhooks or retry via the API.
Delivery format
Each live event is an HTTP POST to your callback URL. Headers and body are shown in Receive an event on your server above.
| Header | Description |
|---|---|
Styrar-Event-Id | Unique event id (use for deduplication) |
Styrar-Event-Type | e.g. link.clicked |
Styrar-Signature | t={unix_ts},v1={hmac_sha256_hex} |
User-Agent | Styrar-Webhooks/1.0 |
Envelope fields:
| Field | Description |
|---|---|
id | Event id (matches Styrar-Event-Id) |
type | Event type string |
api_version | Payload schema version |
created_at | ISO 8601 timestamp |
workspace | company or personal scope |
data.object | Event-specific payload |
Click payloads include geo and device dimensions, not raw IP addresses.