Webhook payloads
Every delivery is an HTTP POST with a JSON body in one envelope. The event field tells you which payload shape to expect. This page lists every field. To register an endpoint, see How to set up webhooks. To verify the signature, see Verifying signatures.
What does the delivery envelope look like?
{
"event": "upload.completed",
"payload": { "...": "event-specific, see below" },
"timestamp": "2026-11-13T09:00:06.267Z",
"deliveryId": "6d0a8f2e..."
}| Field | Type | Meaning |
|---|---|---|
event | string | One of the five event names below. |
payload | object | Event data. |
timestamp | ISO 8601 string | When the delivery was created. Identical across retries. |
deliveryId | string | Unique ID for the delivery. Use it to deduplicate. |
Which headers come with each request?
| Header | Value |
|---|---|
Content-Type | application/json |
X-Webhook-Signature | sha256=<hex>, HMAC-SHA256 of the raw body with your webhook secret |
X-Webhook-Event | The event name |
X-Webhook-Delivery | The delivery ID |
What is in an upload.* payload?
upload.completed, upload.failed and upload.partial_failure fire once when the whole post ends, with the same shape.
| Field | Type | Meaning |
|---|---|---|
uploadId | string | The post ID. |
type | string | video, photo, text or document. |
status | string | completed, failed or partial_failure. |
summary.total | number | Channels in the post. |
summary.succeeded | number | Channels that published. |
summary.failed | number | Channels that failed. |
channels[] | array | One entry per account. |
channels[].platform | string | Platform name, for example instagram. |
channels[].targetName | string or null | Account or page name. |
channels[].status | string | success or failed. |
channels[].postUrl | string or null | Link to the published post. |
channels[].error | string or null | Failure text. |
channels[].publishedAt | string or null | Publish time. |
{
"event": "upload.partial_failure",
"payload": {
"uploadId": "6a05032a84584482ace13d5f",
"type": "photo",
"status": "partial_failure",
"summary": { "total": 2, "succeeded": 1, "failed": 1 },
"channels": [
{
"platform": "instagram",
"targetName": "@mybrand",
"status": "success",
"postUrl": "https://instagram.com/p/DEF123/",
"error": null,
"publishedAt": "2026-11-13T09:00:05.000Z"
},
{
"platform": "x",
"targetName": "@myhandle",
"status": "failed",
"postUrl": null,
"error": "reconnect_required: x-myhandle — x rejected the saved credentials ...",
"publishedAt": null
}
]
},
"timestamp": "2026-11-13T09:00:06.267Z",
"deliveryId": "6d0a8f2e..."
}What is in a platform.* payload?
platform.success and platform.failed fire for each account as soon as it finishes, before the upload-level event.
| Field | Type | Meaning |
|---|---|---|
uploadId | string | The post ID. |
type | string | Post type. |
platform | string | Platform name. |
status | string | success or failed. |
postUrl | string or null | Link on success. |
error | string or null | Failure text on failure. |
note | string or null | Extra context, for example a TikTok post that lands in the app inbox as a platform draft. |
{
"event": "platform.failed",
"payload": {
"uploadId": "6a05032a84584482ace13d5f",
"type": "photo",
"platform": "instagram",
"status": "failed",
"postUrl": null,
"error": "Requires instagram_content_publish permission",
"note": null
},
"timestamp": "2026-11-13T09:00:04.000Z",
"deliveryId": "6d0a8f30..."
}A platform event carries no connection slug, only the platform name. To find the account, fetch the post with GET /api/content/:id and read its channels.
How are deliveries retried?
Socifyr waits up to 10 seconds for your endpoint. Any non-2xx response or timeout counts as a failure and triggers up to 5 retries with exponential backoff starting at 10 seconds. The last 50 attempts per endpoint are visible at GET /api/webhooks/:id/deliveries, and delivery records are kept for 30 days.
Make your handler idempotent on deliveryId, because a retry can arrive after your handler already did the work.
FAQ
Can I filter webhooks by account?
No. Filter on payload.platform or fetch the post in your handler.
Which plan has webhooks?
Business. See limits.