Events
Every delivery is a POST to your webhook URL with a JSON body. The envelope is the same for all types; data differs per type.
Envelope
Section titled “Envelope”{ "id": "evt1a3c5e7g9i2k", "type": "post.published", "created_at": "2026-08-25T09:20:11Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": {}}| Field | Notes |
|---|---|
id |
Event id. Same on every retry of this event. Also in X-MissLess-Delivery |
type |
One of the types below. Also in X-MissLess-Event |
created_at |
When the event happened, UTC |
partner |
Your partner slug |
workspace |
The workspace id, or null for ping |
external_id |
The workspace’s external_id, so you can route without a lookup. null if you did not set one |
data |
The object the event is about |
Headers
Section titled “Headers”| Header | Value |
|---|---|
Content-Type |
application/json |
X-MissLess-Event |
The event type |
X-MissLess-Delivery |
The event id. Use it to de-duplicate |
X-MissLess-Timestamp |
Unix seconds at the moment of sending |
X-MissLess-Signature |
sha256=<hex>, the HMAC-SHA256 of "<timestamp>.<raw body>" with your secret. See Verify signatures |
| Type | When | data |
|---|---|---|
ping |
You called POST /v1/webhook/test |
{ "message": "MissLess Social webhook test", "sent_at": "..." } |
account.connected |
A user connected a Page or Instagram account through a connect link or the widget | { account } |
account.disconnected |
An account was disconnected through the API, the connect page, the widget, or by the user revoking access on Meta’s side | { account }, plus reason: "deauthorized" when Meta initiated it |
account.expired |
A token passed its expiry and the account is no longer usable | { account, error } |
post.published |
Every target of a post succeeded | { post } |
post.partial |
Some targets succeeded, some failed | { post } |
post.failed |
Every target failed | { post } |
message.received |
A DM arrived | { conversation, message } |
comment.received |
A comment or a reply in a comment thread arrived | { conversation, message } |
message.sent |
An outbound message was sent from any surface | { conversation, message } |
The account and post objects inside data are the same shapes as GET /v1/accounts/:id and GET /v1/posts/:id at the moment of the event. Inbox payloads are on Webhooks for the inbox.
account.connected
Section titled “account.connected”{ "id": "evt5e7g9i2k4m6p", "type": "account.connected", "created_at": "2026-08-25T09:15:41Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": { "account": { "id": "acig4h2k5m7p9r1", "workspace": "ws7k2m9p4q1r8t3", "network": "instagram", "platform_id": "17841400000000001", "username": "salonnova", "display_name": "Salon Nova", "avatar_url": "https://scontent.example/avatar.jpg", "page_id": "100000000000001", "status": "active", "last_error": null, "scopes": ["instagram_basic", "instagram_content_publish", "instagram_manage_comments", "instagram_manage_messages", "instagram_manage_insights"], "token_expires_at": null, "connected_at": "2026-08-25T09:15:41Z" } }}One event per account. A user who grants a Page with a linked Instagram account produces two.
account.disconnected
Section titled “account.disconnected”{ "id": "evt6f8h1j3l5n7q", "type": "account.disconnected", "created_at": "2026-09-02T14:03:10Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": { "account": { "id": "acfb8n2c4v6b1m3", "workspace": "ws7k2m9p4q1r8t3", "network": "facebook", "platform_id": "100000000000001", "username": "salonnova", "display_name": "Salon Nova", "avatar_url": "https://scontent.example/page.jpg", "page_id": "100000000000001", "status": "revoked", "last_error": "User removed the app", "scopes": [], "token_expires_at": null, "connected_at": "2026-08-25T09:15:41Z" } }}Remove the account from your UI and offer a reconnect button. Scheduled posts targeting it will fail for that target.
account.expired
Section titled “account.expired”{ "id": "evt7g9i2k4m6p8r", "type": "account.expired", "created_at": "2026-10-24T03:00:00Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": { "account": { "id": "acig4h2k5m7p9r1", "workspace": "ws7k2m9p4q1r8t3", "network": "instagram", "platform_id": "17841400000000001", "username": "salonnova", "display_name": "Salon Nova", "avatar_url": "https://scontent.example/avatar.jpg", "page_id": "100000000000001", "status": "expired", "last_error": "token expired", "scopes": ["instagram_basic", "instagram_content_publish"], "token_expires_at": "2026-10-24T02:58:12Z", "connected_at": "2026-08-25T09:15:41Z" }, "error": "token expired" }}Page-derived tokens normally do not expire, so this is rare. When it happens the fix is the same as for revoked: a new connect link.
post.published
Section titled “post.published”{ "id": "evt1a3c5e7g9i2k", "type": "post.published", "created_at": "2026-08-25T09:20:11Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": { "post": { "id": "pst5g7j9l2n4q6s", "workspace": "ws7k2m9p4q1r8t3", "external_ref": "acme:post:1234", "caption": "Fresh cuts, Friday walk-ins welcome", "media": [{ "id": "med9x2c4v6b8n1m", "kind": "image", "mime": "image/jpeg", "width": 1080, "height": 1350 }], "targets": [ { "account": "acig4h2k5m7p9r1", "network": "instagram", "username": "salonnova", "status": "published", "platform_post_id": "17900000000000001", "permalink": "https://www.instagram.com/p/C_abc123/", "error": null, "published_at": "2026-08-25T09:20:11Z" }, { "account": "acfb8n2c4v6b1m3", "network": "facebook", "username": "salonnova", "status": "published", "platform_post_id": "100000000000001_200000000000002", "permalink": "https://www.facebook.com/100000000000001/posts/200000000000002", "error": null, "published_at": "2026-08-25T09:20:09Z" } ], "schedule_at": null, "status": "published", "published_at": "2026-08-25T09:20:11Z", "attempts": 1, "last_error": null, "created_by": "api", "created": "2026-08-25T09:19:58Z", "updated": "2026-08-25T09:20:11Z" } }}Look up your own record by external_ref and store permalink and platform_post_id per target.
post.partial
Section titled “post.partial”Same payload as post.published with status: "partial" and a mix of published and failed targets. The failed target carries Meta’s message in error.
{ "id": "evt8h1j3l5n7q9s", "type": "post.partial", "created_at": "2026-08-25T09:20:11Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": { "post": { "id": "pst5g7j9l2n4q6s", "external_ref": "acme:post:1234", "status": "partial", "targets": [ { "account": "acig4h2k5m7p9r1", "network": "instagram", "username": "salonnova", "status": "published", "platform_post_id": "17900000000000001", "permalink": "https://www.instagram.com/p/C_abc123/", "error": null, "published_at": "2026-08-25T09:20:11Z" }, { "account": "acfb8n2c4v6b1m3", "network": "facebook", "username": "salonnova", "status": "failed", "platform_post_id": null, "permalink": null, "error": "(#200) The user hasn't authorized the application to perform this action", "published_at": null } ], "last_error": "facebook: (#200) The user hasn't authorized the application to perform this action", "attempts": 1 } }}post.failed
Section titled “post.failed”Same payload with status: "failed"; every target is failed.
{ "id": "evt9i2k4m6p8r1t", "type": "post.failed", "created_at": "2026-09-01T09:00:42Z", "partner": "acme", "workspace": "ws7k2m9p4q1r8t3", "external_id": "user_123", "data": { "post": { "id": "pst6h8k1m3p5r7t", "external_ref": "acme:post:1235", "status": "failed", "schedule_at": "2026-09-01T09:00:00Z", "targets": [ { "account": "acig4h2k5m7p9r1", "network": "instagram", "username": "salonnova", "status": "failed", "platform_post_id": null, "permalink": null, "error": "The image aspect ratio is not supported", "published_at": null } ], "last_error": "instagram: The image aspect ratio is not supported", "attempts": 1 } }}A failed post is not retried on its own. Patch it and call POST /v1/posts/:id/publish; see Scheduling.
message.received, comment.received, message.sent
Section titled “message.received, comment.received, message.sent”Full examples on Webhooks for the inbox.