Zernio Developers
1.38K subscribers
1 photo
1 video
890 links
Changelog updates from zernio.com, the marketing infrastructure for products and agents

zernio.com/changelog
Download Telegram
Ad rule schedules now support set times and optional start/end windows, and everyMinutes is no longer guaranteed to be present.

When reading rules, handle schedule.everyMinutes being missing or null (it’s null when a rule runs at set times).

You can now schedule rules with:
• everyMinutes: 15, 30, 60, 180, 360, 720, 1440, or null
• times: weekly run times (days + HH:MM)
• startsAt / endsAt: optional date-time bounds

Sending schedule replaces the rule’s whole timing; if omitted on create, a new rule defaults to every 60 minutes.

View documentation
Ad rules actions have changed (breaking): budget adjustment actions are no longer represented as type=adjust_budget in rule payloads/requests.

If your integration reads or creates budget-change actions, update your parsing/validation to match the new action variants, and handle the new type=edit_name action.

Also updated:
• GET /v1/ads/rules/activity filter type now includes edit_name (alongside pause, activate, adjust_budget, duplicate)
• Activity entries and webhook payloads may include rename details: previousName, newName

curl -G "https://api.zernio.com/v1/ads/rules/activity" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode "type=edit_name" \
--data-urlencode "limit=50"


View documentation
Ad Rules: update your integrations for action schema changes and new alert lifecycle support.

Breaking changes
• Ad rule actions now include adjust_bid and may no longer match older oneOf shapes (some fields/enums were removed/narrowed). If you validate/deserialize actions, update your models to handle the new variants.
• AdRule now includes lifecycle (nullable) and POST/PATCH ad rule bodies accept lifecycle.

New capabilities
• New endpoint to list a rule’s alert episodes: GET /v1/ads/rules/{ruleId}/alerts with state = pending | open | resolved, plus limit and cursor pagination.
• New webhook events: automation.alert.opened, automation.alert.escalated, automation.alert.resolved (payload: WebhookPayloadAutomationAlert). You can also request these samples via POST /v1/webhooks/test.

curl -sS -H "Authorization: Bearer $ZERNIO_API_KEY" \
"https://api.zernio.com/v1/ads/rules/$RULE_ID/alerts?state=open&limit=50"


View documentation
Ad rules filters have changed: the days_live filter is no longer supported, and filter typing/enums were updated.

If you create or parse rules, update your integration to stop sending/expecting {field: "days_live", op: ">="|"<", value: number} in filters.

You can now filter by budget placement using filters[].field = budget_level with op = equals and value = campaign or adset.

Rule actions now also support maxChangesPerObject (in addition to maxChangesPerDay) for pause, activate, duplicate, adjust_bid, edit_name, and adjust_budget.

View documentation
Shipped today: 14 API updates

• Ad Rules: Build richer automations with budget metrics, rank ops, filters, quiet hours, undo, and activate options via POST /v1/ads/rules and POST /v1/ads/rules/activity/{activityId}/undo.
• Webhooks: Subscribe to automation and ads lifecycle events and generate sample payloads via POST /v1/webhooks/settings and POST /v1/webhooks/test.
• Meta Ads: Handle Meta write limits on ad creation by retrying on 429 MetaAdAccountWriteLimited from POST /v1/ads/messaging, POST /v1/ads/call, POST /v1/ads/ctwa.
• TikTok Analytics: Fetch follower demographics proportions by age/gender/country/city via GET /v1/analytics/tiktok/demographics with breakdown.
• Billing: Link to the right top-up document using invoiceUrl, receiptUrl, and hasInvoice from GET /v1/balance/top-ups/{topupId}/receipt.
• Ad rule templates now include a required goal field in GET /v1/ads/rules/templates responses.
Call billing no longer includes billing.recordingSeconds in call records.

If your integration reads recordingSeconds from call history or call detail responses, remove that dependency and rely on available cost fields like billing.recordingCostUSD, billing.billableCostUSD, and billing.totalCostUSD.

Impacted responses:
• GET /v1/calls, GET /v1/calls/{id}
• GET /v1/voice/calls
• GET /v1/whatsapp/calls

Ads rules now also support optional campaign grouping via groups (returned on rules and in rule previews).

curl -sS -H "Authorization: Bearer $TOKEN" \
"$BASE_URL/v1/calls?accountId=$ACCOUNT_ID&limit=1"


View documentation
Shipped today: 7 API updates

• Ads: Build ad rules with month windows and calendar metrics using window:this_month|last_month and metric:day_of_month|working_day_of_month.
• Ads: Reuse existing videos in placement-customized creatives via placementAssets.defaultVideoId and placementAssets.rules[].videoId on POST /v1/ads/create.
• Publishing: Create platform-less drafts scoped to a profile using profileId with POST /v1/posts (isDraft=true), and read it via posts[].profileId.
• Accounts: Enable Meta ads sync on a Facebook posting account by setting metaAdsSyncEnabled on PUT /v1/accounts/{accountId}.
• Commerce: Route commerce order events by profile using profiles in WebhookPayloadCommerceOrder webhooks.
• You can now create single-use connect links with POST /v1/platform-invites.
Top-ups no longer have a card fee, and GET /v1/balance/top-ups/card-fee has been removed (update any integrations that call it).

When creating a top-up via POST /v1/balance/top-ups, the card is now charged exactly amountCents and your balance is credited the same amount (feeCents is always 0, feeIsExact is always true for compatibility). The minimum amountCents is now 500.

You can now fetch a paid top-up statement (no VAT) via GET /v1/balance/top-ups/{topupId}/statement. Response includes format = pdf or page, plus pdfUrl/pageUrl (short-lived links).

curl -sS -H "Authorization: Bearer $TOKEN" \
"https://api.zernio.com/v1/balance/top-ups/$TOPUP_ID/statement"


View documentation
Ad rules now support new action types adjust_target and reallocate_budget, and activity/run/webhook payloads include additional fields for these actions.

If you validate or deserialize ad rule actions, update your models to handle action type values: pause, activate, adjust_budget, adjust_bid, adjust_target, reallocate_budget, duplicate, edit_name.

For adjust_target actions, target is now required when creating rules. Webhook payload ad_rule.triggered, rule runs, and rule activity entries may now include targetMetric, previousTarget, newTarget.

The activity filter GET /v1/ads/rules/activity also accepts type=adjust_target and type=reallocate_budget.

curl -G "$ZERNIO_API/v1/ads/rules/activity" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode "type=adjust_target" \
--data-urlencode "limit=50"


View documentation
Automations are now available via the API: you can create and manage ad rules, event automations, and scheduled post automations, plus preview/backtest ad rules and track runs/actions.

Core endpoints include GET/POST /v1/automations, PATCH/DELETE /v1/automations/{automationId}, POST /v1/automations/{automationId}/activate, POST /v1/automations/{automationId}/pause, POST /v1/automations/preview, POST /v1/automations/backtest, and run history via GET /v1/automations/{automationId}/checks and GET /v1/automations/actions.

Automation kind is ad_rule, event, or scheduled. Use GET /v1/automations/catalog to discover supported triggers/steps/metrics and the JSON schema used for validation.

Templates are supported for reuse and sharing: /v1/automations/templates (team), /v1/automations/templates/shared/{shareToken}, and /v1/automations/templates/zernio/{templateId}, with install endpoints that support multi-target installs (207 for partial success).

curl -sS -X GET "https://api.zernio.com/v1/automations?limit=50" \
-H "Authorization: Bearer $ZERNIO_API_KEY"


View documentation
Shipped today: 14 API updates

• Billing: Preview and charge top-ups with tax + fetch invoices via POST /v1/balance/top-ups/preview and GET /v1/balance/top-ups/{topupId}/invoice.
• Billing: Auto-top up when balance drops below a threshold by updating PATCH /v1/balance/auto-recharge (enabled, belowCents, toCents, limits).
• Errors: Handle billing-required failures as non-retryable by checking 402 BalanceRequired on send/call/verify endpoints like POST /v1/verify/verifications.
• Ads: Harden ads workflows: Meta create retries (retryOnServerError/recoveredWrites), library 429, status=not_deleted, IG actor, defaults, intro cards.
• Attribution: Attribute results to campaigns via events[].campaign on POST /v1/events and count HubSpot closed-won deals via PATCH /v1/accounts/{id}/hubspot-settings.
Media validation responses changed: POST /v1/tools/validate/media no longer returns type=unknown. Update any enum parsing/validation to handle only type = image | video | document.

The endpoint now verifies media by inspecting the actual bytes (not just headers) and returns stable failure reasons via code: MEDIA_UNDECODABLE | MEDIA_URL_UNREACHABLE | MEDIA_URL_NOT_ALLOWED. It also adds format, width, height, and inspection (decoded | header).

Post validation now reports media decode failures with errors[].code = MEDIA_UNDECODABLE in POST /v1/tools/validate/post.

curl -sS -X POST "$ZERNIO_API/v1/tools/validate/media" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/image.jpg"}'


View documentation
POST /v1/transfers has been removed and now always returns 410. If you were paying creators from your balance, switch to paying via payout batches.

Treasury campaign payouts are now card-based: use POST /v1/creator-campaigns/{campaignId}/payout-batches (one card payment per batch). GET /v1/balance no longer represents creator payout funds; payoutLockedCents / payoutLocks are deprecated and always empty/0.

New: preview what a payout batch would charge with POST /v1/creator-campaigns/{campaignId}/payout-batches/preview. Response includes amountCents, feeCents, taxCents, totalCents, taxLabel, reverseCharge.

Also: payout batch responses now include batch.releasesAt, and items add status value refunded plus refundedCents.

curl -X POST "$BASE_URL/v1/creator-campaigns/$CAMPAIGN_ID/payout-batches/preview" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"excludeParticipantIds":["ptc_..."]}'


View documentation
Shipped since Friday: 14 API updates

• Events API: Avoid duplicate conversion/event ingestion and track delivery outcomes via Idempotency-Key, mode=async, and GET /v1/events/{eventId}.
• Balance & Billing: Build balance-aware billing UX using GET /v1/balance fields (recentCreditRecharges, balanceBilling, spendableCents) plus lineItems[].paidFrom.
• Webhooks: Trigger automations on billing and ad set changes using webhook events balance.low|empty|charged and ad_set.created|updated in events.
• Ads Accounts: Refresh ad account catalogs live and broaden IG identity discovery via GET /v1/ads/accounts?live=true and GET /v1/ads/instagram-accounts source.
• Publishing & Payments: Handle billing blocks and payment throttling via X publish errors (POST/PUT /v1/posts, /retry) plus 429 payment_attempts_limited on top-ups/payouts.
Action required: account.permissions_changed webhook payloads may now return account.oauthAppId as null (when the account uses Zernio’s OAuth app). Update any strict schema validation / deserialization to accept null.

Pinterest now supports account-level analytics via GET /v1/analytics/pinterest/account-insights.

Use accountId (Pinterest SocialAccount), optional metrics (default impressions,engagements,follower_count), fromDate/toDate (max 89 days), and metricType (total_value | time_series). since/until remain as deprecated aliases.

curl -G "https://api.zernio.com/v1/analytics/pinterest/account-insights" \
-H "Authorization: Bearer $TOKEN" \
--data-urlencode "accountId=acc_123" \
--data-urlencode "metricType=time_series"


View documentation
Many content fields can now be null when a team (or profile) uses zero content retention (mode=none). Update your integration to handle contentNotRetained: true and nullable fields (e.g. post content/title, inbox lastMessage/message, mentions/reviews text, lead answers, call recording URLs).

You can now read and change the team-wide mode via the new Content Retention endpoints:
• GET /v1/content-retention
• PUT /v1/content-retention with mode: standard | none

Also: profiles can set contentRetention on create/update, and webhooks add events mention.received, call.transcript_segment, call.recording_ready (important when content isn’t stored).

curl -X PUT "$ZERNIO_API/v1/content-retention" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode":"none"}'


View documentation
Action required: GET /v1/email/send-as response fields changed.

Removed: displayName, isPrimary, verified, and meta.completeList/meta.signatures. Replace with:
• data[].name
• data[].type = primary | alias | shared
• data[].verificationStatus = accepted | pending | unverified
• data[].source = provider | declared
• meta.list = provider | partial and meta.providerSignatures

Also, data[].signature is now an object (or null) describing what appendSignature would add (Zernio default first, else Gmail).

New capability: you can now manage Zernio-stored signatures (works across providers) and explicitly declare Outlook “send as” addresses (e.g. shared mailboxes) so they become valid from values.

curl -X POST "$ZERNI0/v1/email/signatures" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name":"Sales","html":"<b>Ada</b>","defaultFor":["sales@acme.com"]}'


View documentation
Email mailbox connection is now supported via a new Connect flow and IMAP APIs.

Use GET /v1/connect/email to generate a 1-hour hosted connect link that routes users to Google/Microsoft OAuth or IMAP (with provider app-password steps).
Key query params: profileId (required), redirect_url, email, name, reconnectAccountId.

If you’re building your own UI, use POST /v1/email/imap/discover to decide the route (imap | google_oauth | microsoft_oauth | unsupported) and get suggested IMAP/SMTP settings + auth guidance.

To connect without the hosted page, use POST /v1/email/imap/accounts with profileId + email (and optionally password, imap, smtp, identities). Supports dryRun validation and in-place reconnect via reconnectAccountId. Failures return 422 with stage codes (e.g. use_oauth, app_password_required, imap_auth_failed).

Webhooks: account.connected now may include account.reconnected and account.replacedAccountId. account.disconnected now may include account.reasonCode (auth_failed, imap_disabled, tls_error, unreachable, replaced) and account.reconnectUrl (hosted reconnect link).

curl -sS -H "Authorization: Bearer $TOKEN" \
"https://api.zernio.com/v1/connect/email?profileId=$PROFILE_ID&redirect_url=https://app.example.com/callback"


View documentation
Calendar free-busy responses can now return busy: null per account, and free-busy requests now support per-account options.

When an account/calendar/person can’t be read, you’ll now get busy: null plus an error, while other accounts still return results.

In POST /v1/calendar/free-busy:
• Send either accountIds (now optional) or accounts
• accounts[].calendarIds lets you choose calendars (or primary)
• accounts[].emails lets you read coworkers via that account
• Response adds calendars, people, and error details

Also added: list recurring event instances via GET /v1/calendar/events/{eventId}/instances (requires accountId, from, to; supports timezone, cursor, limit). Instances include type (single/series/occurrence/exception) and originalStart.

curl -X POST https://api.zernio.com/v1/calendar/free-busy \
-H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' \
-d '{"from":"2026-11-10T00:00:00Z","to":"2026-11-11T00:00:00Z","accounts":[{"accountId":"acc_123","calendarIds":["primary"]}]}'


View documentation
Shipped today: 22 API updates

• Email: Build full email workflows: schedule/hold drafts, track opens/clicks/replies, manage drafts/forward/labels/send-as/IMAP, and handle webhooks via v1/email/*.
• Creator Campaigns: Run creator campaigns end-to-end: draft review, samples, join approval, Spark codes, and launch posts as ads via public/creator-campaigns/* endpoints.
• Instagram: Backfill Story history and insights: GET /v1/accounts/{accountId}/instagram/stories?includeExpired=true plus insights source=archived and metrics.
• Ads & Conversions: Unify lead + conversion pipelines: GET /v1/ads/leads?platform=google, lead.received includes lead.platform, and conversions use PATCH|DELETE /v1/events/{eventId} + forwarding rules.
• Core APIs: Handle truncation, ownership, metadata, mentions, and calendar notifications: warning+pagination.nextCursor, posts[].isOwner, update-metadata, mentionAuthor, notifyParticipants.
Organization-wide mailbox connections are now supported for Google Workspace and Microsoft 365.

Admins can grant access once (domain-wide delegation / admin consent), then you can add mailboxes without each user signing in.

Start an org connection with:
• POST /v1/connect/google/org using profileId, domain, scopes (email/calendar/files/contacts)
• POST /v1/connect/microsoft/org using profileId, scopes, optional redirectUrl

Manage connections via /v1/org-connections (list/get/update/delete), activate with POST /v1/org-connections/{orgConnectionId}/verify, list users with GET /v1/org-connections/{orgConnectionId}/users, and add mailboxes with POST /v1/org-connections/{orgConnectionId}/mailboxes.

curl -X POST "$ZERNI0_API/v1/connect/microsoft/org" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"profileId":"prof_123","scopes":["email","calendar"],"redirectUrl":"https://app.example.com/callback"}'


View documentation