WhatsApp inbox messages now support commerce interactive messages (products, product lists, catalog messages, and carousels) via
This lets you send catalog-driven messages and receive cart submissions / product inquiries back in webhooks.
New
•
Webhook
•
•
Note: interactive messages are session messages (must be sent within WhatsApp’s 24-hour window).
View documentation
interactive on POST /v1/inbox/conversations/{conversationId}/messages.This lets you send catalog-driven messages and receive cart submissions / product inquiries back in webhooks.
New
interactive.type values:•
product, product_list, catalog_message, carouselWebhook
message.received metadata adds:•
metadata.order (cart submitted from commerce messages)•
metadata.referredProduct (product inquiry context)Note: interactive messages are session messages (must be sent within WhatsApp’s 24-hour window).
View documentation
❤2
Ads reporting endpoints may now return
When this happens, the response includes currently-available data plus
Applies to:
•
•
•
•
•
Also,
•
•
View documentation
202 when part of the requested date range isn’t ingested yet.When this happens, the response includes currently-available data plus
backfillPending: true, and a Retry-After header with the recommended poll interval. Repeat the same request until it returns 200 with the full range.Applies to:
•
GET /v1/ads•
GET /v1/ads/tree•
GET /v1/ads/timeline•
GET /v1/ads/campaigns/{campaignId}/analytics•
GET /v1/ads/{adId}/analyticsAlso,
POST /v1/posts 403 responses now include a stable code to distinguish causes:•
ACCOUNT_DISCONNECTED•
PROFILE_OVER_LIMITView documentation
❤4
You can now update saved_targeting audiences via
This lets you change an audience’s
Request body (send at least one):
Also:
View documentation
PUT /v1/ads/audiences/{audienceId}.This lets you change an audience’s
name, description, or fully replace its spec (no merge). Uploaded/derived audiences aren’t updatable and return 422.Request body (send at least one):
name, description, specAlso:
GET /v1/ads/audiences now returns accountId for type=saved_targeting items, and DELETE /v1/ads/audiences/{audienceId} clarifies that saved_targeting deletes only the local record (it exists only on Zernio).View documentation
❤2
GET /v1/ads/{adId}/analytics and GET /v1/ads/campaigns/{campaignId}/analytics now validate breakdown dimensions and will return 400 for unknown values.This prevents silent/partial breakdown results and makes invalid
breakdowns requests fail fast with a supported-values list.Updates:
•
breakdowns: unknown dimensions now return 400 (instead of being ignored)•
placement is accepted as an alias for publisher_platform•
breakdown (singular) is also acceptedNew Meta breakdown options include:
platform_position, impression_device, video_asset, image_asset, body_asset, title_asset.View documentation
GET /v1/analytics now supports a new metric: follows.You can read
analytics.follows in responses (Instagram feed posts and stories only: organic accounts that started following from this post; 0 for reels and other platforms).You can also sort analytics results by
sortBy = follows (enum now includes: date, engagement, impressions, reach, likes, comments, shares, saves, clicks, views, follows).View documentation
❤2
The supported
If you request breakdowns that are no longer supported, your call may fail (400) or no longer return those breakdowns.
Affected endpoints:
•
•
View documentation
breakdowns values were reduced on analytics endpoints.If you request breakdowns that are no longer supported, your call may fail (400) or no longer return those breakdowns.
Affected endpoints:
•
GET /v1/ads/{adId}/analytics: Meta breakdowns now limited to age, gender, country, publisher_platform, device_platform, region (removed: platform_position, impression_device, video_asset, image_asset, body_asset, title_asset; also removed aliases placement and singular breakdown)•
GET /v1/ads/campaigns/{campaignId}/analytics: Meta breakdowns now limited to age, gender, country, publisher_platform, device_platform, region, platform_position, impression_device, video_asset, image_asset, body_asset, title_asset (removed aliases placement and singular breakdown)View documentation
❤1
Google Business Profile posts:
If you were sending
•
•
•
View documentation
offer.offerType has been removed from GoogleBusinessPlatformData.If you were sending
offerType (previously OFFER or BUY_ONE_GET_ONE), remove it from your payloads and use the remaining offer fields instead:•
redeemOnlineUrl•
termsConditions•
couponCodeView documentation
❤1
POST
This can break existing integrations that submit
For
For
Webhook post events now echo back your post’s free-form
•
•
View documentation
/v1/sms/registrations now enforces additional required fields for 10DLC registrations.This can break existing integrations that submit
brand/campaign without the newly-required fields.For
brand, these fields are now required: website, street, city, state, postalCode (in addition to existing required fields).For
campaign, sample2 is now required and must be distinct from sample1.Webhook post events now echo back your post’s free-form
metadata (when provided at create time) in:•
WebhookPayloadPost.post.metadata•
WebhookPayloadPostPlatform.post.metadataView documentation
❤1
POST
You can either upload bytes with
New JSON body option:
•
•
New response to handle:
•
View documentation
/v1/whatsapp/business-profile/photo now accepts an image via URL in addition to multipart upload.You can either upload bytes with
multipart/form-data (file) or send application/json with url; we fetch the image server-side and upload the bytes to Meta.New JSON body option:
•
accountId•
url (public https image URL; must resolve directly without redirects)New response to handle:
•
422 when the profile photo is locked for WhatsApp coexistence numbers (must be managed in the WhatsApp Business app).View documentation
❤1
New billing snapshot endpoint:
It returns the billing “statement” view (plan, current cycle, balance/credits, spend caps, and payment/access status). Use this for billing state; use
Key response blocks:
•
•
•
•
•
Also:
• Default (no metering params): same snapshot as before
• Metering mode (billed spend by product) when passing any of:
Metering params:
•
•
•
Stripe accounts calling metering mode receive
View documentation
GET /v1/billing.It returns the billing “statement” view (plan, current cycle, balance/credits, spend caps, and payment/access status). Use this for billing state; use
GET /v1/usage for usage/metering.Key response blocks:
•
plan (includes isUsageBased)•
period (start/end may be null on Stripe)•
balance (null for Stripe; populated for Metronome)•
caps (e.g. xSpendUsedCents, xSpendLimitCents)•
status (e.g. hasAccess, suspended, openInvoiceUrl, declineReason)Also:
GET /v1/usage is now dual-mode.• Default (no metering params): same snapshot as before
• Metering mode (billed spend by product) when passing any of:
range, granularity, from, toMetering params:
•
range: cycle | prev-cycle | 7d | 14d | 30d | 3mo | 12mo | custom•
granularity: day | month | total•
from/to required when range=customStripe accounts calling metering mode receive
{ "supported": false }.View documentation
❤1
Webhooks now support additional event subscriptions for conversations, calls, leads, and WhatsApp.
You can subscribe to these new
•
•
•
•
SMS carrier registrations (10DLC) now accept
For rejected registrations,
View documentation
You can subscribe to these new
events via POST /v1/webhooks/settings or PUT /v1/webhooks/settings:•
conversation.started•
call.received, call.ended, call.failed, call.permission_request•
lead.received•
whatsapp.automatic_eventSMS carrier registrations (10DLC) now accept
campaign.subUsecases on POST /v1/sms/registrations (2–5 values): 2FA, ACCOUNT_NOTIFICATION, CUSTOMER_CARE, DELIVERY_NOTIFICATION, FRAUD_ALERT, HIGHER_EDUCATION, MARKETING, POLLING_VOTING, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT.For rejected registrations,
GET /v1/sms/registrations/{id} may now include campaignContent (messageFlow, sample1, sample2), and POST /v1/sms/registrations/{id}/appeal can include corrected messageFlow/sample1/sample2 along with appealReason.View documentation
❤2
GET /v1/usage now includes estimated tax via a new tax field on UsageMetering.This lets you show an estimated tax amount (computed with Stripe Tax) on top of the window’s net spend (
totals.total). tax is null when no billing address is on file, the total is ≤ 0, or the estimate fails.New fields:
•
tax.taxUsd — estimated tax in USD (added on top of totals.total)•
tax.ratePercent — combined rate percentage (nullable)•
tax.jurisdictionLabel — human label like “ES VAT” (nullable)•
tax.reverseCharge — true for EU/UK B2B reverse charge (0 tax added)View documentation
❤2
POST
This lets you restrict CTWA ad delivery to specific Meta surfaces/devices instead of using automatic placements (Meta may still enforce eligibility/co-selection rules and return actionable errors).
Use
•
•
•
View documentation
/v1/ads/ctwa now supports manual ad placements via placements.This lets you restrict CTWA ad delivery to specific Meta surfaces/devices instead of using automatic placements (Meta may still enforce eligibility/co-selection rules and return actionable errors).
Use
placements with:•
publisherPlatforms: facebook | instagram | threads | messenger | audience_network•
facebookPositions, instagramPositions, messengerPositions, audienceNetworkPositions, threadsPositions, whatsappPositions•
devicePlatforms: mobile | desktopView documentation
❤2
Meta placements now support delivering ads on WhatsApp by allowing
This lets you explicitly include WhatsApp inventory when using manual placements (instead of relying on automatic placements).
Set
•
Applies to:
•
•
View documentation
whatsapp in placements.publisherPlatforms.This lets you explicitly include WhatsApp inventory when using manual placements (instead of relying on automatic placements).
Set
placements.publisherPlatforms to include:•
whatsapp (alongside facebook, instagram, threads, messenger, audience_network)Applies to:
•
POST /v1/ads/create•
POST /v1/ads/ctwaView documentation
❤4
GET /v1/inbox/conversations/search now searches by contact identity (participant name/username/phone) in addition to message text, returning matching conversations once (message matches included when present).Contact-identity matches are case-insensitive substrings; they return
matchCount=0 and matches=[]. Note: identity matching is not applied when direction is set (incoming | outgoing).Also updated:
• Searchable platforms now include Twitter/X and Reddit; Bluesky is live-fetched and appears in
meta.accountsSkipped• Response adds
conversation.lastMessage (most recent message preview)View documentation
GET
This lets you filter out ad accounts that can’t currently create/run ads and show a user-friendly reason in your UI.
New fields in
•
•
On non-Meta platforms these fields are absent (treat
View documentation
/v1/ads/accounts now returns Meta ad account usability flags: selectable and unusableReason.This lets you filter out ad accounts that can’t currently create/run ads and show a user-friendly reason in your UI.
New fields in
accounts[] (Meta only):•
selectable (boolean) — whether the account can create/run ads now•
unusableReason (string|null) — reason when selectable is false; null when selectableOn non-Meta platforms these fields are absent (treat
selectable as true).View documentation
❤2
WhatsApp template sends via
This lets you use a single approved template with an image/video/document header while sending a different asset for each recipient (e.g. a unique invoice PDF), instead of always sending the template’s approved sample asset.
Set
•
• Provide exactly one of
• Optional:
View documentation
POST /v1/inbox/conversations now support overriding a media-header template asset per message using headerMedia.This lets you use a single approved template with an image/video/document header while sending a different asset for each recipient (e.g. a unique invoice PDF), instead of always sending the template’s approved sample asset.
Set
headerMedia (JSON body only):•
type: image | video | document (must match the template header type)• Provide exactly one of
link (public URL) or id (Meta media id)• Optional:
filename (document only)View documentation
❤1
conversation.started webhooks now include SMS conversations via conversation.platform.This lets you receive “new conversation started” events for SMS in the same platform-agnostic subscription.
New enum value:
•
conversation.platform: sms (in addition to existing platforms)View documentation
❤2
New endpoint:
This is ad-scoped only (does not affect the parent ad set/campaign), and is a thin wrapper around updating the ad
Set
Response includes
View documentation
PUT /v1/ads/{adId}/status to pause/resume a single ad.This is ad-scoped only (does not affect the parent ad set/campaign), and is a thin wrapper around updating the ad
status.Set
status to active or paused. {adId} accepts Zernio _id, Meta platformAdId, or the creative’s effective story/media IDs.Response includes
updated (1/0) and skipped (1/0); message is returned when the change is skipped (terminal status or already in target state).View documentation
❤1
POST
Use
New/updated request behavior:
•
•
•
View documentation
/v1/phone-numbers/port-in now supports portType to specify whether you’re porting the entire losing account or only some numbers.Use
portType to avoid ambiguity on ports where the losing account keeps some numbers.New/updated request behavior:
•
portType: full | partial (default: full)•
endUser.billingPhoneNumber: now documented as the number on the losing carrier’s bill; defaults to the ported number itself on single-number orders•
focDatetimeRequested: when omitted, defaults to ~1 week out (shifted off weekends)View documentation
❤2
Meta ads now support setting EU DSA (Article 26) defaults at the ad-account level, so EU-targeted calls can omit per-ad
Set defaults once via
Read current defaults via
View documentation
dsaBeneficiary/dsaPayor when defaults are configured.Set defaults once via
PATCH /v1/ads/accounts with accountId, adAccountId, defaultDsaBeneficiary, optional defaultDsaPayor (if omitted, payor defaults to beneficiary).Read current defaults via
GET /v1/ads/dsa-defaults (accountId, adAccountId), and fetch Meta-provided suggestions via GET /v1/ads/dsa-recommendations (accountId, adAccountId).POST /v1/ads/create, POST /v1/ads/boost, and POST /v1/ads/ctwa now treat dsaBeneficiary/dsaPayor as optional for EU targeting when the Meta ad account has defaults set (Meta accounts only; other platforms return 400).View documentation
❤1