Sending inbox messages now supports idempotent retries via
This prevents duplicate sends when you retry after timeouts: same key + same body replays the original response (with
Use:
•
New error responses:
•
•
View documentation
Idempotency-Key on POST /v1/inbox/conversations/{conversationId}/messages.This prevents duplicate sends when you retry after timeouts: same key + same body replays the original response (with
Idempotent-Replayed: true) instead of sending again. Works for both application/json and multipart/form-data requests; keys are retained for 24 hours.Use:
•
Idempotency-Key (header)New error responses:
•
409 - Idempotency key still in flight•
422 - Idempotency key reused with a different bodyView documentation
WhatsApp now supports Meta Direct Send utility messages via
Eligible WhatsApp Business Accounts can start or send a business-initiated
Use
•
•
Notes:
•
•
•
View documentation
category on inbox messaging endpoints.Eligible WhatsApp Business Accounts can start or send a business-initiated
utility text message without an approved template (Meta matches/auto-creates a template asynchronously). If the WABA isn’t eligible, the request fails and you must use an approved template.Use
category:•
POST /v1/inbox/conversations: set category=utility with message and no templateName (WhatsApp only)•
POST /v1/inbox/conversations/{conversationId}/messages: set category=utility to send as a business-initiated utility message (WhatsApp only)Notes:
•
category enum: utility•
category cannot be combined with templateName (create-conversation) or template (send-message)•
category is accepted on application/json only (not multipart/form-data)View documentation
POST /v1/sms/sender-ids no longer enforces global uniqueness for alphanumeric sender IDs.The same
senderId can now be registered by multiple workspaces, so creating a sender ID should no longer fail due to another workspace already having it.Changes:
• Removed
409 (sender_id_taken) conflict response• Increased active sender ID limit in
403 from 5 to 1,000 (sender_id_limit_reached)Request remains:
senderIdView documentation
In
A
Key field:
View documentation
PUT /v1/posts/{postId}, platforms[].platformSpecificData update behavior is now explicitly defined.A
Settings namespace (e.g. facebookSettings, tiktokSettings) that is omitted from the request is preserved from the stored post. If you send the key, it replaces the entire namespace (it is not deep-merged).Key field:
platforms[].platformSpecificDataView documentation
Updating a post now preserves per-platform settings unless you explicitly send them in
A
Also, port-in now supports Brazil by allowing
View documentation
platforms[].platformSpecificData.A
Settings namespace (e.g. facebookSettings, tiktokSettings) omitted from the request is kept from the stored post. If you include the key, it replaces the entire namespace (no deep-merge).Also, port-in now supports Brazil by allowing
endUser.countryCode = BR in POST /v1/phone-numbers/port-in (enum now includes US, CA, GB, ES, DE, FR, NL, AU, BR).View documentation
PUT
If you include
View documentation
/v1/posts/{postId} now requires platforms when sending root-level tiktokSettings or facebookSettings.If you include
tiktokSettings or facebookSettings in an update request without a platforms array, the API will return 400. Include the target platforms (with platform + accountId) in the same request when updating these settings.View documentation
Connect flow redirects now include the created social account id in the success
•
•
•
•
This lets you reliably capture the connected account immediately after OAuth without extra lookup.
Look for
View documentation
redirect_url for these endpoints:•
POST /v1/connect/facebook/select-page•
POST /v1/connect/googlebusiness/select-location•
POST /v1/connect/pinterest/select-board•
POST /v1/connect/snapchat/select-profileThis lets you reliably capture the connected account immediately after OAuth without extra lookup.
Look for
accountId in the returned redirect_url query params (e.g. ...&accountId=...).View documentation
Ad.creative.thumbnailUrl can now be null (was always a string).This affects ad preview/rendering: don’t assume a thumbnail URL is always available; fall back to other creative fields when it’s missing.
Key change:
creative.thumbnailUrl: string | nullView documentation
WhatsApp template creation now supports NAMED variables via
This lets you use {{customer_name}}-style tokens (in addition to the existing positional {{1}} style) and provide per-variable examples for Meta review.
Set
For NAMED templates, include examples in:
•
•
Each named param example uses:
View documentation
parameter_format on POST /v1/whatsapp/templates.This lets you use {{customer_name}}-style tokens (in addition to the existing positional {{1}} style) and provide per-variable examples for Meta review.
Set
parameter_format to POSITIONAL | NAMED (also accepts positional | named).For NAMED templates, include examples in:
•
components[].example.body_text_named_params•
components[].example.header_text_named_paramsEach named param example uses:
{ param_name, example }.View documentation
🔥1
Meta Ads now supports Value Rule Sets (bid adjustments by audience segment) via new endpoints under
You can create/list/read/replace/delete value rule sets, then attach one to an ad set to increase/decrease bids for matching segments (rule order matters: first match wins).
New endpoints:
•
•
•
•
•
Attach/detach on ad sets (Meta only) via
• Attach/replace: send
• Detach: send
• Sending
Also supported on create (Meta only) via
• Attach to the new ad set with
•
Eligibility (Meta enforced): only ad sets on
View documentation
/v1/ads/value-rule-sets.You can create/list/read/replace/delete value rule sets, then attach one to an ad set to increase/decrease bids for matching segments (rule order matters: first match wins).
New endpoints:
•
GET /v1/ads/value-rule-sets•
POST /v1/ads/value-rule-sets•
GET /v1/ads/value-rule-sets/{valueRuleSetId}•
PUT /v1/ads/value-rule-sets/{valueRuleSetId} (full replace, not patch)•
DELETE /v1/ads/value-rule-sets/{valueRuleSetId}Attach/detach on ad sets (Meta only) via
PUT /v1/ads/ad-sets/{adSetId}:• Attach/replace: send
valueRuleSetId (optionally valueRulesApplied: true)• Detach: send
valueRulesApplied: false and omit valueRuleSetId• Sending
valueRulesApplied: false with valueRuleSetId returns 400 mutually_exclusive_fieldsAlso supported on create (Meta only) via
POST /v1/ads/create:• Attach to the new ad set with
valueRuleSetId (optional valueRulesApplied: true)•
valueRulesApplied: false is rejected on createEligibility (Meta enforced): only ad sets on
LOWEST_COST_WITHOUT_CAP or COST_CAP.View documentation
🔥1
POST
This lets you explicitly set the ad set
Set
View documentation
/v1/ads/boost now supports Meta-only optimization goal overrides via optimizationGoal.This lets you explicitly set the ad set
optimization_goal instead of relying on the default derived from goal, which can be useful when Meta requires a different optimization goal for the boost objective.Set
optimizationGoal to a Meta-compatible value for the objective derived from your goal (e.g. boost goal engagement maps to Meta objective OUTCOME_AWARENESS, so values like REACH, IMPRESSIONS, AD_RECALL_LIFT, or THRUPLAY-class are accepted; POST_ENGAGEMENT is rejected under that objective).View documentation
New endpoint
Use it to confirm a credential is valid before proceeding (e.g., when verifying an incoming token).
On
View documentation
GET /v1/auth/verify was added to validate a bearer credential (API key or OAuth access token) without calling a data endpoint.Use it to confirm a credential is valid before proceeding (e.g., when verifying an incoming token).
On
200 it returns valid, userId, authType (api_key | oauth | session), and scope (space-separated OAuth scopes; null for API keys). 401 if invalid.View documentation
Contacts listing now supports filtering by SocialAccount via
Use
New query param:
Also,
View documentation
accountId on GET /v1/contacts.Use
accountId to list contacts through their channel; when accountId is set, the profileId contact filter is not applied (a provided profileId is still access-checked and still scopes filters.tags).New query param:
accountIdAlso,
POST /v1/contacts 409 is now explicitly documented as: Duplicate channel. The platformIdentifier is already bound to a channel on this accountId.View documentation
OAuth connect now surfaces upstream token-exchange failures via a new
This helps distinguish platform-side rejections from internal errors; handle
Key response codes:
•
•
Lead form creation can now return
Key response code:
•
View documentation
502 response on POST /v1/connect/{platform}.This helps distinguish platform-side rejections from internal errors; handle
502 separately from 500 (the upstream 4xx is forwarded as platform_error).Key response codes:
•
502 - platform rejected token exchange (platform_error)•
500 - internal error while connecting the accountLead form creation can now return
422 on POST /v1/ads/lead-forms when Meta rejects the form (error code 3), typically because the Facebook Page hasn’t accepted the Lead Ads Terms.Key response code:
•
422 - Meta rejected lead form (often requires a Page admin to accept Lead Ads Terms)View documentation
Slack DMs are now supported in the Inbox API.
You can list eligible Slack workspace members (for a recipient picker) via
Key params:
•
•
Also updated:
View documentation
You can list eligible Slack workspace members (for a recipient picker) via
GET /v1/accounts/{accountId}/slack-members, then start a DM by passing the member id as participantId to POST /v1/inbox/conversations.Key params:
•
GET /v1/accounts/{accountId}/slack-members: query, limit•
POST /v1/inbox/conversations: participantId (Slack member id, e.g. U01ABCDEF)Also updated:
POST /v1/inbox/conversations now lists supported platforms as X/Twitter, Bluesky, Reddit, WhatsApp, SMS, and Slack.View documentation
❤1
WhatsApp now supports requesting a user’s contact info via interactive messages.
You can send a consent-based “share contact” prompt, and inbound replies include contact cards plus an origin flag so you can distinguish consented self-share vs address-book shares.
Send with
•
On
•
•
View documentation
You can send a consent-based “share contact” prompt, and inbound replies include contact cards plus an origin flag so you can distinguish consented self-share vs address-book shares.
Send with
interactive.type:•
request_contact_infoOn
message.received, check:•
metadata.contacts (array)•
metadata.contactsOrigin: contact_request | otherView documentation
🔥1
Non-draft updates to
If the resulting post violates platform rules (media requirements, platform-specific fields, etc.), the update will return
Also,
View documentation
PUT /v1/posts/{postId} now run the same per-platform validation as post creation.If the resulting post violates platform rules (media requirements, platform-specific fields, etc.), the update will return
400 instead of succeeding.Also,
PostUpdateResponse may now include warnings (array of strings).View documentation
👍1
Webhooks now support per-subscription event blocking via
This lets you prevent specific resource-group events (e.g. private messages) from ever being delivered to a webhook endpoint, even if those events are listed in
Use
• Create: include
• Update: sending
Restricted
New/expanded
•
•
•
Note: after updating a webhook denylist, already-queued events may still arrive for up to ~5 minutes.
View documentation
disabledResourceGroups on POST /v1/webhooks/settings and PUT /v1/webhooks/settings.This lets you prevent specific resource-group events (e.g. private messages) from ever being delivered to a webhook endpoint, even if those events are listed in
events. The same filtering applies to replay paths (test fire, redelivery, dead-letter requeue).Use
disabledResourceGroups (enum: publishing, engagement, messages, contacts, analytics, ads, telephony, accounts, billing, webhooks):• Create: include
disabledResourceGroups to opt out; omit or [] to receive everything in events• Update: sending
disabledResourceGroups replaces the denylist; send [] to clear; omit to leave unchangedRestricted
zrk_ keys: the key’s own disabled groups are always unioned into the subscription, so a restricted key can’t create or widen a subscription beyond itself.New/expanded
403 behavior (ResourceGroupForbidden) was added to:•
GET /v1/webhooks/settings•
DELETE /v1/webhooks/settings•
POST /v1/webhooks/test (note: webhook.test is in the webhooks group)Note: after updating a webhook denylist, already-queued events may still arrive for up to ~5 minutes.
View documentation
Meta multi-language ads now support per-locale destination URLs via
This lets you send users to different landing pages per language while keeping a single ad (shared social proof).
Set
View documentation
translations[].linkUrl on POST /v1/ads/create.This lets you send users to different landing pages per language while keeping a single ad (shared social proof).
Set
translations[].linkUrl to override the destination for that locale; when omitted it inherits the top-level linkUrl (which must be present if any locale uses translations[].linkUrl).View documentation
Incoming message.received webhooks now include quote-reply context via
This lets you correlate an inbound message that quotes/replies to an earlier message (WhatsApp/Instagram/Facebook Messenger) using the original message’s
New field:
•
Also clarified
• WhatsApp: pass
• Telegram: pass Telegram message ID
• Instagram: pass Meta
• Slack: threads the reply (uses
• Silently ignored on platforms without reply support (incl. Facebook Messenger)
View documentation
metadata.quotedMessageId.This lets you correlate an inbound message that quotes/replies to an earlier message (WhatsApp/Instagram/Facebook Messenger) using the original message’s
platformMessageId.New field:
•
metadata.quotedMessageId - platformMessageId of the message being quoted/replied toAlso clarified
POST /v1/inbox/conversations/{conversationId}/messages replyTo behavior:• WhatsApp: pass
wamid• Telegram: pass Telegram message ID
• Instagram: pass Meta
mid• Slack: threads the reply (uses
thread_ts)• Silently ignored on platforms without reply support (incl. Facebook Messenger)
View documentation
Meta ads creation now supports optimizing for pixel custom events via
Use this when you want
Set:
•
•
View documentation
promotedObject.customEventStr on POST /v1/ads/create.Use this when you want
goal=conversions (or lead_conversion) to optimize against a custom event name from Events Manager (instead of a standard event or a Custom Conversion).Set:
•
promotedObject.customEventType = OTHER•
promotedObject.customEventStr = <your_event_name>customEventStr is case-sensitive, and OTHER requires customEventStr (and vice versa).View documentation