Zernio | Developer News
689 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
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
New LinkedIn-only Ads helpers are available:

Suggested bid & budget bounds via POST /v1/ads/targeting/bid-pricing
Returns suggested bid + allowed bid limits and daily budget bounds for a targeting spec (use before POST /v1/ads/create).
Key request fields: accountId, adAccountId, spec, optional campaignType (TEXT_AD/SPONSORED_UPDATES/SPONSORED_INMAILS), bidType (CPM/CPC/CPV), matchType (EXACT/AUDIENCE_EXPANDED), dailyBudget.
Response: available and pricing (may be null).

Impressions/clicks/spend forecast via POST /v1/ads/targeting/supply-forecast
Forecasts metrics for a targeting spec over a future time range.
Key request fields: accountId, adAccountId, spec, timeRangeStart, timeRangeEnd, plus either dailyBudget or totalBudget. For manual bidding, set competingBid with bidType (CPM/CPC/CPV) and amount; for auto-bidding, set optimizationTarget.
Response: available and forecast series with metricType and granularity (DAILY/SEVEN_DAY/THIRTY_DAY/CUSTOM).

For non-LinkedIn accounts, both endpoints return available: false (not an error).

View documentation
LinkedIn now supports Thought Leader ads on POST /v1/ads/create via platformSpecificData.thoughtLeader.

This lets you create a LinkedIn ad that references an existing post (share/ugcPost) as the creative, while still using the normal /v1/ads/create flow for targeting/bidding/schedule.

Set:
platformSpecificData.thoughtLeader.postUrn (pattern: urn:li:share:\d+ or urn:li:ugcPost:\d+)

Notes:
• Mutually exclusive with other LinkedIn creative sources in platformSpecificData (e.g. carousel, document, conversation, etc.)
• When using thoughtLeader, you don’t need headline/body/imageUrl/organizationId for the creative (the referenced post provides them).

View documentation
New endpoint: DELETE /v1/sms/registrations/{id} to deactivate an SMS brand/campaign registration.

This terminates the carrier registry campaign so recurring monthly campaign fees stop; numbers under the registration can no longer send texts (receiving is unaffected). Deactivation is irreversible and the operation is idempotent.

Key parameter: id (path, string)

Response: 200 returns status = deactivated (enum: deactivated)

View documentation
GET /v1/sms/registrations now supports includeDeactivated (boolean).

Deactivated (terminated) registrations are hidden by default; pass includeDeactivated=true to include them in the results.

New query param:
includeDeactivated - true to include deactivated registrations (default: hidden)

View documentation
conversions in ads metrics now includes non-Meta platforms.

You can now rely on conversions for more platforms when charting or aggregating performance (instead of always getting 0 outside Meta).

Applies to:
GET /v1/ads/timeline (rows[].conversions)
AdMetrics.conversions

New platform behavior:
• Meta: events matching the campaign optimization goal
• Google: tracked conversions
• X / LinkedIn: reported website/lead conversions (added 2026-07)

View documentation
1
SMS carrier registration status now includes additional lifecycle states in registration APIs.

You may now see pre-submission review and deactivation states when listing, fetching, or reusing registrations, which can affect clients that assume only the previous 3 statuses.

Updated status enum:
pending, approved, rejected, requested, changes_requested, deactivated

Applies to:
GET /v1/sms/registrations
GET /v1/sms/registrations/{id}
POST /v1/phone-numbers/{id}/sms/reuse-registration

Also added to POST /v1/sms/registrations request body:
resubmitRequestId (resubmit an existing registration returned for changes)
wizardValues (optional raw wizard answers; can be omitted by API integrators)

View documentation
1
GET /v1/connect/{platform}/ads now supports force to trigger a fresh OAuth flow even when an ads account is already connected.

This lets you proactively refresh stored tokens (the endpoint normally returns alreadyConnected: true based on account active state, not token liveness).

Use force=true to always receive authUrl; completing OAuth refreshes the stored token on the existing posting + ads accounts in place.

New param: force (true/false, default false)

View documentation
YouTube demographics analytics now supports per-video audience breakdowns via videoId on GET /v1/analytics/youtube/demographics.

Pass videoId to fetch demographics for a single video (instead of the whole channel). Note: YouTube may return empty breakdowns for low-traffic videos due to signed-in view thresholds.

Use:
videoId - YouTube video ID (scoped to the connected channel; otherwise 404)
startDate - defaults to the video publish date (lifetime) when videoId is provided

Response adds (video mode only): videoId, title, publishedAt.

Also: Meta city targeting docs were updated to reflect that cities[].radius has a minimum (~17 km / 10 mi). Smaller values can produce a 0-size audience and fail at launch; use customLocations for tighter radius targeting.

View documentation
GET /v1/accounts/{accountId}/gmb-locations now supports a limit query parameter.

You can raise the maximum number of Google Business Profile locations returned (default was effectively 100) up to 500 to enumerate accounts with more than 100 locations.

Use limit:
limit (integer, default 100, min 1, max 500)

Invalid values now return 400 (e.g. limit out of range).

View documentation
Meta campaign updates now support a lifetime spend cap via platformSpecificData.spendCap on PUT /v1/ads/campaigns/{campaignId}.

This lets you set or remove a campaign-level spend cap without recreating the campaign.

Use:
platformSpecificData.spendCap = number (sets cap)
platformSpecificData.spendCap = null (removes cap; Meta rejects 0)

Meta ad set updates now accept post-launch delivery settings via platformSpecificData on PUT /v1/ads/ad-sets/{adSetId}.

Set any of:
platformSpecificData.optimizationGoal
platformSpecificData.billingEvent
platformSpecificData.startDate, platformSpecificData.endDate
platformSpecificData.promotedObject (e.g. pixelId, customEventType, pageId, applicationId, objectStoreUrl, customConversionId, productCatalogId, productSetId)

Also added: billingEvent (Meta only) on POST /v1/ads/create to explicitly set the ad set’s billing event (defaults to IMPRESSIONS).

View documentation