Changelog
This is the API & developer changelog — endpoint additions, schema changes, SDK releases, breaking changes, and deprecations. For product-level updates (new UI features, platform support, app improvements), see the Product changelog .
Track API changes, new features, and breaking updates for VoxBurst.
How to read this changelog
Each entry is labeled with one of:
| Label | Meaning |
|---|---|
| Added | New endpoints, fields, or features. Backwards-compatible. |
| Changed | Modifications to existing behavior. Non-breaking unless labeled Breaking. |
| Fixed | Bug fixes and correctness improvements. |
| Breaking | Changes that require client updates. Announced 30 days in advance. |
| Deprecated | Fields or endpoints that will be removed. 90-day removal window. |
| Security | Security improvements. |
Backwards compatibility: additive changes (new optional fields, new endpoints, new enum values) are deployed without prior notice. Clients must ignore unknown fields. Non-additive changes are always labeled Breaking and announced in advance.
Contract precedence: API source code → this documentation → OpenAPI spec → SDK docs → examples. See Contract Precedence.
2026-09-02 — TikTok posting requirements
Breaking:
platformMetadata.TIKTOK.tiktokPrivacyLevelis now required for TikTok posts. TikTok’s Content Sharing Guidelines require an explicit, user-made privacy selection before a post is published, so this field no longer has an implicit default. Omitting it fails the TikTok publish withTIKTOK_PRIVACY_LEVEL_REQUIRED; requesting a level the account doesn’t support fails withTIKTOK_PRIVACY_LEVEL_UNAVAILABLE. Both are returned asplatforms[].error.codeon the post response — other platforms in the same multi-platform post are unaffected. FetchGET /v1/accounts/:id/tiktok/creator-infoto get the account’s allowed privacy levels before submitting. See TikTok publish errors.
Added:
GET /v1/accounts/:id/tiktok/creator-info— returns the connected TikTok account’s allowed privacy levels, duet/stitch/comment interaction settings, and posting eligibility. See TikTok Creator Info.- New TikTok post metadata keys:
TIKTOK.tiktokAllowComment,TIKTOK.tiktokAllowDuet,TIKTOK.tiktokAllowStitch,TIKTOK.tiktokCommercialContent,TIKTOK.tiktokBrandOrganic,TIKTOK.tiktokBrandedContent,TIKTOK.tiktokAutoAddMusic. See Platform Metadata. - New TikTok publish error codes:
TIKTOK_CREATOR_CANNOT_POST,TIKTOK_DISCLOSURE_INCOMPLETE,TIKTOK_BRANDED_CONTENT_PRIVACY. See TikTok publish errors.
2026-08-25 — SDK v1.3.0, MCP Server v0.3.0, CLI v0.3.0
All three published packages have been updated. Install or upgrade with:
npm install @voxburst/sdk@latest
npm install -g @voxburst/mcp-server@latest
npm install -g @voxburst/cli@latest@voxburst/sdk v1.3.0
Added:
-
client.accounts.selectPage(id, pageId, options?)— chooses which Page or organization a connected account publishes as, wrappingPOST /v1/accounts/:id/select-page. Pass an emptypageIdto clear the selection and publish as the personal profile (LinkedIn). Requires theaccounts:writescope.await client.accounts.selectPage('acc_123', 'page_456', { pageName: 'Acme Co' })Throws
ValidationError(HTTP 400) with one of three codes you should handle distinctly:Code Meaning PAGE_SELECTION_NOT_SUPPORTEDAccount was connected via Instagram Direct Login, which has no Facebook Pages. Reconnect via Facebook Login for Business first. ACCOUNT_PAGE_MISMATCHThat Page belongs to a different Instagram account. Select the Page from the matching account’s own record. DESTINATIONS_NOT_LOADEDDestinations are still being fetched — retry. -
client.contacts.get()now returnsContactDetail, which extendsContactwith recent engagement history:comments(comments the contact left on your posts) andinboundMessages(DMs they sent to a connected account).client.contacts.list()continues to return the flatContact— engagement history is detail-only.Both arrays are truncated by the API and carry no cursor, so treat them as a recent-activity preview rather than a complete record. An empty array is not proof the contact has never commented or messaged you. The response also carries
deliveriesandsequenceEnrollments, which are not yet typed in the SDK. -
New exported types:
Contact,ContactDetail,ContactComment,ContactInboundMessage.
Changed:
-
The client constructor now rejects a non-HTTPS
baseUrl. Passing abaseUrlthat does not begin withhttps://throws immediately, so your API key cannot be sent over plaintext. There is no exemption forlocalhost.This affects you only if you set
baseUrlexplicitly — the default (https://api.voxburst.io/v1) is unchanged. If you point the SDK at a local or proxied API overhttp://, that call will now throw at construction time. Terminate TLS in front of the local endpoint, or keep an unpatched client pinned for that environment.
@voxburst/mcp-server v0.3.0
Added:
create_postandupdate_postacceptcontentType— one ofTEXT,IMAGE,VIDEO,CAROUSEL,THREAD,STORY,REEL. Required for Instagram Reels (REEL) and carousels (CAROUSEL); useIMAGEfor single-image Instagram posts.- First-comment support on both tools —
firstComment(text auto-posted as a comment immediately after publishing, up to 2,200 characters) andfirstCommentDelay(seconds to wait first, 0–3600, default 0). Supported on Instagram, LinkedIn, Facebook, and YouTube. update_postacceptsmediaandplatformOverrides—mediareplaces the attached media with an array of VoxBurst media IDs;platformOverridessupplies per-platform content keyed by platform constant, e.g.{ "INSTAGRAM": { "content": "..." } }.create_postacceptsmediaIdsas an explicit alternative tomediaUrls, for agents that have already uploaded media and hold the IDs.
Fixed:
create_postsilently dropped all media passed asmediaUrls. The tool forwardedmediaUrlsstraight toPOST /v1/posts, which accepts only media IDs; the unknown field was ignored and every MCP-created post published without its media. Each URL is now registered viaPOST /v1/media/registerto obtain an ID before the post is created, with content type inferred from the file extension. If you built an agent flow againstmediaUrlsand worked around the missing media, remove that workaround — media now attaches as intended.list_postsaccepts the full status set. Valid statuses were under-specified, so filtering by certain values was rejected.Accountschema corrected and batch tool scope tightened.retry_postdescription corrected, and the server’s advertised version now trackspackage.json— MCP clients previously saw a stale version string during capability negotiation.
@voxburst/cli v0.3.0
Added:
-
voxburst completion— generates a shell completion script for bash and zsh, covering top-level commands and theaccountsandpostssubcommands:eval "$(voxburst completion)" # add to .zshrc / .bashrc voxburst completion --shell bash -
New
postssubcommands:create,update <id> [content],cancel <id>, andvalidate, joining the existinglist,get, anddelete. All accept--json;createandupdateaccept--platformsand--schedule(ISO 8601 or"YYYY-MM-DD HH:mm"), andcancelaccepts--forceto skip confirmation. -
--draft/-donvoxburst post— saves as a draft instead of publishing immediately.
Fixed:
voxburst --versionreported a stale version string that did not match the installed package.accounts list --jsonoutput shape now matches the API response.
Breaking: No. Every change above is additive, except the SDK’s HTTPS requirement on an explicitly-supplied baseUrl — see the note under Changed.
2026-08-25 — API Key Scopes for AI, Billing, Invitations & Comment Automations
Added:
-
Seven new API key scopes. These endpoint groups were previously reachable only with a wildcard (
*) key; scoped keys received403 AUTHORIZATION_ERROR. They can now be requested by name when creating a key:Scope Grants ai:readGET /v1/ai/status,/v1/ai/usage,/v1/ai/usage/history,/v1/ai/image-jobs,/v1/ai/image-jobs/:jobIdai:writeAll POSTroutes under/v1/ai, andGET /v1/ai/suggest-time/:accountIdbilling:readGET /v1/billing/current,/subscription,/usage,/scheduled-post-count,/creditsbilling:writeAll POSTroutes under/v1/billing, andGET /v1/billing/portalinvitations:readGET /v1/workspaces/:id/invitationscomment-automations:readGET /v1/comment-automations,/:id,/:id/logs,/:id/resolve-postcomment-automations:writePOST,PATCH,DELETEon/v1/comment-automationsAs elsewhere,
:writedoes not imply:read— request both if your integration needs to list and modify. See Authentication → Scopes for the full table.No change to existing keys. Wildcard keys reached these groups before and still do. A key holding other named scopes could not reach them before and still cannot — scopes are matched exactly, so these are available only to keys issued with them going forward.
The
hashtag-sets:readandhashtag-sets:writescopes were announced separately earlier the same day and are not repeated here — see the API Key Scopes for Hashtag Sets entry below.Three behaviours here are deliberate and will surprise you if you assume the usual method rule:
-
GET /v1/ai/suggest-time/:accountIdrequiresai:write, notai:read. It reserves and spends workspace AI credits before calling the provider, exactly as thePOSTroutes do. The same applies toGET /v1/billing/portal, which requiresbilling:write— it mints a Stripe billing portal URL whose bearer can change the payment method, switch plan, or cancel. Both are carve-outs above their parent group. Every otherGETin those two groups needs only the:readscope. -
There is no
invitations:write.invitations:readgrantsGET /v1/workspaces/:id/invitationsand nothing else. Invitation mutations are bound to a person, not a workspace, and are unavailable to API keys entirely — no scope, wildcard included, enables them. -
comment-automations:*is an API-access gate only and does not carry the plan entitlement. Comment automations require the PRO or AGENCY plan. A key holdingcomment-automations:writeon a workspace without the feature still receives403 PLAN_UPGRADE_REQUIRED. Both the scope check and the plan check must pass.
Two existing route groups are worth restating because neither has a scope of its own:
/v1/batchusesposts:read/posts:write(there is nobatch:*scope), and/v1/uploadssharesmedia:read/media:writewith/v1/media. -
Changed:
-
GET /v1/platformsnow reports the limits the publish path actually enforces. The capability values in this response are now derived directly from the platform capability registry that validation and publishing read, so the advertised limit and the enforced limit are the same number. Three values changed:Platform Field Previously advertised Now reported WhatsApp Business maxTextLength655364096LinkedIn maxImages920Reddit maxImages201Reddit additionally now reports no video support (
maxVideoLength: 0, andvideo/mp4absent frommediaTypes), matching the adapter — Reddit gallery and video upload are not implemented.What to check in your integration. If you read
GET /v1/platformsto build client-side validation, re-read it: WhatsApp content between 4,097 and 65,536 characters and Reddit posts with more than one image were being accepted by your validation but rejected at publish time. LinkedIn moves the other way — up to 20 images are accepted where your client may still cap at 9.The published platform reference already listed the enforced values, so no documentation page changes with this release; it is the API response that now agrees with it.
Fixed:
-
Invitation endpoints return
403 AUTHORIZATION_ERRORto API-key callers instead of401.POST /v1/invitations,POST /v1/workspaces/:id/invitations,POST /v1/invitations/:id/resend,GET /v1/invitations,POST /v1/invitations/:token/acceptandDELETE /v1/invitations/:idpreviously returned401 Authentication requiredwhen called with an API key. That was both the wrong status — the caller is authenticated; it is the operation that is unavailable to that credential — and a message that read like a broken or expired token. These now return403with a message naming the actual reason.What to check in your integration. If you have retry or re-authentication logic keyed on
401from these paths, it was retrying a call that can never succeed. Treat403here as terminal and route these operations through a signed-in workspace admin instead.
Breaking: No
2026-08-25 — API Key Scopes for Hashtag Sets
Changed:
-
/v1/hashtag-setsis now reachable with named API key scopes. Previously only a wildcard (*) key could call this endpoint group; scoped keys received403 AUTHORIZATION_ERROR. Two scopes are now available and can be requested when creating a key:Scope Grants hashtag-sets:readGET /v1/hashtag-sets,GET /v1/hashtag-sets/:idhashtag-sets:writePOST,PATCH,DELETEon/v1/hashtag-setsAs elsewhere,
:writedoes not imply:read— request both if your integration needs to list and modify. See Authentication → Scopes for the full table.No change to existing keys. Wildcard keys reached this group before and still do. A key holding other named scopes could not reach it before and still cannot — scopes are matched exactly, so this is available only to keys issued with it going forward.
Breaking: No
2026-08-24 — Account Scope Health & Page Selection Ownership
Added:
-
scopeHealthon the account object — returned byGET /v1/accountsandGET /v1/accounts/:id. Records what the platform actually granted at connect time against what each VoxBurst feature requires, so a shortfall is visible immediately rather than at the moment an affected call fails."scopeHealth": { "status": "DEGRADED", "degradedCapabilities": [ { "capability": "deletePost", "label": "deleting posts" } ], "message": "This connection is missing permissions for deleting posts. Reconnect the account and accept all requested permissions to restore it.", "verifiedAt": "2026-08-21T14:02:11.000Z" }statusis one ofOK,DEGRADED,UNKNOWN, orNOT_APPLICABLE. Branch ondegradedCapabilities[].capability(stable); displaylabelormessage(wording may change).grantedForOtherTargetsOnly: truemeans the permission exists but was granted for a different Page or account — the key is omitted otherwise.reasonis an opaque diagnostic forUNKNOWN/NOT_APPLICABLE; log it, do not parse it.scopeHealthabsent is notstatus: "OK". The field is omitted entirely on accounts connected before this check shipped, which means never verified — not no problems found. Treatingnullas healthy is the exact failure mode this field exists to prevent. Verification never blocks a connect: aDEGRADEDaccount is stillstatus: "active"and still publishes unlesspublishis among its degraded capabilities.See Scope Health for the full field and capability reference.
Changed:
-
POST /v1/accounts/:id/select-pagereturns400 ACCOUNT_PAGE_MISMATCHwhen the selected Page does not belong to the account identified by:id. Applies to Instagram and Facebook. Nothing is written when this is returned — the account is left exactly as it was.Honest framing: this is not a breaking change — no status code, envelope, or field changed on any successful call, and a selection that was already valid still succeeds. But a caller that selected a Page belonging to a different connected account previously received
{ "success": true }and will now receive a400. If your integration treats any non-2xx from this endpoint as fatal, add a handler.What a client should do: re-fetch
GET /v1/accounts/:id/pagesand retry with a Page belonging to that account. Retrying with the samepageIdwill fail identically — this is not transient. Note thatGET /v1/accounts/:id/pagescan return a superset of the Pages selectable onto any one account, so do not assume every entry is a validpageIdfor the account you fetched it from. See Page ownership. -
Account matching on reconnect now resolves an account to its platform-stable identity. A reconnect may upgrade an existing disconnected record in place where it previously created a second one, so
GET /v1/accountscan show one account where two appeared before. This is a data-shape outcome, not a contract change, and requires no integration work.
Docs:
POST /v1/accounts/:id/select-pageandGET /v1/accounts/:id/pagesin the OpenAPI spec no longer state that page selection does not apply to Instagram. It does, for Facebook Login-connected accounts.
2026-08-20 — Post, Media, Contact & Workspace Field Reference
No API behaviour changed in this entry. These fields and behaviours were already live and are now documented.
Documented — post and media fields:
GET /v1/posts/:id—platforms[]entries includeaccountAvatarUrl(optional; the key is omitted when absent, notnull) andaccountStatus(active,expired,disconnected,suspended,error— lowercase). CheckaccountStatusbefore unpublishing: any non-activevalue means the platform-side delete cannot succeed.POST /v1/posts/:id/unpublish— the failurereasonvocabulary is now documented and stable:platform_not_supported,account_disconnected,account_not_authenticated,token_expired,token_lookup_failed.token_expiredrequires the user to reconnect;token_lookup_failedis transient and reconnecting will not help.- Media objects include
thumbnailUrl— a poster frame for video, generated asynchronously. Nullable:nullfor non-video media, and until extraction completes.
Documented — contacts and workspaces:
GET /v1/contacts/:idincludesinboundMessages[](30 most recent) andcomments[](20 most recent). Both are capped and unpaginated — treat them as recent context, not a complete record.PATCH /v1/workspaces/:id— theapprove_contentandapprove_schedulesettings are documented. Unrecognisedsettingskeys are silently discarded and still return200; re-read the workspace to confirm a save.
Documented — accounts:
POST /v1/accounts/:id/select-pagereturns400 PAGE_SELECTION_NOT_SUPPORTEDfor Instagram accounts connected via Instagram Direct Login (oauthVersion: "instagram_login"). Not transient — page selection is a Facebook Login concept.
Documented — reserved metadata keys (pre-existing behaviour, previously undocumented):
metadata.titleis read as the post title by the Pinterest and Reddit adapters, and as a YouTube fallback. On a multi-platform post all three share the one value — useplatformMetadatafor per-platform titles.- A top-level
tagsbody field silently overwritesmetadata.tags. Set one or the other. Prefer the namespacedyoutubeTitle/youtubeTagskeys for YouTube.
Docs:
- New Inbox Comments reference page — the comments endpoint group previously had no page.
- WhatsApp Business is documented as pending approval, matching the platform gate in the product. The 2026-06-07 “now live” entry carries a dated correction.
2026-08-17 — Inbox Comments & Mentions Enhancements
Breaking Changes:
-
Inbox list endpoints now exclude hidden items by default.
GET /v1/inbox/commentsandGET /v1/inbox/mentionsno longer return items that have been soft-hidden. There is no tombstone or placeholder for an excluded item, and the response totals (paginationfor comments,meta.totalfor mentions) count only the visible set.The
hiddenOnlyfilter is binary — omitted orfalsereturns non-hidden items only,truereturns hidden items only. No value returns both.Migration: any integration performing a full sync must now issue two requests per resource — one with
hiddenOnly=trueand one without — and merge the results. A single unqualified request will silently under-report. Reconciliation logic that treats “absent from the list” as “deleted upstream” must be updated, or it will incorrectly delete hidden items from local stores. -
Threads posts containing more than 5 links are now rejected before publishing. The link count is validated locally, so the post fails with
VALIDATION_ERROR(Threads posts support a maximum of 5 links) instead of reaching the platform. The resulting failure is non-retryable —POST /v1/posts/:id/retrywill not clear it, where the previous platform-side failure was retried. Reduce the link count and resubmit viaPOST /v1/posts/:id/platforms/:platformId/fix.
New Endpoints:
-
POST /v1/inbox/comments/:commentId/hide— soft-hide a comment -
DELETE /v1/inbox/comments/:commentId/hide— unhide a comment -
POST /v1/inbox/mentions/:id/hide— soft-hide a mention -
DELETE /v1/inbox/mentions/:id/hide— unhide a mentionHiding is a VoxBurst-side visibility control. It does not hide, delete, or otherwise modify the item on the source platform. All four return the stored record, not the formatted shape returned by the corresponding list and get endpoints — re-fetch the item if you need the formatted form. See Inbox Comments and Inbox Mentions.
Changed:
GET /v1/inbox/commentsandGET /v1/inbox/mentionsaccept ahiddenOnlyboolean query parameter. Note thathiddenOnlyis not applied on the account-scoped (GET /v1/accounts/:accountId/comments) or post-scoped (GET /v1/posts/:postId/comments) comment lists — it is accepted and silently ignored there.- Comment and mention objects include
hidden(boolean) andhiddenAt(ISO 8601 timestamp ornull). GET /v1/inbox/mentions/statscounts all unread mentions including hidden ones, sounreadCountcan exceed the number of rows returned by the default list.- Comment sync now conditionally updates author information on resync, allowing previously stored placeholder author names to be replaced with real author data when the platform later supplies it. Consumers caching
author.usernameshould not assume it is immutable. - Facebook mention payloads use real sender identity when the webhook provides it.
authorUsernameremainsnullfor a meaningful fraction of Facebook mentions — see Facebook Mention Author Identity.
Fixed:
- Internal cleanup of the Facebook analytics collection path to stop requesting a metric Meta no longer serves. There is no change to reported
impressionsvalues — the figures returned by the analytics endpoints are sourced as before and the series is continuous. No action required.
Security:
- Improved access control on invitation endpoints
2026-08-12 — Inbox: permalinkUrl on Comments and Mentions, Facebook Mentions Now Delivered
Added:
permalinkUrl: string | nullonGET /v1/inbox/comments,GET /v1/inbox/comments/:id,GET /v1/inbox/mentions, andGET /v1/inbox/mentions/:id— each item now includes a direct public web permalink to the original content on the source platform. For Facebook, this is the fully-formed post or comment URL (e.g.https://www.facebook.com/{post_id}?comment_id={comment_id}), usable as a click-through link in integrations without additional Graph API calls. For Instagram and all other platforms,permalinkUrlis currentlynull— Instagram permalinks require the media shortcode, which is not fetched inline. This is a documented limitation, not a bug; shortcode-based permalink support is tracked as a future enhancement.
Fixed:
- Facebook Page mention events (
GET /v1/inbox/mentions?platform=FACEBOOK) now appear in the API. Due to a payload shape mismatch in the webhook ingestion layer, Facebookmentionwebhook events were previously stored in a format that prevented them from being returned by the mentions endpoints. They were silently dropped from API responses even though they were received from Meta. This is now corrected — Facebook mentions are stored with the correct shape and returned normally. If your integration was not seeing Facebook mentions before this release, no backfill was performed; existing stored events are unaffected.
Platform behavior note — Facebook mention author identity: For Facebook mentions where the tagged content is a comment on a post the Page does not own, authorId and authorUsername may be a non-resolvable placeholder or null. This is a permanent Meta Graph API constraint: the from field on the mention webhook event is documented by Meta as “Only available for Workplace community” for the item: "comment" case, and is not available to consumer apps via pages_read_user_content. VoxBurst performs a best-effort Graph API enrichment and uses real sender data when Meta provides it (which occurs for the item: "post" case when Meta includes sender identity inline). Integrations should handle authorUsername: null gracefully — for example, by displaying “Unknown” or using the new permalinkUrl field for navigation instead. See Inbox — Mentions: Facebook Mention Author Identity.
Breaking: No — permalinkUrl is an additive field. Clients that ignore unknown fields are unaffected.
2026-08-08 — Contacts: Instagram Messaging Window
Changed:
- The 24-hour messaging window on
POST /v1/contacts/:id/messagesis now enforced consistently for both Facebook and Instagram contacts. Previously this was Facebook-only; Instagram sends outside the window were not refused server-side. Integrators sending to Instagram contacts outside the window now receive the sameVALIDATION_ERRORrefusal Facebook contacts already do.messengerEligibleUntilon the contact object is populated for Instagram contacts as well (see updated field table below).
Breaking: No — this closes a gap in enforcement rather than changing a documented contract. Integrations relying on unrestricted Instagram sends should add window handling identical to their existing Facebook logic.
2026-08-08 — Broadcasts: Delivery Status Corrections, New Endpoints, and Missing Fields
Fixed:
-
delivery.statusvalue corrected:"SENT"is not a valid delivery status —DeliveryStatusis an independent enum fromBroadcastStatus. The valid delivery statuses arePENDING,DELIVERING,DELIVERED,FAILED, andREAD."SENT"is a broadcast-level status only; individual delivery records never carry it. Any integration checkingdelivery.status === "SENT"should change that check to"DELIVERED". -
Delete eligibility corrected —
DELETE /v1/broadcasts/:idacceptsDRAFT,FAILED, andSENTbroadcasts, notDRAFTonly. Broadcasts inSENDING,SCHEDULED, orPAUSEDstatus remain non-deletable and return422 BROADCAST_NOT_DELETABLE.
Added:
-
POST /v1/broadcasts/preview-count— returns{ count }with the number of contacts that would receive a broadcast for a given platform, account, and tag selection. Uses the same eligibility query as/:id/send. Agency plan required. -
POST /v1/broadcasts/:id/retry— retries allFAILEDdelivery records on aFAILEDorSENTbroadcast. Resets each failed delivery toPENDING, sets the broadcast status back toSENDING, and re-enqueues for processing. Returns{ broadcast, retriedContacts, batches }. Errors:BROADCAST_NOT_RETRYABLE(422) if the broadcast is not in a retryable state;NO_FAILED_DELIVERIES(422) if there are no failed deliveries to retry. -
socialAccountIdonPOST /v1/broadcastsandPATCH /v1/broadcasts/:id— optional field that pins the broadcast to a specific connected account. On create, accepts a string; on update, acceptsstring | null(passnullto clear). The account must belong to the workspace and its platform must be in the broadcast’splatformslist. -
deliveredCount,failedCount,readCounton the Broadcast object — integer counters maintained as deliveries progress. Now documented in the Broadcast schema. -
sentAt,readAt,errorCode,createdAt,updatedAton BroadcastDelivery records — fields present in the API response but previously undocumented.errorCodeis a platform-specific string populated whenstatusisFAILED. -
avatarUrlon the nestedcontactin delivery list responses — included in the contact selection returned byGET /v1/broadcasts/:id/deliveries.
2026-08-08 — Contacts: Direct Messaging, Messaging Status Fields & Enriched Mutation Responses
Added:
-
POST /v1/contacts/:id/messages— send a 1:1 direct message to a contact via their linked Facebook or Instagram account. Body:{ "text": "..." }(1–2,000 characters). Returns{ delivery: { deliveryId, status, errorCode? }, contact }wherecontactis the full detail shape. See Contacts — Send Direct Message.Eligibility is enforced server-side on every call. A refused send returns 400 before Meta is contacted. A transport failure returns 200 with
delivery.status: "FAILED"and anerrorCode. These are distinct outcomes — integrations must handle both:Outcome Status Meaning Refused (suppressed, window closed, no account, unsupported platform) 400 VALIDATION_ERRORMeta was never contacted; the send was blocked Transport failure (Meta rejected the message) 200, delivery.status: "FAILED"Delivery record created; check delivery.errorCodeSuccess 200, delivery.status: "DELIVERED"Message delivered -
Messaging-status fields on all contact responses —
GET /v1/contactsand all mutation endpoints now include the following fields on every contact:Field Type Notes socialAccountobject | null The connected account this contact was last seen through: { id, displayName, username, platform }lastInboundAtstring | null ISO 8601 timestamp of the most recent inbound message from this contact messengerEligibleUntilstring | null Facebook and Instagram. When the 24-hour messaging window closes. Always nullonce the window lapses — never a past timestamp.nullfor all other platforms.isSuppressedboolean trueif this contact has opted outsuppressedAtstring | null ISO 8601 timestamp when suppression was applied suppressionReasonstring | null "STOP_KEYWORD"or"MANUAL"messagesSentCountinteger Total messages sent to this contact sequenceEnrollmentCountinteger Total sequence enrollments -
Detail shape on
GET /v1/contacts/:id— now returnsdeliveries[](last 20 delivery records) andsequenceEnrollments[](last 10 enrollment records) in addition to all list-shape fields.
Changed:
- All contacts mutation endpoints now return the detail shape —
POST /v1/contacts,PATCH /v1/contacts/:id,POST /v1/contacts/:id/tags, andDELETE /v1/contacts/:id/tags/:tagpreviously returned a bare contact. They now return the same enriched detail shape asGET /v1/contacts/:id(includingdeliveries,sequenceEnrollments, and all messaging-status fields). This change is additive — new fields are present, no existing fields were renamed or removed. Strict deserializers that reject unknown fields will need to be updated.
Breaking: No — the response shape change is additive only. Clients that ignore unknown fields (the standard recommended behavior per the backwards compatibility policy) are unaffected. Strict clients must allow the new fields listed above.
2026-07-27 — WhatsApp Business Templates & Security Hardening
Added:
GET /v1/whatsapp/accounts/:accountId/templates— fetch approved WhatsApp Business message templates from connected accounts. Returns gracefully with an empty array if the Meta API is unavailable, allowing template composition to degrade cleanly.- WhatsApp Business OAuth provider registration — users can now connect WhatsApp Business accounts via Meta Facebook Login (same OAuth flow as Facebook).
Changed:
- Instagram Direct Login post deletion now explicitly blocked at the API level with a clear error message, since graph.instagram.com does not support the DELETE endpoint for this OAuth variant. The UI warns users that Instagram posts from Direct Login accounts must be deleted manually on Instagram.
- Instagram Direct Login analytics now requests
reach,profile_views,viewsinstead of the deprecatedimpressionsmetric, fixing 400 errors on insights calls.
Fixed:
- CloudFront redirect functions on both voxburst.com and app.voxburst.io were silently dropping query strings on trailing-slash redirects, breaking links with UTM parameters, referral codes, and consent tokens. Query strings are now preserved on all redirect paths.
- Improved input validation and request authorization across the API (API key route scoping, workspace path binding, webhook replay safety, and billing operation atomicity).
- Improved frontend dependency security across PostCSS and third-party packages.
Breaking: No
2026-07-20 — WhatsApp Templates, Analytics, and Consent Improvements
Added:
- WhatsApp message templates — Connected WhatsApp Business accounts can now retrieve approved message templates for use in publishing workflows.
- On-demand analytics refresh — Account metrics can be refreshed when needed through
POST /v1/analytics/accounts/:accountId/refresh.
Changed:
- Instagram Direct Login accounts now show a clear in-product notice when post deletion must be completed in Instagram.
- Account analytics are refreshed on demand when stale, improving dashboard freshness.
Fixed:
- Query parameters, including referral and consent values, are preserved through site redirects.
- Consent preferences are retained when navigating between voxburst.com and voxburst.io.
- Instagram analytics use the correct metrics and API host for each connection type.
- API keys cannot access global-administration routes.
- The “Remember me” control has improved keyboard and screen-reader support.
2026-07-04 — Instagram OAuth Redesign: Direct Login Default, New Account Fields & Structured Error Codes
Added:
-
oauthVersionfield on Instagram account responses — all connected Instagram accounts now include anoauthVersionfield indicating which OAuth path was used to connect. Two values are possible:"instagram_login"— connected via Instagram Direct Login (the new default)"fb_login"— connected via Facebook Login for Business
This field is present on all Instagram accounts returned by
GET /v1/accountsandGET /v1/accounts/:id. Accounts connected before this release that went through the Facebook Login path will show"fb_login"; accounts connected via Direct Login will show"instagram_login". -
flobProbefield on Instagram account responses — Instagram accounts connected via Direct Login may include an optionalflobProbeobject. When present, it indicates whether the account is eligible for upgrade to Facebook Login for Business:{ "flobProbe": { "flobAvailable": true, "facebookAccountId": "...", "checkedAt": "2026-07-06T01:29:37Z" } }Field Type Description flobAvailableboolean trueif this Instagram account is linked to a Facebook Page in Accounts Center and is eligible for Facebook Login upgradefacebookAccountIdstring | null The associated Facebook account identifier when flobAvailableistrue;nullotherwisecheckedAtstring ISO 8601 timestamp of when eligibility was last determined The
flobProbefield may be absent if the eligibility check has not yet completed. PollGET /v1/accounts/:idif you need to wait for it. -
Structured error codes on Instagram OAuth failures — when an Instagram OAuth attempt fails during the callback redirect, the result page now includes an
errorCodequery parameter. Integrations that handle the OAuth result URL should parse and present these codes:Code Meaning NO_FACEBOOK_PAGESUser has no Facebook Pages in their account NO_IG_ON_PAGESFacebook Pages found but none are linked to an Instagram account ACCOUNTS_CENTER_MISMATCHThe Instagram account is not associated with the user’s personal Accounts Center CREDENTIALS_NOT_CONFIGUREDInstagram OAuth credentials are not configured on this VoxBurst instance
Changed:
- Instagram Direct Login is now the default connection path — the login method picker previously presented during Instagram account connection is no longer shown. Accounts now connect via Instagram Direct Login by default. Facebook Login for Business remains available as an optional upgrade path for eligible accounts (see
flobProbeabove). Existing connected accounts and all post publishing behavior are unaffected. Integrators callingPOST /v1/accounts/connect/instagramwith an explicitloginMethodparameter are unaffected — the parameter is still accepted when provided.
Removed:
-
message_readsremoved from Meta webhook subscription field lists — VoxBurst’s Instagram and Facebook Page webhook subscriptions no longer includemessage_reads, which Meta’s API no longer accepts as a valid subscribed field. Current subscribed fields:- Instagram:
comments,mentions,messages,messaging_postbacks - Facebook Page:
feed,mention,messages,messaging_postbacks
This change only affects what events VoxBurst receives from Meta’s platform. It does not affect VoxBurst webhook deliveries to your endpoints.
- Instagram:
Breaking: No — oauthVersion and flobProbe are additive fields. Clients must ignore unknown fields. The removal of message_reads from Meta subscriptions is transparent to API consumers.
2026-07-03 — Facebook Post IDs, Twitter/X Engagement Rate, and Mention Filters
Fixed:
-
platformPostIdfor Facebook photo and video posts — for posts published to Facebook as photos or videos,platformPostIdnow returns the feed-level post ID. This is the same ID that appears inpost.publishedwebhook payloads. The field was already present in the response; only the value has changed. No schema migration is needed. -
GET /v1/inbox/mentions—platformandaccountIdfilters now reliably scope results — theplatformandaccountIdquery parameters now correctly filter returned mention records. Both parameters can be used independently or in combination.
Changed:
- Twitter/X
engagementRateis now follower-based — for Twitter/X, theengagementRatefield returned by all analytics endpoints now uses a follower-based denominator rather than impressions. For accounts below a minimum follower threshold,engagementRateisnullrather than0. All other platforms continue to use impression-based engagement rate. Existing stored data is not retroactively recalculated; the change applies to new metric fetches.
2026-06-27 — scheduledFor with saveAsDraft: true accepts past timestamps
Changed:
POST /v1/postsandPATCH /v1/posts/:id—scheduledForpast-date validation bypassed whensaveAsDraft: true— the 60-second future-date minimum is no longer enforced whensaveAsDraft: trueis set. This allows integrations that import historical content to preserve the original publication date for calendar positioning without requiring a future timestamp. The post is saved as a draft regardless of thescheduledForvalue. The future-date constraint still applies when creating or updating scheduled posts withoutsaveAsDraft: true.
Breaking: No — saveAsDraft: true behavior is unchanged. Integrations that do not use saveAsDraft are unaffected.
2026-06-22 — Google Business Profile Live, GMB Review Management, platformMetadata Validation, and API Key Scope Enforcement
Added:
-
Google Business Profile (
GOOGLE_BUSINESS) is now live — publishing is fully enabled. Connect a Google account with Owner or Manager access via Settings > Accounts. Supports Business Updates, Offers, and Events post types. See Google Business Profile. -
GET /v1/inbox/reviews— list Google Business Profile reviews for the workspace. Supports filtering byaccountId,locationPath,rating(1–5),unreadOnly, andunrepliedOnly. Paginated (page,limit1–100, default 20). Triggers a lazy GMB sync on each call, debounced per 5 minutes per account; sync failures do not block the response. See Inbox — Reviews. -
GET /v1/inbox/reviews/stats— returns aggregate unread and unreplied review counts for the workspace. Response:{ "unreadCount": N, "unrepliedCount": N, "totalCount": N }. -
GET /v1/inbox/reviews/locations— returns distinct synced GMB location paths for use in filter dropdowns. Response:{ "locations": [{ "locationPath": "string", "locationName": "string" }] }. -
POST /v1/inbox/reviews/:id/reply— post a reply to a GMB review via the Google Business API. Body:{ "comment": "string" }(1–4,096 characters). On success, setsreplied: true,repliedAt,replyContent, andread: trueon the review record. -
PATCH /v1/inbox/reviews/:id/read— mark a review as read. No request body required. -
GET /v1/accounts/:id/gmb/locations— list all GMB locations available under a connected Google Business account, grouped by account, with each location’s current selection state. Account must beGOOGLE_BUSINESSplatform. Returns400if the account is a different platform or the token is missing or expired. -
PUT /v1/accounts/:id/gmb/locations— save the set of selected location paths for a connected GMB account. Body:{ "locationPaths": ["string"] }(max 100 paths). Returns{ "success": true, "selectedCount": N }.
Breaking:
-
platformMetadatavalidation tightened onPOST /v1/postsandPATCH /v1/posts/:id— nested values inplatformMetadataare now strictly validated. Each value must bestring,number,boolean,null, or an array of those primitive types (max 50 elements per array). Each platform’s metadata object is limited to 20 keys. Requests containing arbitrary nested objects or non-primitive values now return400 VALIDATION_ERROR. Previously these were silently ignored or passed through.Migration: Audit any
platformMetadatapayloads your integration sends. Nested objects (e.g.{ "TIKTOK": { "nested": { "key": "val" } } }) are no longer accepted. Flatten any nested structures to top-level primitive key-value pairs. -
API key scope validation now enforced on
POST /v1/workspaces/:id/api-keysandPATCH /v1/workspaces/:id/api-keys/:keyId— requests containing unrecognized scope strings are rejected with400 VALIDATION_ERROR. The wildcard scope (*) must be the sole scope in the array; combining it with named scopes is rejected.Valid scopes: see the full table at Authentication — Scopes.
Error response when an invalid scope is submitted:
{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid scope(s): unknown_scope" } }Migration: Remove any custom or fabricated scope strings from API key creation/update calls. Replace
["*", "posts:read"]with["*"]alone or list only named scopes.
2026-06-20 — Facebook Analytics Metrics Deprecated by Meta
Changed:
-
Facebook analytics —
reach,engagements, andclicksnow return0— Meta deprecated the per-post metricspost_impressions_unique,post_engaged_users, andpost_clicksacross all Graph API versions effective June 15, 2026. For posts published on Facebook, thereach,engagements, andclicksfields in all analytics responses (GET /v1/analytics/posts/:postId,GET /v1/analytics/aggregate,GET /v1/analytics/overview, etc.) now return0. Theimpressionsfield for Facebook posts now reflectspost_media_view(view and play count) rather than the former impression metric.Instagram analytics are not affected by this change.
Breaking: No — fields are still present in the response and remain 0 rather than being removed. Downstream calculations that divide by or compare these fields against non-zero expectations should be updated.
2026-06-15 — TikTok Privacy Level, Publish Warnings, Unpublish Behavior Change & Threads Replies
Added:
-
platformMetadataonPOST /v1/postsandPATCH /v1/posts/:id— New optional request field for per-platform metadata overrides. Keys are platform constants (e.g."TIKTOK"); values are objects merged into the post’s platform-specific metadata. First supported key:TIKTOK.tiktokPrivacyLevel— set the TikTok privacy level (PUBLIC_TO_EVERYONE,MUTUAL_FOLLOW_FRIENDS,SELF_ONLY,FOLLOWER_OF_CREATOR) per post. Available values depend on the connected TikTok account’s creator permissions. See Platform Metadata. -
publishWarningonPostPlatformresponse objects — Non-fatal publishing warnings are now returned on per-platform publish state entries (theplatforms[]array in all post responses). The field isstring | null—nullwhen no warning occurred. First value:TIKTOK_SELF_ONLY_FALLBACK— the requested TikTok privacy level was rejected by the API and the post was automatically retried withSELF_ONLYvisibility and published successfully. See PostPlatform fields. -
GET /v1/posts/:id/replies— New endpoint to fetch replies for a published Threads post. Returns up to 25 replies. Requires theposts:readscope. If the connected Threads account does not havethreads_read_repliespermission (granted at OAuth time), the response is always{ "data": [] }— no error is returned. Returns{ "data": [] }for posts not published on Threads. See Get Post Replies. -
/v1/settings/notifications— now documented —GETandPUTendpoints for managing per-user notification preferences are now part of the public API reference. All existing fields (emailEnabled,pushEnabled,postPublished,postFailed,weeklyDigest,analyticsReport,timezone, dormant account reminder fields, andmarketingEmails) are documented. Two fields added in this release:webhookFailed(defaulttrue) — alerts when a webhook endpoint fails or is auto-disabled; andapprovalUpdates(defaulttrue) — alerts when an approval workflow state changes (submitted, approved, or rejected). All fields accept partial updates — send only the fields you want to change. See Notification Settings.
Changed:
-
POST /v1/posts/:id/unpublishnow deletes posts from platforms — Previously this endpoint only marked the VoxBurst post asunpublishedwithout touching the content on social platforms. It now attempts to delete the post from each connected platform before marking itunpublished. The response shape has changed:Previous response:
{ "success": true }(or similar — behavior was undocumented)New response:
{ "results": { "INSTAGRAM": { "success": true }, "TWITTER": { "success": false, "reason": "platform_not_supported" } }, "unsupported_platforms": ["TWITTER"], "note": "Posts on unsupported platforms must be deleted manually." }The
resultsobject contains per-platform outcomes (success: boolean, optionalreason: stringon failure).unsupported_platformslists platforms where deletion is not supported — you must remove posts on those platforms manually. The VoxBurst post is markedunpublishedregardless of per-platform deletion outcomes.Migration: If your integration calls
POST /v1/posts/:id/unpublishand reads the response body, update your handler to parse the new shape. If you were manually deleting posts from platforms after calling unpublish, review whether that logic is still needed for platforms listed inunsupported_platforms. See Unpublish Post.
Breaking: No — platformMetadata and publishWarning are additive. The unpublish response shape change affects integrations that parse the response body; the previous response was undocumented, so no stable contract existed. Update handlers that read the unpublish response.
2026-06-13 — Instagram Page Selection, Audio Search & AI Add-On Clarifications
Added:
GET /v1/accounts/:id/pagesnow supports Instagram — for accounts connected via Facebook Login, returns a list of Instagram Business accounts linked to the connected Facebook user token. The response shape differs from LinkedIn: Instagram entries usepageId,pageName,type, andavatarUrlfields (LinkedIn usesurnandlogoUrl). See List Pages.POST /v1/accounts/:id/select-pagenow supports Instagram — re-fetches IG business accounts from the Graph API, matches onpageId, and updates the account withusername,instagramAccountId,pageAccessToken,pageId,pageName, andoauthVersion: 'fb_login'. Returns400 INVALID_PAGE_IDifpageIdis not found. See Select Page.GET /v1/instagram/audio/search— search for audio tracks for use in Instagram Reels. Requires a Facebook Login-connected Instagram account. Returns trending tracks (omitq) or search results (q=<term>). Feature-flagged behindINSTAGRAM_AUDIO_ENABLED=true— currently returns503 FEATURE_DISABLEDwhile pending Meta App Review. See Instagram Audio Search.POST /v1/users/me/ga4-client-id— stores the browser GA4 client ID for server-side Measurement Protocol event stitching. Body:{ "clientId": "XXXXXXXXX.XXXXXXXXX" }(must match/^\d+\.\d+$/). Returns{ ok: true }. See User Endpoints.
Changed:
GET /v1/billing/current—aiAddonfield clarifications:subscribed: true, tier: nullis now a valid combination for complimentary or admin-granted AI access.creditsLimit: nullandcreditsRemaining: nullmean unlimited credits (not missing data). Previously these null combinations were undocumented. See Get Current Billing Status.
Breaking: No
2026-06-07 — WhatsApp Business Live, Analytics Expansion & AI Insights
Added:
-
WhatsApp Business is now a live platform — connect your WhatsApp Business Account (WABA) via OAuth and start publishing TEXT, IMAGE (up to 30 images), and VIDEO posts to your business number. Requires Meta Business verification and a registered phone number ID. See WhatsApp platform guide.
Correction (2026-08-19): WhatsApp Business was returned to pending approval status on 2026-06-24 and is not currently available for publishing. This 2026-06-07 entry is retained for history but no longer reflects the platform’s status. See Supported Platforms for current availability.
-
AI Insights — a new collapsible panel on the analytics dashboard surfaces AI-generated recommendations (priority-ranked, categorized as
posting_time,content_quality,platform_mix,growth,engagement) with actionable next steps and direct navigation links to the relevant dashboard section. Available on paid plans with a system-level AI provider configured. -
10 new analytics endpoints:
GET /v1/analytics/hashtag-performance— top hashtags by post count and average engagement rateGET /v1/analytics/content-types— engagement breakdown by content type (TEXT, IMAGE, VIDEO, etc.)GET /v1/analytics/insights— AI-generated insights (paid plan, 2-hour cache, configurable per workspace)GET /v1/analytics/publishing-calendar— post frequency calendar heatmap by dateGET /v1/analytics/content-themes— top words/themes by engagement rate across postsGET /v1/analytics/goals— retrieve current follower, impression, engagement, and post goalsPOST /v1/analytics/goals— set or update analytics goals (all fields optional, null to clear)GET /v1/analytics/report-schedule— retrieve the email report schedule (frequency, recipients)POST /v1/analytics/report-schedule— configure weekly or monthly email reports with up to 10 recipientsPOST /v1/analytics/send-report— immediately dispatch an analytics email report to configured or override recipients
-
Engagement Per Post KPI card added to the analytics dashboard overview
-
Email report redesign — new visual layout with platform breakdown, top posts, and insights summary; accessible via a toolbar button in the analytics panel
Changed:
- Facebook first comment —
pages_manage_engagementpermission required for Facebook first comments is currently under review by Meta. Posts that includefirstCommentwill publish normally; the comment is silently skipped on Facebook until the permission is approved and re-enabled. All other platforms are unaffected. GET /v1/analytics/posting-heatmapnow acceptsplatformsandaccountIdsfilter parameters; response now includeshasEngagementDataboolean
Fixed:
- AI Insights panel no longer shows fabricated data for workspaces with no post history — a structured onboarding state is returned instead
- Funnel bars now use the true maximum value in the dataset instead of clamping all bars relative to 100%, so a single high-performing post no longer makes all other posts appear flat
- “View breakdown” insight action link now correctly scrolls to the platform breakdown section
Breaking: No
2026-06-01 — AI Credit Costs Updated & Analytics Filtering Fixed
Added:
- Meta deauthorize and data deletion compliance webhooks (
POST /webhooks/meta/deauthorize,POST /webhooks/meta/data-deletion,GET /webhooks/meta/data-deletion?id=<code>) for OAuth app review and live-mode Instagram/Facebook support - Credit usage tracking in ledger for unlimited/admin-granted accounts (audit visibility without blocking generation)
- Follower count display in
/v1/accountsresponse and account UI cards - Engagement per Post KPI card to analytics dashboard
Changed:
- AI credit costs realigned: image generation, best time analysis, and hashtag suggestions now each consume credits
- Default credit cost per post updated — varies by content type (text-only vs. text+image)
- Workspace AI key (
/v1/ai/hashtags) now consumes credits /v1/overviewanalytics endpoint now respectsplatformsfilter parameter (previously ignored)- OAuth scopes: removed
instagram_business_messagingfrom required scopes to unblock account reconnection during Meta app review
Fixed:
- Analytics dashboard platform filter now correctly returns posts for selected platforms only (was showing all platforms regardless of filter)
- Account follower counts now display correctly after reconnection (separate followers_count fetch to gracefully handle restricted personal accounts)
- Instagram account sync no longer fails on personal accounts or accounts with restricted follower_count field
- OAuth result page no longer flashes “Connection failed” during redirect hydration
- Instagram Direct Login OAuth callback now correctly broadcasts result to parent window (was treating Instagram’s
#_=_hash artifact as pure page load)
Breaking: No
2026-05-26 — Instagram Discovery Improvements
Added:
- Setup guide — new “How to connect Instagram for Discovery” section in the Getting Started help page walks through the 5-step Facebook Business Manager + Instagram Professional Account setup
- Requirements banner — Discovery search now shows an inline banner listing which requirements are not yet met, with a direct link to the setup guide
- Per-account readiness check — each connected Instagram account is now checked for Discovery eligibility before you search; accounts that are missing the Facebook connection or are personal accounts show a specific, actionable warning
- Hashtag chips — hashtags are stripped from post captions and rendered as clickable chips; clicking any chip searches that hashtag immediately
- Copy-all hashtags — each result card has a “Copy all N” button that copies the post’s hashtags to the clipboard
- FAQ — “How Discovery works” FAQ is shown in the empty state, covering data source, top-post ranking, missing engagement fields, and the 30-hashtag platform limit
- Clickable media-type badge — the Photo / Video / Carousel badge on each result card links directly to the post on Instagram
Changed:
- “Album” renamed to “Carousel” across Discovery results (correct Instagram term)
- Post result cards are now compact text-only cards; image placeholders removed (Meta’s hashtag search API does not return media URLs for public posts)
- Relative timestamps (“3d ago”, “2w ago”) replace formatted dates on result cards
- Search button is disabled when the selected account is not Discovery-ready, so issues are surfaced before an API call is made
Fixed:
- Error messages are now specific and actionable — each error type returns its own message and suggested next steps
- Invalid account ID errors (code 100) are now distinguished from permission denied errors (code 10) and handled separately
Breaking: No
2026-05-25 — Workspace Ownership Transfer & Plan Enforcement
Added:
POST /v1/workspaces/:id/transfer-requests— Owner initiates a transfer request to any workspace memberPOST /v1/workspaces/:id/transfer-requests/:requestId/accept— Target accepts the ownership transfer (re-validates plan capacity at accept time)POST /v1/workspaces/:id/transfer-requests/:requestId/decline— Target declines the transfer requestDELETE /v1/workspaces/:id/transfer-requests/:requestId— Owner cancels a pending transfer requestGET /v1/billing/scheduled-post-count— Returns count of SCHEDULED and PAYMENT_PAUSED posts across owned workspacesPOST /v1/billing/cancelnow accepts{ cancelScheduledPosts: boolean }to bulk-move scheduled posts to DRAFT before cancellation- Workspace transfer requests expire after 7 days and auto-reject
- Email notifications sent to both owner and target on successful transfer (non-blocking; failures logged but do not roll back)
- Old owner becomes admin (retains data access); ownership transfer does not affect Stripe subscription
Changed:
- Workspace ownership transfer now uses request/acceptance flow instead of immediate transfer
- Plan capacity validation now occurs at acceptance time (not just request initiation) to prevent race conditions
- Scheduled posts targeting disconnected social accounts are now skipped at dispatch time (marked
SKIPPEDwithskipReason: 'account_disconnected') instead of failing — posts auto-recover if the account reconnects before the scheduled time - WhatsApp moved back to Early Access (Channels API not yet available from Meta); renamed to “WhatsApp Business” in platform listings
/enhance,/hashtags,/suggest-timenow require plan-level AI access (Starter or higher, or active AI add-on) — documented in API referencePOST /v1/accounts/store-oauth-tokensnow enforces plan account limits at OAuth callback time; returns 402 if limit reached- AI credit enforcement for plan-only users (non-addon) is now atomic — credits reserved before provider call on all three plan AI endpoints
Fixed:
- Scheduled post month calculation now uses
scheduledFor(publish month) instead ofcreatedAtfor accurate plan limit enforcement - Scheduler now correctly handles posts that exceed plan limits, preventing indefinite reprocessing
- Posts paused due to plan limits automatically resume when the plan is upgraded, within a recovery window
- Dispatch-time plan limit re-check added — posts scheduled before downgrade now correctly blocked
- WhatsApp OAuth account reconnection now preserves stable account identity
- AI usage reports now read from an updated data source
- Publish Now button no longer schedules posts that were auto-populated with a scheduled time
- Plan-only AI routes (
/enhance,/hashtags,/suggest-time) now log usage correctly for billing reports - Automatic image quality correction passes no longer charge credits
- Post deletion now correctly releases the associated scheduling capacity reservation
- Persona overage now visible in downgrade confirmation email
- Bulk post creation (
/posts,/bulk-video) now correctly enforce post limits based on the number of posts being created - Post creation enforcement is now consistent across all validation layers
- Facebook OAuth flow no longer overridden by secondary #= artifact redirect
Breaking: No
2026-05-20 — @voxburst/sdk v1.2.0
Added:
client.media— newMediaResourcewithget(id),delete(id), andgetUploadUrl({ filename, contentType, sizeBytes })methods. NewMediatype exported from the package root.client.webhooks— newWebhooksResourcewithcreate(input),list(),get(id),update(id, input), anddelete(id)methods. NewWebhooktype exported from the package root.client.batch.createPosts(posts, options?)— now hitsPOST /posts/bulkdirectly (up to 50 posts per call). Accepts{ dryRun?: boolean }. ReturnsBulkPostResponsewith per-post status (created | failed | valid).BulkPostResponseandBulkPostResulttypes exported fromBatchResource.client.posts.cancel(id)— cancel adraftorscheduledpost without deleting it.client.posts.unpublish(id)— attempt to delete a published post from each connected platform. Returns{ results: Record<string, { success, reason? }>, unsupported_platforms, note }.client.accounts.listAll(options?)— async generator that auto-paginates all accounts, mirroringposts.listAll().- Per-request timeout override —
client.request()now accepts{ timeout?: number }as a third argument. Pass a per-call timeout in milliseconds to override the global client timeout. X-Request-IDon errors — when the API returns anx-request-idresponse header, it is now attached to the thrownVoxBurstErroraserror.requestIdfor easier support debugging.- 429 Retry-After respected — on rate-limit responses the SDK now waits exactly the number of seconds specified in the
Retry-Afterheader (capped at 60 s) before retrying, rather than applying an exponential multiplier.
Upgrade: npm install @voxburst/sdk@latest
2026-05-20 — @voxburst/sdk v1.1.0
Added:
client.posts.validate(input)— new method onPostsResource. Checks content against platform character limits and rules without creating a post. Accepts{ content: string; platforms: string[] }, returns{ valid: boolean; platforms: Record<string, ValidatePlatformResult> }. TypesValidateContentResultandValidatePlatformResultare exported from the package root.
Upgrade: npm install @voxburst/sdk@latest
2026-05-20 — @voxburst/sdk v1.0.1
Fixed:
- Error class names preserved through minification —
instanceof ValidationError,instanceof NotFoundError,instanceof AuthenticationErroretc. now work correctly in bundled/minified consumer code. Previously all error instances appeared as a generic minified class. fromResponsedispatches to the correct error subclass — API errors are now thrown as the appropriate subclass based on HTTP status (400→ValidationError,401→AuthenticationError,404→NotFoundError,409→ConflictError,429→RateLimitError) instead of always throwing a baseVoxBurstError.ValidationErrorpreserves the API’s error code — thecodefield now reflects the actual code returned by the API (e.g.INVALID_INPUT) rather than always being hardcoded toVALIDATION_ERROR.
Upgrade: npm install @voxburst/sdk@latest
2026-05-20 — TypeScript SDK, CLI & MCP Server Published
Added:
@voxburst/sdkv1.0.0 is now publicly available on npm. Install withnpm install @voxburst/sdk. The SDK provides full TypeScript support, cursor-based auto-pagination vialistAll(), automatic retries with exponential backoff, and typed error classes. See the TypeScript SDK docs for installation and usage examples.@voxburst/cliv0.2.2 — updated release with API response shape fixes. Install withnpm install -g @voxburst/cli.@voxburst/mcp-serverv0.2.2 — updated release with API path fixes (see API Correctness Fixes below). Install withnpm install -g @voxburst/mcp-server.
Breaking: No — SDK is a new package; CLI and MCP Server updates are backwards-compatible.
2026-05-20 — API Correctness Fixes
Fixed:
POST /v1/posts/validateschema clarified — this endpoint requires aplatformsarray (e.g.["TWITTER", "INSTAGRAM"]), notaccountIds. It validates content rules for the named platforms without performing any account lookup. Previous documentation incorrectly showedaccountIdsin the example. See Validate Post for the corrected schema.- Post
statusvalues are lowercase — the API has always returned lowercase status strings (draft,scheduled,published,failed,partial, etc.). Documentation examples incorrectly showed uppercase values (DRAFT,SCHEDULED, etc.). Updated throughout the API reference, SDK docs, and examples. - Health check endpoint path —
GET /v1/healthandGET /v1/readyare the correct paths. Requests to/health(without the/v1prefix) return403from CloudFront and do not reach the API. See Health Check. - Malformed resource IDs return
400, not404— Passing a malformed ID returns a400 BAD_REQUEST. Handle both400and404when accepting user-supplied IDs. See Resource ID Format. @voxburst/mcp-serverv0.2.2 — API path fix — all internal HTTP client paths were incorrectly prefixed with/api/v1/instead of/v1/. This caused every MCP tool call to return403. Update to0.2.2or later. If you are running the MCP server from source, pull the latestmain.
2026-05-11 — Trial Countdown, Plan Features Control Plane, and Security Hardening
Added:
GET /billing/currentnow returnstrialEnd,trialTotalDays, andrecentlyExpiredTrialfields for accurate trial status tracking- Plan feature changes now take effect immediately without requiring a redeploy
- PDF analytics report generation (
GET /v1/reports/pdf, PRO/AGENCY plan-gated, white-label option for AGENCY) - New plan feature gates:
brand_voice,persona_evolution,ai_image_generation,pdf_reports,mcp_cli
Changed:
- Trial polling reduced for Twitter: account-level snapshots cached 24h (was 4x/day), post metrics use 7-day lookback with 24h staleness (was 90-day, 6h)
- “White-label Reports” renamed to “White-label Client Portal” (feature is CNAME-verified agency portal, not PDF branding)
- Qwen models updated to Qwen3.6 series with US-endpoint variants
- AI add-on credit system now enforces per-token rate limits on generation endpoints
Fixed:
- User avatar uploads now accept Cognito sub or DB ID (fixed 403 for all avatar uploads)
- Qwen API key validation fixed: uses correct US endpoint (dashscope-us.aliyuncs.com) and chat completion probe
- Unlimited team members now correctly enforced on Pro/Agency plans
- ai-sitemap and ai-context endpoints no longer blocked by CloudFront index.html rewrite
- Plan limit sync now occurs on cold start without overwriting admin edits
- Trial end dates now properly cleared from DB when subscription canceled to FREE
- Fixed a race condition on concurrent review submissions
Security:
- Improved prompt injection defense on AI generation endpoints
- Improved cost abuse prevention: tightened input field validation on AI generation and image prompt fields
- Improved rate limiting on review submissions and contact form attachments
- Improved webhook signature verification
- Improved Qwen key validation: added timeout to prevent hangs on network failures
Breaking: No
2026-05-06 — Webhook Auto-Disable, Downgrade Endpoints & Security Hardening
Added: New API fields and endpoints for webhook health management and plan downgrade workflows.
- Webhook objects now include
autoDisabledAt(ISO timestamp,nullif active) andconsecutiveFailures(integer) — use these to detect and alert on unhealthy webhook endpoints in your integration. - Webhook auto-disable behavior: after repeated consecutive delivery failures VoxBurst sends a warning email; after further failures it disables the webhook. Re-enabling via
PATCH /v1/webhooks/:idresets the failure state and resumes delivery immediately. GET /v1/billing/downgrade-readiness— returns a checklist of items to resolve before a plan downgrade (over-quota posts, connected accounts above the lower limit, active AI addons, etc.). Use this before initiating a plan change to surface blockers proactively.GET /v1/billing/downgrade-designations— lists the connected accounts that will remain active after a downgrade (workspace owner chooses which to keep up to the lower plan’s limit).
Changed:
- Plan enforcement is now consistent between API responses, feature gates, and display — upgrading mid-period activates new limits immediately; downgrading activates at the next renewal.
Fixed:
- Improved input validation on file upload endpoints (MIME type enforcement) and AI generation fields (length and content checks).
Breaking: No — autoDisabledAt and consecutiveFailures are additive webhook fields. Existing handlers that ignore unknown fields are unaffected.
2026-04-02 — Partial Failure Retry & Fix Endpoints
Added: Two new endpoints for recovering from partial or failed posts without re-publishing to platforms that already succeeded.
POST /v1/posts/:id/retry— Re-queues all failed platform targets automatically. Platforms withstatus: publishedare never touched. ReturnsretriedPlatformsandskippedPlatformsarrays indicating which platforms were retried and which had exhausted retries.POST /v1/posts/:id/platforms/:platformId/fix— Fixes a single failed platform and optionally replaces the image (mediaUrl) or caption (content) before resubmitting. This is the correct path for platforms that have exhausted automatic retries.post.publishedwebhook payload now includesstatusand a full per-platformplatformsarray (withpostPlatformId,status,error,platformPostUrlper entry) so handlers can detect partial failures and identify which platform needs fixing.
Breaking: No — existing post.published webhook handlers that only read postId are unaffected. New fields are additive.
2026-03-24 — Bulk Generation v2.1
Added: Queue-based bulk generation with credit reservation and decision engine foundation.
- New
POST /v1/bulk-generation/jobsendpoint for creating bulk post generation jobs - Credit reservation system ensures credits are held before generation begins
- Decision engine scores and categorizes generated content
Breaking: No
2026-03-16 — Persona Support for Posts
Added: Posts can now be linked to personas for AI-generated content with consistent voice.
- Added
personaIdfield to posts - Persona memory updates after publishing enable learning from successful posts
- Persona profiles define tone, style, and platform-specific adaptations
Breaking: No — personaId is optional; existing posts unaffected.
2026-03-15 — AI Generation Improvements
Added: Enhanced tracking for AI content generation.
workspace_idadded to AI generation records for billing queries by workspaceresolved_modelfield stores the actual model used when aliases redirect requests- New AI providers: Qwen added to supported models
Breaking: No
2026-03-14 — Account Permission Modes
Added: Granular permission controls for connected social accounts.
- Accounts now support permission modes:
read,publish,full - Fine-grained access control for team workspaces
- Permission checks enforced at the API level
Breaking: No — existing accounts have full access unless a permission mode is specified.
2026-02-22 — Webhook Delivery Logs
Added: Comprehensive webhook delivery tracking and improved delivery diagnostics.
- Delivery status tracking:
pending,delivering,delivered,failed - Automatic retry with exponential backoff for failed deliveries
Breaking: No
2026-02-19 — Webhook Delivery Fields
Added: Enhanced webhook endpoint reliability features.
failureCounttracking on webhook endpointslastDeliveryAttimestamp for monitoring- Improved delivery diagnostics
Breaking: No
Versioning Policy
VoxBurst follows semantic versioning principles for API changes:
- Non-breaking changes (new fields, new endpoints) are deployed continuously
- Breaking changes are announced 30 days in advance via email and changelog
- Deprecated fields are marked in documentation 90 days before removal
Follow @voxburst on X for announcements.
Docs & contract changes
This feed tracks changes to the documentation and OpenAPI spec — new pages, schema corrections, field additions to reference tables, and spec updates. It is distinct from the API changelog above, which tracks live API behavior changes.
2026-07-29 — Updated Webhooks with Meta compliance callback configuration: the versioned data-deletion and deauthorize URLs, signed-request authentication, and the public deletion-status flow. Updated Versioning & Compatibility to clarify that VoxBurst API /v1 is independent of Meta Graph API versions; Meta Graph API v25.0 remains the current integration version while v26.0 is validated in a Meta test app.
2026-06-15 — Updated Posts API reference: added platformMetadata request field to POST /v1/posts and PATCH /v1/posts/:id; added publishWarning to PostPlatform fields; corrected POST /v1/posts/:id/unpublish behavior description and response schema; added GET /v1/posts/:id/replies endpoint
2026-06-13 — Updated Accounts API reference: expanded GET /v1/accounts/:id/pages and POST /v1/accounts/:id/select-page to document Instagram support alongside LinkedIn; added GET /v1/instagram/audio/search endpoint; added POST /v1/users/me/ga4-client-id endpoint
2026-06-13 — Updated Subscription API reference: clarified aiAddon field in GET /v1/billing/current — documented subscribed: true, tier: null (complimentary access) and creditsLimit: null / creditsRemaining: null (unlimited) as valid states
2026-05-31 — Added OpenAPI Spec page: codegen examples (openapi-typescript, openapi-generator, openapi-zod-client), Postman/Insomnia import, and generated type excerpts for Post and CreatePostInput
2026-05-31 — Added Post with media and Scheduled campaign end-to-end production workflow guides
2026-05-31 — Added Versioning & Compatibility page: explicit breaking-change tables, deprecation timeline, SDK semver rules, stability tiers, contract precedence
2026-05-31 — Added SDK↔REST mapping tables for 8 previously undocumented resources: Batch, Personas, Hashtag Sets, Contacts, Broadcasts, Sequences, Approval Workflows, Image Generation Jobs
2026-05-31 — Surfaced OpenAPI spec URLs on homepage, Getting Started, and SDK mapping page; added idempotency and versioning to Getting Started Next Steps
2026-05-31 — Added Python (REST) page to SDK navigation — clarifies no official Python package exists, REST-only with comparison table
2026-05-31 — Added client.media and client.webhooks reference sections to TypeScript SDK docs; completed client.posts with publish, cancel, clone, fixPlatform
2026-05-31 — Added API conventions section to Canonical Schemas: camelCase naming, ISO 8601 UTC dates, cuid2 ID prefix table, enum casing rules, null-vs-absent, pagination envelope
2026-05-31 — Corrected TypeScript SDK method coverage to match published @voxburst/sdk@1.2.1: removed publish(), clone(), fixPlatform() from client.posts (REST-only); removed completeConnect(), test(), listPages(), listPlaylists(), selectPage() from client.accounts (REST-only); removed client.personas, client.hashtagSets, client.approvalWorkflows (REST-only); corrected recurrence field to REST-only for creation. All affected examples replaced with raw-fetch equivalents.
2026-05-31 — Improved docs lint script: stale-pip check uses denial-text detection instead of path exemption; response-shape check extended to let/var and multiline destructuring, scoped to code blocks only; platforms-on-create check replaced line-window heuristic with fenced-code-block parser
2026-05-31 — Added scripts/sdk-methods.json (snapshot of @voxburst/sdk@1.2.1 resource/method surface derived from published package types) and scripts/generate-sdk-methods.js (regenerates the snapshot from the npm registry tarball). Added check 5 to the docs lint script: validates every client.X.Y() call in TypeScript code blocks against the snapshot — CI now fails if a documented SDK method does not exist in the published package. Immediately caught 22 violations across four files, all corrected.
2026-05-31 — Corrected Personas and Hashtag Sets tables in the SDK ↔ REST mapping: TypeScript SDK column incorrectly listed client.personas.* and client.hashtagSets.* as SDK methods. Both resources are REST-only and do not exist in @voxburst/sdk@1.2.1. All entries updated to REST only, resolving the contradiction between the mapping page and the TypeScript SDK page.
2026-06-07 — Added WhatsApp Business MCP guide: content types, failure cookbook, account requirements, cross-platform override example, benchmark checklist
2026-06-07 — Added 10 new analytics endpoints to Analytics API reference: hashtag-performance, content-types, insights, publishing-calendar, content-themes, goals (GET/POST), report-schedule (GET/POST), send-report
2026-06-07 — Expanded SDK ↔ REST mapping Analytics section from 2 to 21 endpoints; corrected prior client.analytics.* entries which incorrectly implied TypeScript/Go SDK coverage (all analytics endpoints are REST-only)
2026-06-07 — Updated platform count from 8 → 9 across platforms-at-a-glance, same-post-all-platforms, 7 MCP platform guide breadcrumbs, and facebook-mcp guide; WhatsApp row added to all comparison tables
2026-06-07 — Documented Facebook first-comment pending-approval state in api-reference/posts, sdks/mcp, platforms/index, and guides/facebook-mcp with consistent ✗ † notation and footnote explaining the pages_manage_engagement Meta review status
2026-06-20 — Updated Analytics API reference: added platform-specific caveat for Facebook metrics — reach, engagements, and clicks now return 0 for Facebook posts; impressions reflects post_media_view; Instagram unaffected
2026-06-22 — Updated Platforms reference: Google Business Profile status updated from Pending approval to Live (go-live date 2026-06-22)
2026-06-22 — Updated Posts API reference: added platformMetadata validation constraints (primitive-only values, max 50 array elements, max 20 keys per platform object); updated scheduledFor scheduling semantics to document saveAsDraft exception to past-date validation
2026-06-22 — Added Inbox — Reviews: new page documenting all GMB review management endpoints (GET /v1/inbox/reviews, GET /v1/inbox/reviews/stats, GET /v1/inbox/reviews/locations, POST /v1/inbox/reviews/:id/reply, PATCH /v1/inbox/reviews/:id/read)
2026-06-22 — Updated Accounts API reference: added Google Business Profile subsection documenting GET /v1/accounts/:id/gmb/locations and PUT /v1/accounts/:id/gmb/locations; updated API key scope table in Authentication with complete scope list and wildcard constraint
2026-06-22 — Updated Errors reference: added requestId field to OAuth error response shape; noted X-Request-Id header on all OAuth handler responses
2026-07-04 — Updated Accounts API reference: added oauthVersion and flobProbe to the Account Fields table; added Instagram-specific OAuth error codes (NO_FACEBOOK_PAGES, NO_IG_ON_PAGES, ACCOUNTS_CENTER_MISMATCH, CREDENTIALS_NOT_CONFIGURED) to the OAuth Edge Cases section; updated Instagram authentication description in platforms reference and Instagram MCP guide to reflect both connect paths
2026-08-08 — Rewrote Contacts API reference: added POST /v1/contacts/:id/messages; documented all new messaging-status fields (socialAccount, lastInboundAt, messengerEligibleUntil, isSuppressed, suppressedAt, suppressionReason, messagesSentCount, sequenceEnrollmentCount); documented list vs. detail response shapes; documented deliveries[] and sequenceEnrollments[] on the detail shape; updated all mutation endpoint response descriptions to reflect the enriched detail shape
2026-08-12 — Updated Inbox — Mentions: added permalinkUrl field to all response field tables and JSON example; added Facebook Mention Author Identity callout documenting the Meta platform constraint on authorId/authorUsername for item: "comment" events; updated Platform Coverage table with Permalink URL column. Note: GET /v1/inbox/comments endpoints also return permalinkUrl in production but no API reference page for Comments exists yet — reference-page creation is a separate task.