GET
Use
PUT
View documentation
/v1/ads/campaigns now supports listing Meta empty campaigns (campaigns with adCount: 0), which were previously invisible because campaigns are aggregated from ad documents.Use
includeEmpty=true to include these campaigns (metrics will be zeroed). Requires accountId and adAccountId when includeEmpty=true.PUT
/v1/ads/campaigns/{campaignId} can now update an empty Meta campaign by sending accountId in the request body (otherwise it may 404 due to no local ad docs). The response will return updated: 0 for empty campaigns.View documentation
POST /v1/contacts/bulk now treats missing platformIdentifier as a per-contact failure when importing in channel mode.If you send a top-level
accountId, each contact is expected to include platformIdentifier; rows missing it are rejected individually and returned in errors[] under an HTTP 200 (the whole import no longer fails with HTTP 400 for that case).Key behavior:
• Channel mode:
accountId set + contact missing platformIdentifier → HTTP 200 with errors[]• Request-level
400 still applies for missing required name, or when a row includes channel data but there is no top-level accountId to attach it toView documentation
❤1
GET
This lets you distinguish platform-specific states (e.g., Meta disabled vs. billing vs. review) and show better “why can’t I run ads?” messaging instead of relying only on
New fields in
•
•
•
Note: LinkedIn continues to use
View documentation
/v1/ads/accounts now returns additional platform status details for ad accounts.This lets you distinguish platform-specific states (e.g., Meta disabled vs. billing vs. review) and show better “why can’t I run ads?” messaging instead of relying only on
selectable.New fields in
accounts[]:•
accountStatus (platform status; type varies by platform)•
disableReason (Meta only; integer code when accountStatus indicates disabled)•
approvalStatus (X only; observed: ACCEPTED, PENDING, REJECTED)Note: LinkedIn continues to use
status (filtered to active accounts).View documentation
GET
Use
New parameter:
View documentation
/v1/contacts now supports filtering by multiple tags via a new tags query parameter.Use
tags as a comma-separated list to match contacts that have any of the provided tags.New parameter:
tags (comma-separated, OR match). Example: tags=vip,lead,partnerView documentation
LinkedIn ads now return delivery diagnostics and effective bidding details via new fields on
This lets you distinguish “configured active” vs “actually serving” and understand why a LinkedIn campaign/creative is not delivering (holds, review, budget, etc.).
New fields:
•
•
•
•
Also added to tree responses:
•
Note: for LinkedIn,
View documentation
Ad and GET /v1/ads/tree nodes.This lets you distinguish “configured active” vs “actually serving” and understand why a LinkedIn campaign/creative is not delivering (holds, review, budget, etc.).
New fields:
•
Ad.costType (LinkedIn only): CPM | CPC | CPV•
Ad.servingStatuses (LinkedIn only): array of serving/hold reasons (e.g. RUNNABLE, ACCOUNT_TOTAL_BUDGET_HOLD)•
Ad.creative.isServing (LinkedIn only): true | false | null•
Ad.creative.servingHoldReasons (LinkedIn only): creative-level hold reasons (e.g. UNDER_REVIEW, REJECTED)Also added to tree responses:
•
AdTreeAdSet.costType, AdTreeAdSet.servingStatusesNote: for LinkedIn,
bidAmount represents the campaign’s effective unitCost and can be 0 (a real, delivery-stopping value), independent of bidStrategy.View documentation
PostAnalytics now includes videoDurationSeconds (nullable integer).This exposes the video length (currently Instagram Reels only) so you can estimate retention when combined with
igReelsAvgWatchTime (ms).New field:
•
videoDurationSeconds - video length in seconds; null when unknown (non-video/other platforms, or when Instagram doesn’t expose the media URL, e.g. some copyrighted-audio reels).View documentation
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