Zernio | Developer News
691 subscribers
1 photo
1 video
487 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
GET /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 selectable

On non-Meta platforms these fields are absent (treat selectable as true).

View documentation
2
WhatsApp template sends via 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: 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 /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 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
GET /v1/inbox/reviews now returns Google Business review photo info via hasPhotos and photoCount.

This lets you detect and display reviews with attached photos (Google Business only; other platforms return hasPhotos=false and photoCount=0).

New fields:
hasPhotos
photoCount

GET /v1/ads/accounts now includes Meta’s minimum daily budget via minimumDailyBudget.

Use this to validate budget inputs against account-level minimums (field may be absent if the connected token can’t read it).

New field:
minimumDailyBudget

View documentation
1
Analytics responses now include media accessibility alt text via mediaItems[].altText.

Use this to display or audit the alt text set on each media item when available.

New field:
mediaItems[].altText (string)

Included in:
AnalyticsSinglePostResponse
AnalyticsListResponse

View documentation
1
Comment-to-DM automations now support message variations for random rotation of DM text and public comment replies.

This lets you provide multiple alternate texts so repeat triggers don’t always send identical messages.

New optional fields:
• Create/Update: dmMessageVariations (up to 5), commentReplyVariations (up to 5)
• Returned on list/detail/update responses: dmMessageVariations, commentReplyVariations

Rotation behavior:
• DM text is picked at random from [dmMessage, ...dmMessageVariations]
• Public reply is picked at random from [commentReply, ...commentReplyVariations]

Applies to: POST /v1/comment-automations, PATCH /v1/comment-automations/{automationId}, GET /v1/comment-automations, GET /v1/comment-automations/{automationId}.

View documentation
2
LinkedIn ads now support campaign bidding & delivery controls via platformSpecificData on POST /v1/ads/create and POST /v1/ads/boost.

This lets you set LinkedIn-specific options (manual bids, cost model, audience expansion, Audience Network, etc.) while keeping the platform inferred from accountId (sending options for a different platform returns 400).

Use platformSpecificData (LinkedIn only):
costType: CPM | CPC | CPV
unitCost (manual bid; requires costType)
optimizationTargetType (pass-through)
creativeSelection: OPTIMIZED | ROUND_ROBIN
audienceExpansionEnabled, offsiteDeliveryEnabled, connectedTelevisionOnly

View documentation
Sole-prop 10DLC registrations can now re-send the OTP via POST /v1/sms/registrations/{id}/resend-otp.

Use this when the original code expired or never arrived. It only works while the registration is pending and awaiting OTP, and is rate-limited to 1 request/min.

Request: id (path)
Response: { sent: boolean }
Errors: 400 not awaiting OTP, 404 not found, 429 wait 1 minute

Port-in updates:
POST /v1/phone-numbers/port-in: endUser.accountNumber is now required (and endUser.countryCode is restricted to US/CA)
POST /v1/phone-numbers/port-in/check: response adds lineType (when known) to indicate if a transfer PIN is required at submit

10DLC campaign submissions:
POST /v1/sms/registrations: campaign.optinMessage, campaign.optoutMessage, and campaign.helpMessage are now optional; when omitted, compliant templates are generated.

View documentation
1👏1
POST /v1/ads/create now supports more LinkedIn ad formats via platformSpecificData.

You can create LinkedIn-only creatives (beyond single image/video) by setting one of these mutually-exclusive options:
platformSpecificData.carousel (2–10 cards)
platformSpecificData.document (PDF/PPT/DOC)
platformSpecificData.spotlight (dynamic spotlight)
platformSpecificData.follower (dynamic follower)
platformSpecificData.textAd (right-rail text ad)
platformSpecificData.event (promote an existing event)

Notes:
• Carousel cards use cards[].imageUrl and optionally cards[].headline / cards[].landingUrl (falls back to ad-level linkUrl).
• Document ads use document.url + document.title.
• Spotlight ads use spotlight.headline + spotlight.callToAction + spotlight.landingUrl.
• Follower ads use follower.callToAction enum: VISIT_ORGANIZATION_COMPANY_PAGE, VISIT_ORGANIZATION_LIFE_PAGE, VISIT_ORGANIZATION_JOBS_PAGE, VISIT_ORGANIZATION_CAREERS_PAGE.

Also clarified: on LinkedIn, imageUrl + linkUrl publishes an ARTICLE-content creative (with longHeadline as the description).

View documentation
1👏1
POST /v1/ads/create now supports LinkedIn Jobs ads via a new goal job_applicants.

This lets you create Dynamic Jobs Ads that promote open roles (requires a Company Page with active job postings).

Use:
goal: job_applicants
platformSpecificData.jobs with headline and buttonLabel (each takes exactly one of preApproved or custom)

Also added for LinkedIn-only creatives on platformSpecificData:
conversation (Conversation Ads) with subject, firstMessageId, and messages (buttons use exactly one of nextMessageId or url).

View documentation
LinkedIn firmographic breakdowns are now supported in analytics via the breakdowns query param on GET /v1/ads/{adId}/analytics and GET /v1/ads/campaigns/{campaignId}/analytics.

This lets you request LinkedIn aggregated firmographic segments for the requested date range (note: LinkedIn data is aggregated over the whole range, delayed 12–24h, and segments with <3 events are omitted).

Use breakdowns with LinkedIn dimensions:
job_title, job_function, seniority, industry
company, company_size
country, region

LinkedIn breakdown rows include the raw pivot value plus a resolved name.

View documentation
Custom audiences now support new types: company_list and engagement on /v1/ads/audiences.

You can list and filter these via GET /v1/ads/audiences using type = customer_list | company_list | engagement | website | lookalike | saved_targeting.

To create them via POST /v1/ads/audiences:
type=engagement (LinkedIn): requires sourceType (VIDEO_ADS | LEAD_GEN_FORMS | ORGANIZATION_PAGES | EVENT_PAGES | SINGLE_IMAGE_ADS), plus trigger, lookbackDays (30 | 60 | 90 | 180 | 365), and engagementSources.
type=company_list (LinkedIn): requires companies (array of company rows like name, domain, website, linkedinPageUrl).

View documentation
2
Website retargeting audiences are now supported via a new audience type: website_retargeting (LinkedIn only).

You can now create and list these audiences using type=website_retargeting on POST /v1/ads/audiences and filter them via GET /v1/ads/audiences.

When creating, set:
type: website_retargeting
matchRules: array of URL patterns (matchType: EXACT | STARTS_WITH | CONTAINS | ENDS_WITH, plus matchValue)

View documentation
New endpoint: POST /v1/accounts/{accountId}/pinterest-boards to create Pinterest boards on a connected Pinterest account.

The returned board.id can be used immediately as platformSpecificData.boardId when creating a Pinterest post.

Request body:
name (required)
description
privacy: PUBLIC | PROTECTED | SECRET (default PUBLIC)

Response (201): board with id, name, description, privacy, url.

View documentation
New endpoint: POST /v1/sms/registrations/{id}/opt-in-proof uploads an SMS opt-in form screenshot/PDF and returns a public URL you can include in an appeal.

Use it to host proof of consent when submitting POST /v1/sms/registrations/{id}/appeal (add the returned URL to your messageFlow).

Request: multipart/form-data with file (PNG/JPG/WebP/GIF/PDF, max 4MB)
Response: { "url": "..." }
Errors: 404 registration not found, 422 unsupported type/too large

View documentation
SMS carrier registration now accepts optional policy URLs on 10DLC campaigns via POST /v1/sms/registrations.

You can include privacy/terms links in the campaign object to help carrier reviewers validate compliance.

New campaign properties:
privacyPolicyLink
termsAndConditionsLink

Also, embeddedLink and embeddedPhone now document auto-derivation from your sample messages when omitted.

View documentation
POST /v1/sms/messages now supports scheduling via sendAt.

Set sendAt (ISO 8601 date-time with offset) to queue an SMS/MMS for a future time; it must be in the future. The message is queued and the message.delivered webhook fires when it actually sends.

New field: sendAt

View documentation
New endpoint POST /v1/sms/opt-in-proof uploads SMS opt-in proof (screenshot/PDF) and returns a public URL you can include in a campaign’s messageFlow for carrier review.

Send multipart/form-data with file (PNG/JPG/WebP/GIF/PDF, max 4MB).

Response: { "url": "..." }

Errors: 422 unsupported type/too large, 401 unauthorized. Alias: /v1/sms/registrations/{id}/opt-in-proof.

View documentation