Zernio | Developer News
687 subscribers
1 photo
1 video
482 links
This channel is for recurrent updates and announcements on https://zernio.com.

Zernio is a Social API for Posting and Analytics on 14 platforms.
Download Telegram
POST /v1/inbox/comments/{postId} now supports attaching an image when replying on Facebook via attachmentUrl.

This lets you publish a photo comment alongside the text reply. The image URL must be publicly accessible so Meta can fetch it.

New request field:
attachmentUrl (uri) — Facebook only

If attachmentUrl is sent for non-Facebook platforms, the API now returns 400 (e.g. code PLATFORM_NOT_SUPPORTED).

View documentation
Google Business batch reviews now supports server-side sorting via orderBy on POST /v1/accounts/{accountId}/gmb-reviews/batch.

This lets you fetch newest-updated reviews first (default) and stop paginating earlier when polling for recent changes.

Use orderBy:
updateTime desc (default)
rating
rating desc

Also note: locationNames is now capped at maxItems: 50 per request (chunk larger sets).

Responses now clarify attribution: each locationReviews[].name is the LOCATION resource name (not the review resource name), and review includes review.name (full review resource name) plus reviewMediaItems (photos/videos).

Inbox reviews (GET /v1/inbox/reviews) now includes Google Business location attribution fields: locationId (bare id) and locationName (display name).

View documentation
Meta insights now supports action-level segmentation and attribution controls on both the sync and async insights APIs.

You can segment actions[] and control attribution windows/reporting time without changing endpoints.

New on GET /v1/ads/insights:
actionBreakdowns
actionAttributionWindows
actionReportTime
useUnifiedAttributionSetting

New on POST /v1/ads/insights/reports:
actionBreakdowns
actionAttributionWindows (array of strings)
actionReportTime
useUnifiedAttributionSetting

Meta ad creation also adds hand-built carousels via carouselCards on POST /v1/ads/create (2–10 cards, deterministic order).

View documentation
2
New Meta Ads capabilities are available: ad previews, click-to-message ads, and click-to-call ads.

You can now render embeddable preview iframes before creating an ad via POST /v1/ads/preview (provide exactly one of existingCreativeId or creativeSpec) or for an existing ad via GET /v1/ads/{adId}/preview. Use formats (Meta ad_format values, max 10) to control placements.

Click-to-message ads are now unified under POST /v1/ads/messaging with destination:
whatsapp
messenger
instagram_direct

Click-to-call ads are supported via POST /v1/ads/call using phoneNumber (E.164) and linkUrl.

POST /v1/ads/ctwa is now deprecated; use POST /v1/ads/messaging with destination: whatsapp (the old endpoint remains for back-compat).

View documentation
New Meta Ads endpoints are available for live reads, auditing, studies, finances, and asset upload.

You can now:
• Read a live Meta ad set (incl. learning phase) via GET /v1/ads/ad-sets/{adSetId} with accountId and optional fields (default includes learning_stage_info).
• Fetch account audit/activity log via GET /v1/ads/activity using accountId, adAccountId, optional since/until, optional objectId (client-side filter), plus paging limit/after.
• List A/B tests & lift studies via GET /v1/ads/studies with accountId, adAccountId, optional fields, and paging limit/after.
• Read ad account finances via GET /v1/ads/accounts/finance (balance, amountSpent, spendCap, fundingSource).
• Upload ad images from base64 via POST /v1/ads/images with accountId, adAccountId, imageBase64 (optional filename); returns image.hash and image.url.

Also updated:
specialAdCategories now includes FINANCIAL_PRODUCTS_SERVICES and ONLINE_GAMBLING_AND_GAMING on POST /v1/ads/boost and POST /v1/ads/create.
callToAction enums expanded on POST /v1/ads/create (and Meta creatives[].callToAction) to include values like ADD_TO_CART, APPLY_NOW, BOOK_NOW, ORDER_NOW, INSTALL_MOBILE_APP, USE_APP (plus others).
POST /v1/ads/conversions: consent now affects Meta too — if adUserData or adPersonalization is DENIED, events are sent with Meta Limited Data Use (LDU); GRANTED (or omitted) uses default processing.

View documentation
Meta ads now support Reach & Frequency (RESERVED) buying via new R&F prediction + reservation endpoints.

You can request a quote (no spend, no entities created), reserve it to lock price/inventory, then create an ad using the reserved prediction.

New endpoints:
POST /v1/ads/rf-predictions (create quote; provide date range + exactly one of budgetAmount or reach)
GET /v1/ads/rf-predictions/{predictionId}
POST /v1/ads/rf-predictions/{predictionId}/reserve (returns a NEW RESERVED predictionId + expiresAt)
DELETE /v1/ads/rf-predictions/{predictionId} (cancel reservation)

POST /v1/ads/create adds:
buyingType: AUCTION | RESERVED
rfPredictionId (required when buyingType=RESERVED)

Notes: RESERVED uses the single-ad shape only (no creatives[], adSetId, existingCampaignId, or dynamicCreative). Budget/schedule/pricing come from the reservation; bid fields are ignored.

View documentation
SMS now supports alphanumeric sender IDs (e.g. ZERNIO) for one-way international texting.

Create/manage sender IDs via:
GET /v1/sms/sender-ids (includes workspace daily budget: budget.cap, budget.usedToday, budget.level, budget.pendingRequest)
POST /v1/sms/sender-ids with senderId (3–11 chars; letters/digits/spaces; at least one letter)
DELETE /v1/sms/sender-ids/{id}
POST /v1/sms/sender-ids/limit-request with requestedCap + reason

Sending: POST /v1/sms/messages now accepts from as either an SMS-enabled number or an approved sender ID.

Notes for sender IDs: text-only (no MMS), recipients can’t reply, and sends to US/CA/PR are blocked.

New responses to handle on POST /v1/sms/messages:
403 (gate: registration/MMS not supported/alpha to US-CA-PR)
429 (alphanumeric daily cap reached; code alpha_daily_limit_reached; resets midnight UTC)
404 now covers “no SMS-enabled number or sender ID matches from”.

View documentation
Meta Ads: new endpoints for campaign/creative management, duplication, and library access.

You can now create a standalone campaign shell, duplicate ad sets/ads via Meta native copy, manage creatives separately from ads, and query labels/images/creative library + budget schedules.

New endpoints:
• Create campaign (ODAX shell): POST /v1/ads/campaigns with goal (engagement, traffic, awareness, video_views, lead_generation, lead_conversion, job_applicants, conversions, app_promotion, catalog_sales), optional CBO via budgetAmount + budgetType (daily|lifetime), status (ACTIVE|PAUSED)
• Duplicate ad set: POST /v1/ads/ad-sets/{adSetId}/duplicate with deepCopy, campaignId, statusOption (ACTIVE|PAUSED|INHERITED_FROM_SOURCE), syncAfter
• Duplicate ad: POST /v1/ads/{adId}/duplicate with adSetId, statusOption (ACTIVE|PAUSED|INHERITED_FROM_SOURCE), syncAfter
• Creative library + CRUD: GET /v1/ads/creatives, POST /v1/ads/creatives (use imageUrl or imageHash or carouselCards), GET /v1/ads/creatives/{creativeId}, PUT /v1/ads/creatives/{creativeId} (rename via name), DELETE /v1/ads/creatives/{creativeId}
• Libraries/metadata: GET /v1/ads/images, GET /v1/ads/labels
• Budget schedules: GET /v1/ads/high-demand-periods (exactly one of campaignId or adSetId)

Audience updates expanded:
PUT /v1/ads/audiences/{audienceId} now supports updating platform audiences’ name/description (Meta only). spec is still allowed only for saved_targeting; sending spec for a platform audience returns 400. Non-Meta platform audience updates return 501.

View documentation
WhatsApp inbound attachments can now be downloaded via GET /v1/whatsapp/media/{mediaId}.

This streams the binary for a WhatsApp attachment referenced by attachments[].url in message.received webhooks and List messages.

Call it with:
mediaId (path) from attachments[].payload.id
accountId (query) = the WhatsApp account that received the media
Authorization: Bearer <your API key> (required; otherwise 401)

Important behavior:
• Download on receipt: WhatsApp media expires on Meta’s side (typically ~7 days). After expiry this endpoint returns 400 permanently (do not retry).

Removed endpoints:
GET /v1/sms/sender-ids, POST /v1/sms/sender-ids, POST /v1/sms/sender-ids/limit-request, DELETE /v1/sms/sender-ids/{id}
POST /v1/ads/campaigns
POST /v1/ads/ad-sets/{adSetId}/duplicate
POST /v1/ads/{adId}/duplicate
GET /v1/ads/labels
GET /v1/ads/high-demand-periods
GET/POST/GET/PUT/DELETE /v1/ads/creatives (and /v1/ads/creatives/{creativeId})
GET /v1/ads/images

Breaking change (SMS): POST /v1/sms/messages no longer supports alphanumeric sender IDs in from (now requires an SMS-enabled number).

View documentation
Discord: new member lookup + search endpoints, and guild member listing now fails fast when the Server Members Intent is missing.

You can now fetch a single member or prefix-search members without the privileged intent (useful when full listing is blocked).

New endpoints:
GET /v1/discord/guilds/{guildId}/members/{userId} (accountId)
GET /v1/discord/guilds/{guildId}/members/search (accountId, query, optional limit) — query is prefix-only

Breaking change:
GET /v1/discord/guilds/{guildId}/members now returns 403 if the Server Members Intent is not enabled (previously Discord could return an empty array).

SMS: alphanumeric Sender IDs are now supported.

Create and manage branded one-way SMS sender IDs (3–11 chars; letters/digits/spaces; at least one letter) and view the workspace-wide daily cap.

New endpoints:
GET /v1/sms/sender-ids (returns senderIds + budget with cap/usedToday/level/pendingRequest)
POST /v1/sms/sender-ids (senderId)
DELETE /v1/sms/sender-ids/{id}
POST /v1/sms/sender-ids/limit-request (requestedCap, reason)

Ads (Meta): new campaign/creative utilities + validate-only dry runs.

You can now create campaign shells, manage the creative library, duplicate ad sets/ads, and run a Meta validation pass without creating anything.

New endpoints:
POST /v1/ads/campaigns (standalone campaign)
POST /v1/ads/creatives, GET /v1/ads/creatives, GET /v1/ads/creatives/{creativeId}, PUT /v1/ads/creatives/{creativeId}, DELETE /v1/ads/creatives/{creativeId}
GET /v1/ads/images, GET /v1/ads/labels, GET /v1/ads/businesses, GET /v1/ads/high-demand-periods
POST /v1/ads/ad-sets/{adSetId}/duplicate, POST /v1/ads/{adId}/duplicate

New option on POST /v1/ads/create:
validateOnly: true (Meta only; single standalone shape only) — returns 200 with validation results instead of creating entities.

View documentation
Meta ads now support additional promoted-object fields, and some payloads are validated more strictly.

In POST /v1/ads/create, promotedObject adds:
offlineConversionDataSetId
whatsappPhoneNumber

In PUT /v1/ads/ad-sets/{adSetId}, platformSpecificData.promotedObject adds the same fields and now rejects unknown keys (additionalProperties: false), returning 400.

In POST /v1/ads/boost and POST /v1/ads/create, Meta adds specialAdCategoryCountry (array of 2-letter ISO codes). It requires specialAdCategories to be set (400 otherwise).

GET /v1/ads/audiences and POST /v1/ads/audiences add a new audience type value: meta_engagement.

View documentation
Meta ads updates:

You can now pass additional Meta promoted object fields, and some objects are now strictly validated (unknown keys will 400).

PUT /v1/ads/ad-sets/{adSetId}platformSpecificData.promotedObject now supports:
offlineConversionDataSetId, whatsappPhoneNumber
(unknown keys rejected; additionalProperties: false)

POST /v1/ads/createpromotedObject now supports:
offlineConversionDataSetId, whatsappPhoneNumber
(unknown keys rejected; additionalProperties: false)

POST /v1/ads/boost and POST /v1/ads/create now accept specialAdCategoryCountry (Meta only):
array of 2-letter ISO country codes; requires specialAdCategories to be set.

GET /v1/ads/audiences and POST /v1/ads/audiences add audience type value meta_engagement (Meta-only engagement audiences).

View documentation
Profile create/update now return 409 Conflict when the profile name is already taken.

This lets clients distinguish name collisions from generic validation errors and handle retries/renames cleanly.

New response:
POST /v1/profiles409 (code: profile_name_conflict)
PUT /v1/profiles/{profileId}409 (code: profile_name_conflict)

Several Ads read endpoints now also document 400 Bad Request for invalid query input:
GET /v1/ads400
GET /v1/ads/catalogs400
GET /v1/ads/catalogs/{catalogId}/product-sets400
GET /v1/ads/conversions/quality400

View documentation
WhatsApp template creation now supports carousel and limited time offer components in components on POST /v1/whatsapp/templates.

This lets you build richer MARKETING templates (multi-card carousels and offer labels/countdowns) using the same template creation endpoint.

New component types:
type=carousel with cards (2–10), each card components can include type=header, type=body, type=buttons
type=limited_time_offer with limited_time_offer.text (<=16 chars) and optional limited_time_offer.has_expiration

Phone number purchase adds wantsWhatsapp on POST /v1/phone-numbers/purchase (used when connectWhatsapp=false) to ensure the assigned number is WhatsApp-eligible by swapping it during purchase if needed.

View documentation
YouTube analytics endpoints now support returning provisional (not-yet-finalized) days when you set an explicit endDate up to today.

By default, endDate still resolves to the newest fully finalized day (~3-day delay). If you request into the delay window, the response indicates which days may still change.

Applies to:
GET /v1/analytics/youtube/daily-views
GET /v1/analytics/youtube/video-retention
GET /v1/analytics/youtube/demographics

New response field:
provisionalSince — first date in the returned range whose numbers are provisional and may be revised by YouTube.

View documentation
2
Zernio Ads now supports OpenAI Ads (ChatGPT Ads), including connect, create/manage, reporting, and conversions.

Connect an OpenAI Ads account via POST /v1/connect/openai-ads/credentials with apiKey and profileId (requires Ads add-on).

Ads endpoints now accept platform=openai:
GET /v1/ads, GET /v1/ads/campaigns, GET /v1/ads/tree, GET /v1/ads/timeline
• Campaign/ad set status updates: PUT /v1/ads/campaigns/{campaignId}/status, POST /v1/ads/campaigns/bulk-status, PUT /v1/ads/ad-sets/{adSetId}, PUT /v1/ads/ad-sets/{adSetId}/status

Creating ads: POST /v1/ads/create supports OpenAI Ads with:
goal: traffic | awareness | conversions
• Required creative fields: headline, body, imageUrl, linkUrl
• Budget: budgetType must be lifetime (sending daily returns 422) and requires endDate

Conversions: POST /v1/ads/conversions now supports accountId platform openaiads.
• Use GET /v1/accounts/{accountId}/conversion-destinations to get the OpenAI pixel destinationId (pixel wire id)
• If no pixel exists yet, create one via POST /v1/accounts/{accountId}/tracking-tags (OpenAI Ads may return 422 if pixel management isn’t enabled)

Note: PUT /v1/ads/{adId} supports OpenAI Ads for status + budget only (no targeting/creative updates). DELETE /v1/ads/{adId} archives OpenAI Ads (no platform delete API).

View documentation
🔥3👏2
PUT /v1/ads/ad-sets/{adSetId} now supports updating bid strategy for platform=openai.

You can set OpenAI ad group bidding via bidStrategy + bidAmount; bidAmount is converted to micros (× 1,000,000).

Use bidStrategy:
LOWEST_COST_WITH_BID_CAP (requires bidAmount)
COST_CAP (requires bidAmount)

LOWEST_COST_WITH_MIN_ROAS is not supported on OpenAI and will return 422.

View documentation
KYC reuse selection now supports a stable option identifier via reusable.options[].id, and KYC reuse options now include instant to indicate activation speed.

This makes selecting which prior verification to reuse unambiguous (a phone number may label multiple verifications) and lets you know whether reuse activates in minutes or still queues for carrier review.

Use on submit:
POST /v1/phone-numbers/kyc: pass reuseOptionId (preferred)
reuseFrom is now a legacy fallback and may be ambiguous

Returned on form spec:
GET /v1/phone-numbers/kyc (and the deprecated WhatsApp alias): reusable.options[] now includes id and instant

View documentation
👏1
You can now view KYC documents on file via GET /v1/phone-numbers/kyc/document/{documentId}.

This streams the stored verification document inline as application/pdf, so users can confirm what’s on file before reusing a verification. Access is auth-scoped (returns 404 if the documentId isn’t referenced by one of your numbers).

KYC spec responses now include documentId on document rows:
GET /v1/phone-numbers/kycreusable.options[].details[].documentId
GET /v1/whatsapp/phone-numbers/kycreusable.options[].details[].documentId

Use that documentId as the {documentId} path parameter when fetching the PDF.

View documentation
1
New endpoint: POST /v1/phone-numbers/{id}/remediate/reply lets you reply to a regulatory reviewer on a phone number awaiting remediation, including optional file attachments.

Use it when the reviewer asks for info the structured remediation form can’t express; posting a reply can move the number back to in review (comment-style asks). Requires text or at least one attachments item.

Request body:
text (string, max 2000)
attachments (array, max 5) items: { filename, base64 } (PDF/JPG/PNG/WEBP, max 10MB each)

Response 200:
posted (boolean)
attachments (integer uploaded)

Errors: 400, 401, 404, 502 (retry).

View documentation
👍1
GET /v1/profiles now supports exact-name filtering and pagination, and the default sort order is now default-first (then creation date).

Use name (exact match) to find a profile by name, and limit/skip to paginate. When limit or skip is provided, the response may include total, skip, and limit.

New query params: name, limit (1..1000), skip (>=0)

POST /v1/profiles now supports idempotent retries via Idempotency-Key (header).

With Idempotency-Key: same key + same body replays the original 201; same key + different body returns 422; key still processing returns 409. Duplicate name conflicts (409) now include details.existingProfileId.

View documentation
1