Webhook event catalog
Every webhook event uses the same envelope. The type field identifies the event; data contains the event-specific payload.
{
"id": "evt_abc123",
"type": "<event-type>",
"createdAt": "2026-06-01T14:00:00Z",
"data": { ... }
}All delivery requests include the headers documented in Delivery Headers. Always verify X-VoxBurst-Signature before processing.
post.created
Fires when: A post is successfully created (draft or scheduled) via POST /v1/posts or POST /v1/posts/bulk.
{
"id": "evt_abc001",
"type": "post.created",
"createdAt": "2026-06-01T10:00:00Z",
"data": {
"id": "post_abc123",
"workspaceId": "ws_xyz",
"content": "Check out our new launch! 🚀",
"status": "DRAFT",
"scheduledFor": null
}
}| Field | Type | Description |
|---|---|---|
id | string | Post ID |
workspaceId | string | Workspace that owns the post |
content | string | Post text content |
status | string | "DRAFT" or "SCHEDULED" |
scheduledFor | string | null | ISO 8601 scheduled time, or null if draft |
post.scheduled
Fires when: A post transitions to scheduled status — either created with a scheduledFor time, or updated from draft to scheduled.
{
"id": "evt_abc002",
"type": "post.scheduled",
"createdAt": "2026-06-01T10:05:00Z",
"data": {
"id": "post_abc123",
"workspaceId": "ws_xyz",
"content": "Check out our new launch! 🚀",
"status": "SCHEDULED",
"scheduledFor": "2026-06-15T14:00:00Z"
}
}Same schema as post.created. scheduledFor is always set.
post.published
Fires when: Publishing completes — all platforms succeeded ("PUBLISHED") or at least one succeeded with at least one failed ("PARTIAL").
There is no separate post.partial event. Check data.status in every post.published handler to detect partial failures. Always inspect data.platforms for per-platform outcomes.
All platforms succeeded (status: "PUBLISHED")
{
"id": "evt_abc003",
"type": "post.published",
"createdAt": "2026-06-15T14:00:05Z",
"data": {
"id": "post_abc123",
"workspaceId": "ws_xyz",
"content": "Check out our new launch! 🚀",
"status": "PUBLISHED",
"publishedAt": "2026-06-15T14:00:05Z",
"platforms": [
{
"platform": "TWITTER",
"status": "PUBLISHED",
"platformPostId": "1234567890123456789",
"platformPostUrl": "https://x.com/user/status/1234567890123456789",
"publishedAt": "2026-06-15T14:00:04Z"
},
{
"platform": "INSTAGRAM",
"status": "PUBLISHED",
"platformPostId": "17854360229135492",
"platformPostUrl": "https://www.instagram.com/p/ABC123/",
"publishedAt": "2026-06-15T14:00:05Z"
}
]
}
}Partial failure (status: "PARTIAL")
{
"id": "evt_abc004",
"type": "post.published",
"createdAt": "2026-06-15T14:00:06Z",
"data": {
"id": "post_abc123",
"workspaceId": "ws_xyz",
"content": "Check out our new launch! 🚀",
"status": "PARTIAL",
"publishedAt": "2026-06-15T14:00:06Z",
"platforms": [
{
"platform": "TWITTER",
"status": "PUBLISHED",
"platformPostId": "1234567890123456789",
"platformPostUrl": "https://x.com/user/status/1234567890123456789",
"publishedAt": "2026-06-15T14:00:04Z"
},
{
"platform": "INSTAGRAM",
"status": "FAILED",
"error": {
"code": "MEDIA_REJECTED",
"message": "Media format not supported: image must be JPEG"
}
}
]
}
}| Field | Type | Description |
|---|---|---|
id | string | Post ID |
workspaceId | string | Workspace ID |
content | string | Post text |
status | string | "PUBLISHED" (all succeeded) or "PARTIAL" (some failed) |
publishedAt | string | ISO 8601 completion timestamp |
platforms[] | array | Per-platform publish results |
platforms[].platform | string | Platform constant — UPPERCASE (e.g. "TWITTER") |
platforms[].status | string | "PUBLISHED" or "FAILED" — UPPERCASE |
platforms[].platformPostId | string | undefined | Platform’s native post ID (success only) |
platforms[].platformPostUrl | string | undefined | Public URL of the post (success only) |
platforms[].publishedAt | string | undefined | ISO 8601 timestamp (success only) |
platforms[].error | object | undefined | { code, message } — failure only |
Platform and status strings in webhook payloads are always UPPERCASE. This differs from REST API responses, which use lowercase.
post.failed
Fires when: Publishing completed and all platforms failed.
{
"id": "evt_abc005",
"type": "post.failed",
"createdAt": "2026-06-15T14:00:08Z",
"data": {
"id": "post_abc123",
"workspaceId": "ws_xyz",
"content": "Check out our new launch! 🚀",
"status": "FAILED",
"publishedAt": "2026-06-15T14:00:08Z",
"platforms": [
{
"platform": "TWITTER",
"status": "FAILED",
"error": {
"code": "ACCOUNT_DISCONNECTED",
"message": "OAuth token expired or revoked"
}
},
{
"platform": "INSTAGRAM",
"status": "FAILED",
"error": {
"code": "PUBLISH_ERROR",
"message": "Media format not supported"
}
}
]
}
}Same schema as post.published. Use POST /v1/posts/:id/retry or POST /v1/posts/:id/platforms/:id/fix to recover.
post.draft.approved
Fires when: A post in an approval workflow reaches its final approval step and is queued for publishing.
{
"id": "evt_abc006",
"type": "post.draft.approved",
"createdAt": "2026-06-01T11:30:00Z",
"data": {
"postId": "post_abc123",
"approverId": "usr_approver1",
"stepOrder": 2,
"comment": "Looks good, approved."
}
}| Field | Type | Description |
|---|---|---|
postId | string | Post that was approved |
approverId | string | null | User ID who approved, or null if system-approved |
stepOrder | integer | Which approval step was completed |
comment | string | null | Reviewer’s comment, if any |
account.connected
Fires when: A social account is successfully connected via the OAuth callback.
{
"id": "evt_abc007",
"type": "account.connected",
"createdAt": "2026-06-01T09:00:00Z",
"data": {
"accountId": "acc_abc123",
"workspaceId": "ws_xyz",
"platform": "INSTAGRAM",
"username": "brandname"
}
}| Field | Type | Description |
|---|---|---|
accountId | string | VoxBurst account ID |
workspaceId | string | Workspace ID |
platform | string | Platform constant — UPPERCASE |
username | string | null | Platform username or handle |
account.disconnected
Fires when: A social account is disconnected via DELETE /v1/accounts/:id or revoked by the platform.
{
"id": "evt_abc008",
"type": "account.disconnected",
"createdAt": "2026-06-01T15:00:00Z",
"data": {
"accountId": "acc_abc123",
"workspaceId": "ws_xyz",
"platform": "TWITTER",
"reason": "user_disconnected"
}
}| Field | Type | Description |
|---|---|---|
accountId | string | VoxBurst account ID |
workspaceId | string | Workspace ID |
platform | string | Platform constant — UPPERCASE |
reason | string | "user_disconnected", "token_revoked", "token_expired", or "platform_suspended" |
account.error
Fires when: A connected account encounters a token error (expired, revoked) that prevents publishing.
{
"id": "evt_abc009",
"type": "account.error",
"createdAt": "2026-06-01T16:00:00Z",
"data": {
"accountId": "acc_abc123",
"workspaceId": "ws_xyz",
"platform": "LINKEDIN",
"error": "Token expired"
}
}| Field | Type | Description |
|---|---|---|
accountId | string | VoxBurst account ID |
workspaceId | string | Workspace ID |
platform | string | Platform constant — UPPERCASE |
error | string | Human-readable error description |
When you receive this event, prompt the user to reconnect the account via the OAuth flow.
media.uploaded
Fires when: A media file completes the S3 upload and processing pipeline — status transitions to READY.
{
"id": "evt_abc010",
"type": "media.uploaded",
"createdAt": "2026-06-01T10:01:30Z",
"data": {
"mediaId": "media_abc1234567890abc12345678",
"filename": "campaign-banner.jpg",
"contentType": "image/jpeg",
"sizeBytes": 204800
}
}| Field | Type | Description |
|---|---|---|
mediaId | string | VoxBurst media ID |
filename | string | Display filename |
contentType | string | MIME type (always image/jpeg after normalization for PNG/WebP) |
sizeBytes | integer | File size in bytes (post-normalization) |
media.ready and media.processing_failed are internal events and are not deliverable via webhooks. To track processing failures, poll GET /v1/media/:id until status is READY or FAILED.