Webhooks
Receive signed HTTP notifications when your posts are published, scheduled or fail, and when an image finishes generating, then verify each payload signature.
https://post.adaptlypost.com/post/api/v1/webhooksRegister a webhook endpoint. Every webhook receives all events, signed with its secret.
Creating, updating, deleting and testing a webhook need webhooks.manage (Admin and Editor). Listing and reading webhooks need webhooks.read, which Contributor keys do not hold.
Body Parameters
| Parameter | Type | Description |
|---|---|---|
urlREQUIRED | string | Publicly reachable http(s) endpoint that will receive event deliveries. Private hosts are rejected. Max 10 webhooks per workspace. |
Events
Every registered webhook receives all of the following events. The event name is sent in the payload and in the x-adaptly-event header, so you can filter on your side.
| Event | Description |
|---|---|
post.published | All platforms of the post published successfully |
post.partially_failed | Some platforms published, others failed |
post.failed | Publishing failed on all platforms |
post.scheduled | A post was scheduled for a future date |
account.unauthorized | A platform rejected an account's token; the account is unauthorized until it is reconnected |
image.completed | An image started with POST /ai/images finished; data.image.imageUrl is ready to use |
image.failed | An image started with POST /ai/images failed; data.image.error says why |
Event payload
Every delivery is a JSON body with id, event, createdAt and data. data carries post, the full post in the same shape as GET /api/v1/social-posts/:id, for post.* events; account (id, platform, displayName, pageId for Facebook, status and the platform's reason) for account.unauthorized; and image (jobId, sessionId, prompt, then imageUrl and imageId, or error) for image.* events. A test delivery sends the event webhook.test with the webhook id and the list of events.
Verifying Signatures
Every delivery is signed with your webhook secret (whsec_...). Compute an HMAC-SHA256 over "{timestamp}.{rawBody}" and compare it to the x-adaptly-signature header before trusting the payload.
The Secret Is Shown Only Once
The signing secret (whsec_...) is returned only in the response to the create request, never in list, get, or update responses. Store it securely. If you lose it, delete the webhook and create a new one.const crypto = require('crypto');
const expected =
'sha256=' +
crypto
.createHmac('sha256', webhookSecret)
.update(`${req.headers['x-adaptly-timestamp']}.${rawBody}`)
.digest('hex');
const isValid = expected === req.headers['x-adaptly-signature'];Delivery and Retries
Your endpoint must respond with a 2xx status within 10 seconds. Failed deliveries are retried up to 5 times with exponential backoff. Deliveries can arrive more than once, make your handler idempotent.
Auto-Disable
After 20 consecutive failed deliveries the webhook is automatically disabled. Re-enable it via PATCH { "active": true } or from the dashboard.Managing Webhooks
Webhooks are managed with the following endpoints, using the same API key authentication:
GET /api/v1/webhooks # list registered webhooks
GET /api/v1/webhooks/:id # get one webhook
PATCH /api/v1/webhooks/:id # update url or active
DELETE /api/v1/webhooks/:id # delete a webhook
POST /api/v1/webhooks/:id/test # send a signed webhook.test eventYou can also manage webhooks visually from the dashboard, in the API Tokens page.
OpenAPI Specification
A machine-readable OpenAPI 3.0 spec of the entire REST API: including webhooks and the event payload schema, is publicly available. Import it into Make, n8n, or any OpenAPI-compatible tool to scaffold an integration.
curl https://post.adaptlypost.com/post/api/v1/openapi.jsoncurl --request POST \
--url https://post.adaptlypost.com/post/api/v1/webhooks \
--header 'Authorization: Bearer <api-key>' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://your-server.com/webhook"
}'curl --request POST \
--url https://post.adaptlypost.com/post/api/v1/webhooks/<webhook-id>/test \
--header 'Authorization: Bearer <api-key>'POST <your-url>
x-adaptly-event: post.published
x-adaptly-webhook-id: wh_abc123
x-adaptly-timestamp: 1784643600
x-adaptly-signature: sha256=3f5a...
{
"id": "deliver-webhook-...",
"event": "post.published",
"createdAt": "2026-07-21T14:20:00.000Z",
"data": {
"post": {
"id": "post_xyz789",
"status": "COMPLETED",
"recurringPostId": "rp_abc123",
"occurrenceAt": "2026-07-21T14:19:00.000Z",
"platforms": [
{
"platform": "TWITTER",
"status": "PUBLISHED",
"platformPostId": "1234567890",
"publishedAt": "2026-07-21T14:19:58.000Z"
}
]
}
}
}
POST <your-url>
x-adaptly-event: account.unauthorized
{
"id": "deliver-webhook-...",
"event": "account.unauthorized",
"createdAt": "2026-09-13T09:10:00.000Z",
"data": {
"account": {
"id": "conn_jkl012",
"platform": "FACEBOOK",
"displayName": "Your Page",
"pageId": "123456789012345",
"status": "unauthorized",
"reason": "Error validating access token: Sessions for the user are not allowed because the user is not a confirmed user."
}
}
}
POST <your-url>
x-adaptly-event: image.completed
{
"id": "deliver-webhook-...",
"event": "image.completed",
"createdAt": "2026-09-20T10:02:31.000Z",
"data": {
"image": {
"jobId": "generate-image-8f2a1c40-6d3b-4e91-b7c2-0a5d9e13f846",
"sessionId": "b31c7a44-2f19-4c85-9d60-7e2af4c81b93",
"prompt": "a red bicycle leaning against a yellow wall, soft morning light",
"imageUrl": "https://cdn.adaptlypost.com/ai-images/ai-studio-4c81b93.png",
"imageId": "d7e44a10-93bc-4f27-8ae5-1b06c2f4d938"
}
}
}{
"id": "wh_abc123",
"url": "https://your-server.com/webhook",
"active": true,
"secret": "whsec_c99807...",
"createdAt": "2026-07-21T14:00:00.000Z",
"updatedAt": "2026-07-21T14:00:00.000Z",
"lastSuccessAt": null,
"lastFailureAt": null,
"disabledAt": null
}