Manage subscriptions
Use these endpoints to create, list, update, pause, and delete webhook subscriptions, and to manage their signing secrets.
Webhook management endpoints use the same team API key authentication as the rest of the Scribeless API.
X-API-Key: YOUR_API_KEY
List event types
GET https://platform.scribeless.co/api/webhooks/event-types
Returns every event type you can subscribe to. Two of the seven entries are shown here.
[
{
"type": "recipient.created",
"label": "Recipient created",
"description": "A recipient was added to a campaign."
},
{
"type": "qr_code.scanned",
"label": "QR code scanned",
"description": "A recipient scanned a Smart QR code on their note."
}
]
Create a subscription
POST https://platform.scribeless.co/api/webhooks
Content-Type: application/json
X-API-Key: YOUR_API_KEY
| Field | Type | Description |
|---|---|---|
url | string | Public HTTPS endpoint that should receive webhook deliveries. Up to 2048 characters. |
event_types | array | Required. One or more event type strings. |
description | string | Optional. A note to help you recognise the subscription. Up to 255 characters. |
Integrations that send a single event_type string instead of event_types keep working; it is treated as a one-item event_types list.
curl --request POST 'https://platform.scribeless.co/api/webhooks' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"url": "https://example.com/scribeless/webhooks",
"event_types": ["recipient.ready", "recipient.shipped"],
"description": "CRM sync"
}'
Successful requests return 201 Created with the subscription and its signing secret.
{
"id": "WEBHOOK_SUBSCRIPTION_ID",
"team_id": "TEAM_ID",
"event_types": ["recipient.ready", "recipient.shipped"],
"url": "https://example.com/scribeless/webhooks",
"description": "CRM sync",
"status": "active",
"disabled_reason": null,
"created_at": "2026-01-01T10:00:00.000000+00:00",
"updated_at": "2026-01-01T10:00:00.000000+00:00",
"secret": "whsec_SIGNING_SECRET"
}
Store secret securely. List, fetch, and update responses do not include it; use Get the signing secret to fetch it again.
List subscriptions
GET https://platform.scribeless.co/api/webhooks
curl --request GET 'https://platform.scribeless.co/api/webhooks' \
--header 'X-API-Key: YOUR_API_KEY'
The response is an array of non-deleted subscriptions.
[
{
"id": "WEBHOOK_SUBSCRIPTION_ID",
"team_id": "TEAM_ID",
"event_types": ["recipient.ready", "recipient.shipped"],
"url": "https://example.com/scribeless/webhooks",
"description": "CRM sync",
"status": "active",
"disabled_reason": null,
"created_at": "2026-01-01T10:00:00.000000+00:00",
"updated_at": "2026-01-01T10:00:00.000000+00:00"
}
]
Fetch a subscription
GET https://platform.scribeless.co/api/webhooks/{webhookId}
curl --request GET 'https://platform.scribeless.co/api/webhooks/WEBHOOK_SUBSCRIPTION_ID' \
--header 'X-API-Key: YOUR_API_KEY'
Returns one subscription in the same shape as the list response.
| Field | Description |
|---|---|
status | active or inactive. Inactive subscriptions receive no deliveries. |
disabled_reason | Why Scribeless disabled the subscription, or null. Set when deliveries have failed continuously for 5 days. |
Update a subscription
PATCH https://platform.scribeless.co/api/webhooks/{webhookId}
Use this endpoint to change the delivery URL, event types, or description, or to switch a subscription between active and inactive.
curl --request PATCH 'https://platform.scribeless.co/api/webhooks/WEBHOOK_SUBSCRIPTION_ID' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"event_types": ["recipient.created", "recipient.shipped"]
}'
| Field | Type | Description |
|---|---|---|
url | string | Optional. New public HTTPS endpoint. |
event_types | array | Optional. Event type strings. Replaces the subscribed event types. |
description | string or null | Optional. New description. Send null or an empty string to clear it. |
status | string | Optional. active or inactive. |
Send at least one field. Setting status to active on a subscription Scribeless disabled clears disabled_reason. Once it is re-enabled, resend any deliveries you missed.
Delete a subscription
DELETE https://platform.scribeless.co/api/webhooks/{webhookId}
curl --request DELETE 'https://platform.scribeless.co/api/webhooks/WEBHOOK_SUBSCRIPTION_ID' \
--header 'X-API-Key: YOUR_API_KEY'
Successful deletes return 204 No Content. Pending deliveries for a deleted subscription are not sent.
Get the signing secret
GET https://platform.scribeless.co/api/webhooks/{webhookId}/secret
curl --request GET 'https://platform.scribeless.co/api/webhooks/WEBHOOK_SUBSCRIPTION_ID/secret' \
--header 'X-API-Key: YOUR_API_KEY'
{
"secret": "whsec_SIGNING_SECRET",
"previous_secret_expires_at": null
}
previous_secret_expires_at is set while a rotation overlap is in progress.
Rotate the signing secret
POST https://platform.scribeless.co/api/webhooks/{webhookId}/secret/rotate
Issues a new signing secret. By default the previous secret stops working immediately, which is what you want if a secret has leaked.
For a planned rotation, ask for an overlap. Until it ends, each delivery carries a signature for both the new and the previous secret, so you can deploy the new secret without dropping events.
| Field | Type | Description |
|---|---|---|
previous_secret_expires_in_hours | integer | Optional. How long the previous secret keeps signing, from 0 to 168. Defaults to 0. |
curl --request POST 'https://platform.scribeless.co/api/webhooks/WEBHOOK_SUBSCRIPTION_ID/secret/rotate' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: YOUR_API_KEY' \
--data '{
"previous_secret_expires_in_hours": 24
}'
{
"secret": "whsec_NEW_SIGNING_SECRET",
"previous_secret_expires_at": "2026-01-02T10:00:00.000Z"
}
Status codes
| Status | Meaning |
|---|---|
200 | Request succeeded. |
201 | Subscription created. |
204 | Subscription deleted. |
400 | Invalid payload, invalid event type, the URL is not a public HTTPS URL, or the team already has 10 subscriptions. |
401 | Missing, malformed, invalid, or unauthorized API key. |
404 | Webhook subscription not found. |
409 | A non-deleted subscription already exists for the same URL, or the secret changed during a rotation. Retry the rotation. |
500 | Webhook operation failed unexpectedly. Retry or contact support if it persists. |
Next step
After creating a subscription, use Receive deliveries to verify and process incoming requests.