WhatsApp sends via
If you send bursts to the same recipient, WhatsApp may reject excess messages with Meta error code
If you see
View documentation
POST /v1/inbox/conversations/{conversationId}/messages now document a per-recipient rate limit.If you send bursts to the same recipient, WhatsApp may reject excess messages with Meta error code
131056 ("Too many messages sent to this recipient"). Pace sends to a single recipient to ~10/min; sends to other recipients are unaffected.If you see
400 responses with platformError.code = 131056, throttle per recipient and retry later.View documentation
WhatsApp templates now support working with a specific Meta template variant via its Meta template id.
New endpoints:
•
•
•
Template listing and name-based operations are now language-aware (Meta stores templates per
•
•
•
Delete behavior change:
•
View documentation
New endpoints:
•
GET /v1/whatsapp/templates/id/{templateId} (requires accountId)•
PATCH /v1/whatsapp/templates/id/{templateId} (body: accountId, components)•
DELETE /v1/whatsapp/templates/id/{templateId} (requires accountId)Template listing and name-based operations are now language-aware (Meta stores templates per
name + language):•
GET /v1/whatsapp/templates adds filters: name, language, status (APPROVED/REJECTED/PENDING/PAUSED/DISABLED/IN_APPEAL/PENDING_DELETION)•
GET /v1/whatsapp/templates/{templateName} adds optional language; if multiple variants exist and no language is provided, it can return 409 ambiguous_template with details.languages•
PATCH /v1/whatsapp/templates/{templateName} now takes language in the request body (required when multiple variants exist); missing language can return 409 ambiguous_templateDelete behavior change:
•
DELETE /v1/whatsapp/templates/{templateName} without language deletes all language variants; with language it deletes only that variant and returns scope = all_languages or language.View documentation
PostAnalytics.follows can now be null in GET /v1/analytics responses.This affects Instagram where Meta doesn’t expose
follows for Reels and non-Reels video; in those cases Zernio will return null instead of 0. Update your parsing/aggregation to handle follows: null (treat as “unknown/not available”, not zero).View documentation
Some endpoints now return additional billing/capability errors you may need to handle.
Posts listing may now fail with
OpenAI Ads connect may now return
SMS sender ID creation now has explicit billing-related failures on
•
•
View documentation
Posts listing may now fail with
403 when X analytics isn’t enabled for the account (code X_ANALYTICS_NOT_ENABLED) on GET /v1/accounts/{accountId}/posts.OpenAI Ads connect may now return
402 PaymentRequired on POST /v1/connect/openai-ads/credentials.SMS sender ID creation now has explicit billing-related failures on
POST /v1/sms/sender-ids:•
402 (code payment_required) when no payment method is on file•
409 (code billing_setup_incomplete) when billing setup is incompleteView documentation
Some endpoints now return additional error statuses you may need to handle.
Posts listing can now return
•
Billing-gated connect / SMS setup now surfaces payment/setup issues explicitly.
•
•
View documentation
Posts listing can now return
403 when X analytics isn’t enabled for the account.•
GET /v1/accounts/{accountId}/posts → 403 (code X_ANALYTICS_NOT_ENABLED)Billing-gated connect / SMS setup now surfaces payment/setup issues explicitly.
•
POST /v1/connect/openai-ads/credentials → 402 (PaymentRequired)•
POST /v1/sms/sender-ids → 402 (code payment_required), 409 (code billing_setup_incomplete)View documentation
Creating or retrying posts can now return 403 with
This happens when the target
Applies to:
•
•
View documentation
code=ACCOUNT_NOT_ENABLED_FOR_POSTING.This happens when the target
accountId is connected for ads only (i.e., enabled: false) and cannot be posted to. Connect the account as a posting account, refresh IDs via GET /v1/accounts, then retry.Applies to:
•
POST /v1/posts (403 code enum now includes ACCOUNT_NOT_ENABLED_FOR_POSTING)•
POST /v1/posts/{postId}/retry (403 may include ACCOUNT_NOT_ENABLED_FOR_POSTING, PROFILE_OVER_LIMIT, or insufficient_permissions)View documentation
WhatsApp template sends via
If you provide fewer values than the template’s required header + body + dynamic URL-button slots, the request is rejected with
Key fields:
•
•
View documentation
POST /v1/inbox/conversations now validate templateParams more strictly for positional templates.If you provide fewer values than the template’s required header + body + dynamic URL-button slots, the request is rejected with
400 (INVALID_TEMPLATE_PARAMS) instead of sending a message with misaligned values.Key fields:
•
templateParams - must cover all required slots for positional templates•
templateButtonParams - can override a button’s value; overridden buttons may not need a value in templateParams unless later uncovered dynamic URL buttons followView documentation
GET
This makes it easier to build adset-centric dashboards by listing only ads within a specific platform ad set.
Use
PUT
Meta creative updates are now patch-style: send any subset of
Key Meta-only options in
•
•
•
GET
These ids can be used in
•
•
•
Also,
View documentation
/v1/ads now supports filtering by Meta ad set via adSetId.This makes it easier to build adset-centric dashboards by listing only ads within a specific platform ad set.
Use
adSetId (platform ad set id) alongside existing filters like campaignId.PUT
/v1/ads/{adId} now supports richer creative updates, especially for Meta.Meta creative updates are now patch-style: send any subset of
creative fields and omitted fields are preserved (including existing media), and you can also repoint an ad to an existing creative.Key Meta-only options in
creative:•
description (link description)•
videoId (reuse an already-uploaded video)•
existingCreativeId (repoint to a creative from GET /v1/ads/creatives; ignores other creative fields)GET
/v1/ads/targeting/search now supports Meta work demographics via dimension values workPosition, workEmployer, workIndustry.These ids can be used in
TargetingSpec as:•
workPositions•
workEmployers•
workIndustriesAlso,
TargetingSpec audience lists are now supported: audienceInclude and audienceExclude accept platform audience IDs (not supported on OpenAI Ads; returns 400).View documentation
GET /v1/connect/pending-data pending OAuth tokens are now repeatable and expire 1 hour after issuance (previously one-time use, 10 minutes).This makes headless OAuth selection flows more resilient (you can re-fetch the pending selection data until the user completes selection; completion deletes the pending record).
Use
token (query) from pendingDataToken on the redirect. selectionType can be: organizations, pages, boards, locations, profiles.Scope note: this pending-data flow now covers Google Business locations and Slack channels in addition to existing large selection lists.
View documentation
Several Ads endpoints can now return
This happens when a team has no payment method on file and has reached the 500 free live ads limit; add a card to resume/continue.
You may see this on:
•
•
•
•
•
•
•
•
•
•
•
•
•
If you have retry logic, treat
View documentation
403 with code ads_allowance_exceeded.This happens when a team has no payment method on file and has reached the 500 free live ads limit; add a card to resume/continue.
You may see this on:
•
PUT /v1/ads/campaigns/{campaignId}/status•
PUT /v1/ads/campaigns/{campaignId}•
POST /v1/ads/campaigns/bulk-status•
POST /v1/ads/campaigns/{campaignId}/duplicate•
POST /v1/ads/ad-sets/{adSetId}/duplicate•
POST /v1/ads/{adId}/duplicate•
PUT /v1/ads/ad-sets/{adSetId} and PUT /v1/ads/ad-sets/{adSetId}/status•
PUT /v1/ads/{adId} and PUT /v1/ads/{adId}/status•
PATCH /v1/ads/{adId}/tracking-tags•
POST /v1/ads/create•
POST /v1/ads/boost•
POST /v1/ads/messaging, POST /v1/ads/call, POST /v1/ads/ctwa•
POST /v1/ads/campaigns/{campaignId}/assetsIf you have retry logic, treat
403 ads_allowance_exceeded as non-retryable until billing is set up.View documentation
Meta ads now accept regional regulated categories on ad set creation/boosting.
Use this when targeting countries where Meta requires extra regulation flags (e.g. Singapore/Taiwan/Thailand/Australia/India). Without it, Meta may reject the ad set.
Send
•
•
Example values include
View documentation
Use this when targeting countries where Meta requires extra regulation flags (e.g. Singapore/Taiwan/Thailand/Australia/India). Without it, Meta may reject the ad set.
Send
regionalRegulatedCategories (array of strings) on:•
POST /v1/ads/create•
POST /v1/ads/boostExample values include
SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV.View documentation
Instagram comment-to-DM private replies may now fail for non-followers when you include interactive elements.
Since late Aug 2026, Instagram can refuse
If you need to reach non-followers, send plain text using
View documentation
Since late Aug 2026, Instagram can refuse
buttons (and other attachments/cards) to commenters who don’t follow the account, returning a non-retryable 400 (Meta code 2, subcode 1545133). The failed call still consumes the comment’s single private reply.If you need to reach non-followers, send plain text using
message only, then add buttons after they reply. (quickReplies and buttons remain mutually exclusive.)View documentation
New endpoint
This lets integrations stay in sync with far fewer calls than polling
Key params:
•
•
•
•
Response fields:
•
•
•
New webhook event available for subscriptions:
View documentation
GET /v1/analytics/delta returns a cursor-based feed of analytics snapshots that changed across all readable accounts.This lets integrations stay in sync with far fewer calls than polling
GET /v1/analytics per account; bootstrap once from GET /v1/analytics, then poll deltas.Key params:
•
cursor (opaque; omit to start “from now” and receive data: [] + nextCursor)•
limit (1–100, default 50; out-of-range = 400)•
platform (optional)•
profileId (default all)Response fields:
•
data (oldest-first changed snapshots)•
nextCursor (always present, even on empty pages)•
hasMore (if true, call again immediately)New webhook event available for subscriptions:
analytics.synced. It’s a trigger (no metrics/cursor); on receipt, call GET /v1/analytics/delta using your last stored nextCursor.View documentation
Meta ads now support regional regulation identity mapping via
When you include
Set:
•
•
If omitted, Meta may use Ads Manager defaults when configured.
View documentation
regionalRegulationIdentities on POST /v1/ads/create and POST /v1/ads/boost.When you include
regionalRegulatedCategories (e.g. BRAZIL_REGULATION, SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV, TAIWAN_FINSERV), you can now pass the required Meta-verified beneficiary/payer entity IDs in regionalRegulationIdentities.Set:
•
regionalRegulatedCategories: [...]•
regionalRegulationIdentities: { universal_beneficiary: 123, universal_payer: 456, ... }If omitted, Meta may use Ads Manager defaults when configured.
View documentation
Instagram publishing now supports paid partnership, sponsor tagging, comment toggling, and location tagging via new fields in
Use:
•
•
•
•
View documentation
platformSpecificData.Use:
•
isPaidPartnership (boolean) — adds the “Paid partnership” label (feed/Reels/carousels; Stories return 400). Requires Facebook Login connection.•
brandedContentSponsors (array, max 2) — tag sponsor brands by username (optional @) or numeric IG user ID; implies isPaidPartnership.•
commentsEnabled (boolean, default true) — when false, turns off comments after publish (best-effort; Stories ignored).•
locationId (string digits) — tags the post location using a Facebook Page ID with location data (feed/Reels/carousels; Stories rejected with 400).View documentation
Meta ads created via
This lets you send 1–5 variations of primary text/headlines (and optionally descriptions) and have Meta optimize delivery across them, without using full
Use:
•
•
•
Requires
View documentation
POST /v1/ads/create now support Multiple Text Options (Advantage+ Flexible Format) using new top-level fields bodies, headlines, and optional descriptions.This lets you send 1–5 variations of primary text/headlines (and optionally descriptions) and have Meta optimize delivery across them, without using full
dynamicCreative.Use:
•
bodies (1–5)•
headlines (1–5)•
descriptions (0–5)Requires
imageUrl or video, plus linkUrl and callToAction. When set, top-level body and headline are used for preview text (object_story_spec), and this mode is mutually exclusive with dynamicCreative, placementAssets, carouselCards, and creatives[].View documentation
🔥1
WhatsApp Flows now supports managing the Flows endpoint encryption key via new endpoints.
You can check whether a business RSA public key is registered (and retrieve it) and register/replace the key used for endpoint-backed flows (
New endpoints:
•
•
Note: only one key is active per phone number; replacing the key requires your flow endpoint to serve the matching private key or
View documentation
You can check whether a business RSA public key is registered (and retrieve it) and register/replace the key used for endpoint-backed flows (
flow_action: data_exchange).New endpoints:
•
GET /v1/whatsapp/flows/encryption-key (query accountId) returns publicKey, registered, signatureStatus (VALID | MISMATCH)•
POST /v1/whatsapp/flows/encryption-key body: accountId, businessPublicKey (PEM)Note: only one key is active per phone number; replacing the key requires your flow endpoint to serve the matching private key or
data_exchange flows will fail at runtime.View documentation