# Zernio API Documentation > Social media management API for scheduling, publishing, and analytics ## Documentation Pages - [Changelog](https://docs.zernio.com/changelog.mdx) - Stay up to date with the latest API changes and improvements - [CLI](https://docs.zernio.com/cli.mdx) - Schedule posts, manage inbox, broadcasts, sequences, and automations across 14 platforms from the terminal. Built for developers and AI agents. - [Quickstart](https://docs.zernio.com/.mdx) - Get started with the Zernio API - authenticate, connect accounts, and schedule your first post in minutes. - [MCP](https://docs.zernio.com/mcp.mdx) - Connect AI assistants to the Zernio API using the Model Context Protocol - [Pricing](https://docs.zernio.com/pricing.mdx) - Pay-per-account pricing — first 2 accounts free, then graduated rates with everything included - [Refer & earn](https://docs.zernio.com/refer-and-earn.mdx) - Earn 20% recurring commission for 12 months when you refer new customers to Zernio. - [SDKs](https://docs.zernio.com/sdks.mdx) - Official Zernio API client libraries for Node.js, Python, Go, Ruby, Java, PHP, .NET, and Rust. Post to 14+ social platforms. - [Webhooks](https://docs.zernio.com/webhooks.mdx) - How Zernio webhook deliveries work and the payload sent for each event. - [Bluesky](https://docs.zernio.com/platforms/bluesky.mdx) - Schedule and automate Bluesky posts with Zernio API - Text posts, images, videos, threads, and App Password authentication - [Discord](https://docs.zernio.com/platforms/discord.mdx) - Send messages, DMs, embeds, polls, forum posts, threads, schedule events, and manage roles in Discord servers with Zernio API - No bot hosting, no gateway, no intents approval - [Facebook](https://docs.zernio.com/platforms/facebook.mdx) - Schedule and automate Facebook Page posts with Zernio API - Feed posts, Stories, multi-image, multi-link carousels, GIFs, and first comments - [Google Ads](https://docs.zernio.com/platforms/google-ads.mdx) - Create Search and Display campaigns via Zernio API - No MCC or Standard Access application required - [Overview](https://docs.zernio.com/platforms.mdx) - Complete guide to all social media platforms supported by Zernio API - [Instagram](https://docs.zernio.com/platforms/instagram.mdx) - Schedule and automate Instagram posts with Zernio API - Feed, Stories, Reels, Carousels, collaborators, and user tags - [LinkedIn Ads](https://docs.zernio.com/platforms/linkedin-ads.mdx) - Create and boost LinkedIn campaigns via Zernio API - No Marketing Developer Platform application required - [LinkedIn](https://docs.zernio.com/platforms/linkedin.mdx) - Schedule and automate LinkedIn posts with Zernio API - Personal profiles, company pages, images, videos, documents, and multi-organization posting - [Pinterest Ads](https://docs.zernio.com/platforms/pinterest-ads.mdx) - Create Promoted Pin campaigns via Zernio API - No Pinterest developer approval required - [Pinterest](https://docs.zernio.com/platforms/pinterest.mdx) - Schedule and automate Pinterest Pins with Zernio API - Image pins, video pins, boards, destination links, and cover images - [Reddit](https://docs.zernio.com/platforms/reddit.mdx) - Schedule and automate Reddit posts with Zernio API - Text posts, link posts, image posts, subreddit targeting, flair selection, and gallery posts - [Snapchat](https://docs.zernio.com/platforms/snapchat.mdx) - Schedule and automate Snapchat posts with Zernio API - Stories, Saved Stories, Spotlight content, and Public Profile management - [Telegram](https://docs.zernio.com/platforms/telegram.mdx) - Schedule and automate Telegram channel and group posts with Zernio API - Text, images, videos, media albums, silent messages, and bot management - [Threads](https://docs.zernio.com/platforms/threads.mdx) - Schedule and automate Threads posts with Zernio API - Text, images, videos, carousels, and thread sequences - [TikTok Ads](https://docs.zernio.com/platforms/tiktok-ads.mdx) - Create campaigns and Spark Ads via Zernio API - No TikTok Business Center developer onboarding required - [TikTok](https://docs.zernio.com/platforms/tiktok.mdx) - Schedule and automate TikTok posts with Zernio API - Videos, photo carousels, privacy settings, and AI disclosure - [X Ads](https://docs.zernio.com/platforms/x-ads.mdx) - Create campaigns and promote tweets via Zernio API - OAuth 1.0a and approval handled for you - [YouTube](https://docs.zernio.com/platforms/youtube.mdx) - Schedule and automate YouTube video uploads with Zernio API - Videos, Shorts, thumbnails, visibility, and COPPA settings - [Open Source](https://docs.zernio.com/resources/open-source.mdx) - Open-source projects and OpenAPI specifications built with and for the Zernio API - [Create group](https://docs.zernio.com/account-groups/create-account-group.mdx) - Creates a new account group with a name and a list of social account IDs. Accounts can belong to different profiles; the caller must have access to every account's profile. Group names must be unique per user. - [Delete group](https://docs.zernio.com/account-groups/delete-account-group.mdx) - Permanently deletes an account group. The accounts themselves are not affected. - [List groups](https://docs.zernio.com/account-groups/list-account-groups.mdx) - Returns all account groups visible to the authenticated user. Groups can contain accounts from multiple profiles. For API keys scoped to specific profiles, only groups whose accounts all live in allowed profiles are returned. - [Update group](https://docs.zernio.com/account-groups/update-account-group.mdx) - Updates the name or account list of an existing group. You can rename the group, change its accounts, or both. - [Delete IG ice breakers](https://docs.zernio.com/account-settings/delete-instagram-ice-breakers.mdx) - Removes the ice breaker questions from an Instagram account's Messenger experience. - [Delete FB persistent menu](https://docs.zernio.com/account-settings/delete-messenger-menu.mdx) - Removes the persistent menu from Facebook Messenger conversations for this account. - [Delete TG bot commands](https://docs.zernio.com/account-settings/delete-telegram-commands.mdx) - Clears all bot commands configured for a Telegram bot account. - [Get IG ice breakers](https://docs.zernio.com/account-settings/get-instagram-ice-breakers.mdx) - Get the ice breaker configuration for an Instagram account. - [Get FB persistent menu](https://docs.zernio.com/account-settings/get-messenger-menu.mdx) - Get the persistent menu configuration for a Facebook Messenger account. - [Get TG bot commands](https://docs.zernio.com/account-settings/get-telegram-commands.mdx) - Get the bot commands configuration for a Telegram account. - [Set IG ice breakers](https://docs.zernio.com/account-settings/set-instagram-ice-breakers.mdx) - Set ice breakers for an Instagram account. Max 4 ice breakers, question max 80 chars. - [Set FB persistent menu](https://docs.zernio.com/account-settings/set-messenger-menu.mdx) - Set the persistent menu for a Facebook Messenger account. Max 3 top-level items, max 5 nested items. - [Set TG bot commands](https://docs.zernio.com/account-settings/set-telegram-commands.mdx) - Set bot commands for a Telegram account. - [Disconnect account](https://docs.zernio.com/accounts/delete-account.mdx) - Disconnects and removes a connected social account. - [Check account health](https://docs.zernio.com/accounts/get-account-health.mdx) - Returns detailed health info for a specific account including token status, permissions, and recommendations. - [Check accounts health](https://docs.zernio.com/accounts/get-all-accounts-health.mdx) - Returns health status of all connected accounts including token validity, permissions, and issues needing attention. - [Get follower stats](https://docs.zernio.com/accounts/get-follower-stats.mdx) - Returns follower count history and growth metrics for connected social accounts. Requires analytics add-on subscription. Follower counts are refreshed once per day. - [Get TikTok creator info](https://docs.zernio.com/accounts/get-tiktok-creator-info.mdx) - Returns TikTok creator details, available privacy levels, posting limits, and commercial content options for a specific TikTok account. Only works with TikTok accounts. - [List accounts](https://docs.zernio.com/accounts/list-accounts.mdx) - Returns connected social accounts. Only includes accounts within the plan limit by default. Follower data requires analytics add-on. Supports optional server-side pagination via page/limit params. When omitted, returns all accounts (backward-compatible). - [Move account to another profile](https://docs.zernio.com/accounts/move-account-to-profile.mdx) - Moves a connected social account to a different profile owned by the same user. The target profile must belong to the same user as the account. For API keys restricted to specific profiles, BOTH the source account's current profile AND the target profile must be in the key's allowed set. Calls with a target profile outside the key's scope return 403. - [Update account](https://docs.zernio.com/accounts/update-account.mdx) - Updates a connected social account's display name or username override. For X/Twitter accounts on usage-based billing, also accepts an `xCapabilities` object to toggle background API operations that incur X API pass-through costs. Both fields are opt-in (default `false`) — when off, no analytics syncs or DM polling are performed for that account, and no API call is metered for those operations. Publishing and deleting posts are always available regardless of these toggles. Setting `xCapabilities` on a non-X account returns 400. - [Create key](https://docs.zernio.com/api-keys/create-api-key.mdx) - Creates a new API key with an optional expiry. The full key value is only returned once in the response. - [Delete key](https://docs.zernio.com/api-keys/delete-api-key.mdx) - Permanently revokes and deletes an API key. - [List keys](https://docs.zernio.com/api-keys/list-api-keys.mdx) - Returns all API keys for the authenticated user. Keys are returned with a preview only, not the full key value. - [Associate campaigns](https://docs.zernio.com/ads/add-conversion-associations.mdx) - Associate one or more campaigns with this conversion rule. Returns a per-campaign success/failure result so callers can retry only the rows that failed (e.g. wrong campaign type for the rule's objective). - [Share with an ad account](https://docs.zernio.com/ads/add-tracking-tag-shared-account.mdx) - Shares the pixel with another ad account so campaigns/audiences in that account can use it. Requires that you administer both the pixel's owning Business Manager and the target ad account; a pixel on a personal (non-BM) ad account can't be shared (Meta will reject the call). Meta only (platform `metaads`); other platforms return 405. - [Add users to audience](https://docs.zernio.com/ads/add-users-to-ad-audience.mdx) - Upload user data to a customer_list audience. Data is SHA256-hashed server-side before sending to the platform. Email is used on every platform; phone is used on Meta only (other platforms ignore it). On TikTok and Pinterest, the first upload also provisions the audience (deferred create). LinkedIn uploads are full-replace. Max 10,000 users per request. - [Adjust uploaded conversions](https://docs.zernio.com/ads/adjust-conversions.mdx) - Adjust conversions that were previously uploaded via `POST /v1/ads/conversions` — retract them, restate their value, or enhance them with first-party data. Requires the Ads add-on. **Google Ads only.** Google handles adjustments through the classic Google Ads API (`ConversionAdjustmentUploadService`); the Data Manager `ingestEvents` path used for sending conversions is ingest-only. Meta and LinkedIn have no equivalent, so this endpoint returns `405` for those platforms. Adjustment types: - `RETRACTION` — remove the conversion entirely (refund, chargeback, cancelled order, churn). - `RESTATEMENT` — change the conversion's value (upgrade / downgrade / partial refund). Send the corrected **total** value in `restatementValue` (not a delta). - `ENHANCEMENT` — attach first-party identifiers (hashed email / phone) to an existing conversion (enhanced conversions applied after the fact). Identifying the original conversion (per adjustment): - `orderId` — the transaction ID you sent as `eventId` on the original conversion. Recommended, and **required** for `ENHANCEMENT`. - or `gclid` + `conversionTime` — the click ID and the original conversion's time (unix seconds). Not available for `ENHANCEMENT`. `destinationId` is the conversion action resource name, e.g. `customers/1234567890/conversionActions/987654321` (same value you send to `POST /v1/ads/conversions`). PII in `user` is hashed with SHA-256 server-side (Gmail-specific normalization included). Send plaintext. Times are unix seconds; we convert to Google's required `yyyy-MM-dd HH:mm:ss+00:00` format. Up to 2000 adjustments per request; partial failure is supported (inspect `adjustmentsFailed` / `failures[]`). - [Archive a lead form](https://docs.zernio.com/ads/archive-lead-form.mdx) - Meta has no hard delete for forms; this archives the form (status=ARCHIVED). - [Boost post as ad](https://docs.zernio.com/ads/boost-post.mdx) - Creates a paid ad campaign from an existing published post. Creates the full platform campaign hierarchy (campaign, ad set, ad). - [Pause or resume many campaigns](https://docs.zernio.com/ads/bulk-update-ad-campaign-status.mdx) - Process up to 50 campaigns in one call. Each campaign is updated concurrently and the response contains a per-campaign result so a single bad row does not fail the whole batch. - [Create custom audience](https://docs.zernio.com/ads/create-ad-audience.mdx) - Create a custom audience. `customer_list` is supported on Meta, Google, X, LinkedIn, TikTok, and Pinterest; `website` and `lookalike` are Meta-only. `saved_targeting` stores a reusable TargetingSpec (no member upload, no adAccountId) that you reference later via `savedTargetingId` on `POST /v1/ads/create`. Upload-backed audiences are created empty, add members via `POST /v1/ads/audiences/{audienceId}/users`. On TikTok and Pinterest the audience is provisioned lazily on the first member upload (until then its status is `pending`). Create is not idempotent, never auto-retry. - [Create a conversion destination](https://docs.zernio.com/ads/create-conversion-destination.mdx) - Create a new conversion destination on the platform. Supported for LinkedIn (conversion rule) and Google Ads (conversion action). Meta manages destinations in its own UI and returns 405. **LinkedIn:** creation is NOT idempotent. A retry creates a second destination. Deduplicate before retrying. **Google Ads:** calling with a name that already exists reuses the existing conversion action transparently (the response is identical to a fresh create). Calling with the same name but a different category returns a typed `IDEMPOTENCY_CONFLICT` (409) rather than silently returning the mismatched action. **LinkedIn:** the rule is created with `conversionMethod=CONVERSIONS_API` and (by default) auto-associated with all of the ad account's campaigns via `autoAssociationType=ALL_CAMPAIGNS`. Pass `autoAssociationType: NONE` to opt out and manage associations explicitly via the associations endpoints below. 365-day attribution windows are only valid for `SUBMIT_APPLICATION`, `PURCHASE`, `ADD_TO_CART`, `QUALIFIED_LEAD`, and `LEAD` rule types; the API rejects other combinations locally. **Google Ads:** the conversion action is created with `type=UPLOAD_CLICKS` (required for API-uploaded offline conversions, immutable after creation). The `type` field carries the Google `ConversionActionCategory` enum value, e.g. `PURCHASE`, `SUBSCRIBE_PAID`, `SIGNUP`, `IMPORTED_LEAD`, `BOOK_APPOINTMENT`. Unified standard event names (e.g. `Purchase`, `Subscribe`, `CompleteRegistration`, `Lead`, `Schedule`) are resolved to their Google category equivalents automatically. The action defaults to secondary (non-primary) to avoid immediately steering Smart Bidding; pass `primaryForGoal: true` to opt in. - [Create Click-to-WhatsApp ad](https://docs.zernio.com/ads/create-ctwa-ad.mdx) - Creates one or more Click-to-WhatsApp (CTWA) ads on Meta under a single campaign and ad set. When tapped, each ad opens a WhatsApp conversation with the business attached to the supplied Facebook Page. The full hierarchy (campaign, ad set, creative(s), ad(s)) is created and activated in one call. The CTA is locked to WHATSAPP_MESSAGE and the destination is hard-coded to api.whatsapp.com/send; Meta resolves the actual WhatsApp number from the Page-to-WA pairing configured in Page settings or Business Manager. Supports two mutually-exclusive shapes: - **Single-creative**: supply top-level `headline`, `body`, and one of `imageUrl` / `video`. Creates 1 campaign + 1 ad set + 1 ad. - **Multi-creative**: supply a `creatives[]` array with N entries (each carrying its own headline, body, and image/video). Creates 1 campaign + 1 ad set + N ads sharing budget and targeting so Meta A/Bs the creatives inside a single auction instead of fragmenting budget across N parallel campaigns. Recommended when launching multiple creative variants for the same campaign. Prerequisites enforced by Meta (surfaced as platform_error on failure): the Facebook Page must be paired with a verified WhatsApp Business number, the WhatsApp Business Account must be business-verified, and the Meta access token must carry ads_management. - [Create a lead form](https://docs.zernio.com/ads/create-lead-form.mdx) - Creates a Lead Gen form on the connected Facebook Page (POST /{page-id}/leadgen_forms). NOT idempotent — a retry creates a second form. Prefilled question types (EMAIL, PHONE, FULL_NAME, …) must omit label/key; CUSTOM questions require both. Requires the Ads add-on. - [Create standalone ad](https://docs.zernio.com/ads/create-standalone-ad.mdx) - Creates a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X/Twitter, and LinkedIn. Supports three mutually-exclusive request shapes selected by the body, a legacy single-creative shape (all platforms, default), a Meta-only multi-creative shape via the creatives array (one ad set with N ads sharing budget and targeting), and a Meta-only attach shape via adSetId (adds one new ad to an existing ad set). Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content "dark post" authored by a Company Page (see `organizationId`); supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h. - [Create a test lead](https://docs.zernio.com/ads/create-test-lead.mdx) - Submits a test lead against the form (POST /{form-id}/test_leads) to exercise retrieval without waiting for real ad impressions. Meta allows one test lead per form at a time. - [Create a tracking tag](https://docs.zernio.com/ads/create-tracking-tag.mdx) - Creates a Meta Pixel on the given ad account (`POST /act_{id}/adspixels` — `name` is the only input). Returns the created tag including its install `code`. The pixel is owned by the Business Manager that owns the ad account; a pixel created on a personal (non-BM) ad account ends up with `ownerBusinessId: null` and can't be shared with other ad accounts. Creating a pixel does NOT install it — install the returned `code` snippet on the site, or send events server-side via `POST /v1/ads/conversions`. The check `installed` is derived from `lastFiredTime`. NOT idempotent: each call creates a new pixel. Do not retry blindly on timeout. Meta only (platform `metaads`); other platforms return 405. - [Delete custom audience](https://docs.zernio.com/ads/delete-ad-audience.mdx) - Deletes the audience from both Meta and the local database. - [Delete a campaign](https://docs.zernio.com/ads/delete-ad-campaign.mdx) - Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked `status: cancelled`. Meta-only for now. Other platforms return 501 Not Implemented — fall back to DELETE /v1/ads/{adId} per ad in the meantime. - [Cancel an ad](https://docs.zernio.com/ads/delete-ad.mdx) - Cancels the ad on the platform and marks it as cancelled in the database. The ad is preserved for history. - [Delete a conversion destination](https://docs.zernio.com/ads/delete-conversion-destination.mdx) - LinkedIn-only today. LinkedIn does not expose hard-delete on conversion rules — what their UI calls "delete" is the same `enabled: false` flip we apply here. The rule remains fetchable via GET with `status: 'inactive'`; the unified discovery endpoint hides it by default. `adAccountId` may be passed as a query parameter (recommended) or as a JSON body field for clients that can send DELETE bodies. - [Duplicate a campaign](https://docs.zernio.com/ads/duplicate-ad-campaign.mdx) - Duplicates a campaign, including its ad sets, ads, creatives, and targeting by default (`deepCopy: true`). The copy is created paused so callers can review before launching. Per-platform implementation: - **Meta** uses the native `POST /{campaign-id}/copies` endpoint. - **TikTok** has no native copy primitive; Zernio walks the source graph (`/v2/campaign/get/`, `/v2/adgroup/get/`, `/v2/ad/get/`) and recreates each entity via the corresponding `/create/` endpoints, carrying over budget / targeting / bid_type / bid_price / deep_bid_type / creative fields. Spark Ad linkage (`tiktok_item_id`) is preserved. The new hierarchy is asynchronous to materialize in our DB — we trigger sync discovery automatically. Set `syncAfter: false` to skip and poll `/v1/ads/tree` on your own cadence. Other platforms return 501 Not Implemented. - [Estimate audience reach](https://docs.zernio.com/ads/estimate-ad-reach.mdx) - Returns a normalized pre-flight audience-size estimate for a targeting spec, before any campaign is created. Backed by each platform's native reach API (Meta `delivery_estimate`, LinkedIn `audienceCounts`, X `audience_summary`, Pinterest `audience_sizing`). Platforms without a usable pre-flight reach API (Google Search/Display, TikTok) return `available: false` with no bounds, so clients can hide or grey out the estimate rather than treat the absence as an error. - [Get ad analytics](https://docs.zernio.com/ads/get-ad-analytics.mdx) - Returns detailed performance analytics for an ad. Includes summary metrics, a daily timeline over the requested date range, and optional demographic breakdowns (Meta and TikTok only). If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max. - [Get audience details](https://docs.zernio.com/ads/get-ad-audience.mdx) - Returns the local audience record and fresh data from Meta (if available). - [List comments on an ad](https://docs.zernio.com/ads/get-ad-comments.mdx) - Returns comments on an ad's underlying creative post. Useful for moderating or analyzing engagement on dark posts (ad creatives that never went live organically), which the regular GET /v1/inbox/comments/{postId} endpoint cannot serve because dark posts are not in Zernio's post database. An ad that runs on both Facebook feed and Instagram feed has two separate underlying posts with separate comment threads (the creative's effective_object_story_id and effective_instagram_media_id). Use the `placement` query param to pick one; with no param the Instagram side is returned when it exists, otherwise Facebook. The identifiers are read from the ad record (persisted during sync) with a Marketing-API fallback for ads that predate the field. For Instagram-placed comments, the Instagram account that runs the ad must be connected to Zernio — those comments are read through that account's token. If no connected Instagram account on the profile can read the ad's media, the call returns ads_connection_required (the Facebook side, if any, is still readable via ?placement=facebook). Meta-only. Other ad platforms (TikTok, LinkedIn, Pinterest, Google, X) do not expose a public per-ad comments API and return feature_not_available. Requires the Ads add-on. Response shape matches GET /v1/inbox/comments/{postId}. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: Zernio internal `_id` (24-char hex), Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`), or the creative's `effective_object_story_id` / `effective_instagram_media_id`. Caller doesn't need a translation step. - [Get ad tracking tags](https://docs.zernio.com/ads/get-ad-tracking-tags.mdx) - Unified read of the platform's native click-URL tracking params. - Meta (facebook/instagram): the creative's `url_tags` (and template_url_spec). - Google (googleads): the campaign's `trackingUrlTemplate` + `finalUrlSuffix`. Subject to the Google Ads API access-tier daily quota; bulk audits need Standard access. - LinkedIn (linkedinads): the campaign's Dynamic UTM `dynamicValueParameters` + `customValueParameters`. Returns 405 for platforms without a click-URL tracking surface (TikTok, X, Pinterest). - [Get campaign tree](https://docs.zernio.com/ads/get-ad-tree.mdx) - Returns a nested Campaign > Ad Set > Ad hierarchy with rolled-up metrics at each level. Uses a two-stage aggregation: ads are grouped into ad sets, then ad sets into campaigns. Metrics are computed over an optional date range, then rolled up from ad level to ad set and campaign levels. Pagination is at the campaign level. Ads without a campaign or ad set ID are grouped into synthetic "Ungrouped" buckets. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max. Pass `timeIncrement=1` to also get a daily breakdown: each node gains a `daily[]` array of per-day metrics (same fields as the aggregated `metrics`) in the same call. Use `dailyLevel` (`campaign` default, or `adset` / `ad`) to choose which levels carry the series. This replaces calling the tree once per day for per-campaign daily trends. - [Get ad details](https://docs.zernio.com/ads/get-ad.mdx) - Returns an ad with its creative, targeting, status, and performance metrics. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. - [Get daily account metrics](https://docs.zernio.com/ads/get-ads-timeline.mdx) - Returns daily aggregate metrics across all ads in a SocialAccount as a single time series — one row per calendar day in the requested range. Use this for dashboards that draw a daily-spend or daily-conversions chart, instead of calling `/v1/ads/tree` once per day. `accountId` is required. The lookup is sibling-expanded so passing the `metaads` ID also includes ads under the linked `facebook` / `instagram` posting account (and vice-versa) — same convention as `/v1/ads/tree` and `/v1/ads`. Date range defaults to the last 90 days. Capped at 730 days. Ranges older than the 90-day cache window trigger an on-demand backfill from the platform before returning. - [Get campaign analytics](https://docs.zernio.com/ads/get-campaign-analytics.mdx) - Returns performance analytics for a whole campaign in one call: summary metrics, a daily timeline over the requested date range (summed across the campaign's ads), and optional demographic breakdowns. Breakdowns are fetched live from Meta at the campaign level (one call per dimension, no per-ad fan-out), so an agency dashboard gets campaign-level age/gender/etc. without summing thousands of per-ad reads. `campaignId` is the platform campaign id; pass `platform` when a campaign id could be ambiguous across platforms. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max. - [Get a conversion destination](https://docs.zernio.com/ads/get-conversion-destination.mdx) - LinkedIn-only today. Returns the full destination record for one conversion rule. The `adAccountId` query parameter is required because LinkedIn rules are scoped to a sponsored ad account. - [Get attribution metrics](https://docs.zernio.com/ads/get-conversion-metrics.mdx) - LinkedIn-only today. Returns conversion-attribution metrics (`externalWebsiteConversions`, `externalWebsitePostClickConversions`, `externalWebsitePostViewConversions`, `conversionValueInLocalCurrency`, `qualifiedLeads`, `costInLocalCurrency`) bucketed by date. Date-range constraints (passed through from LinkedIn): - `granularity=DAILY` is retained for ~6 months only - `granularity=ALL` with a range > 6 months auto-rounds to month boundaries - `granularity=MONTHLY`/`YEARLY` retains 24 months Throttle: LinkedIn caps adAnalytics at 45M metric values per 5-minute window across the calling token. Single-rule queries are well within that limit; surfaces as 429 if hit. - [Get Event Match Quality](https://docs.zernio.com/ads/get-conversions-quality.mdx) - Reads Meta Event Match Quality (EMQ) and pixel↔CAPI event coverage for a pixel/dataset, live from Meta's Dataset Quality API. Web events only (a Meta limitation). Meta-only; other platforms return 405. Requires the Ads add-on. - [Get a lead form](https://docs.zernio.com/ads/get-lead-form.mdx) - [Get aggregated event stats](https://docs.zernio.com/ads/get-tracking-tag-stats.mdx) - Returns aggregated event counts for the pixel (`GET /{pixel_id}/stats`). Rows are passed through from Meta as-is — their shape depends on the `aggregation` requested. Meta only (platform `metaads`); other platforms return 405. - [Get a tracking tag](https://docs.zernio.com/ads/get-tracking-tag.mdx) - Returns the full tag record including the base-code `code` snippet, `lastFiredTime`, `ownerBusinessId`, `isUnavailable`, etc. Meta only (platform `metaads`); other platforms return 405. - [List ad accounts](https://docs.zernio.com/ads/list-ad-accounts.mdx) - Returns the platform ad accounts available for the given social account (e.g. Meta ad accounts, TikTok advertiser IDs, Google Ads customer IDs). For TikTok agencies: enumerates every advertiser under every Business Center the token can read (paginated server-side), then chunks the lookup against TikTok's `/advertiser/info/` endpoint (which has a per-call cap of ≤100 IDs). Solo advertisers without a BC fall back to the OAuth-time `advertiser_ids` list. Cached for 1h on the SocialAccount; lazy-refreshed on first call after expiry. - [List custom audiences](https://docs.zernio.com/ads/list-ad-audiences.mdx) - Returns custom audiences for the given ad account. Supports Meta, Google, TikTok, Pinterest, LinkedIn, and X (Twitter). - [List campaigns](https://docs.zernio.com/ads/list-ad-campaigns.mdx) - Returns campaigns as virtual aggregations over ad documents grouped by platform campaign ID. Metrics (spend, impressions, clicks, etc.) are summed across all ads in each campaign. Campaign status is derived from child ad statuses (active > pending_review > paused > error > completed > cancelled > rejected). - [List a catalog's product sets](https://docs.zernio.com/ads/list-ad-catalog-product-sets.mdx) - Lists a Meta product catalog's product sets — the unit a catalog ad promotes. Pass the chosen set as `promotedObject.productSetId` on POST /v1/ads/create with `goal: catalog_sales`. - [List Meta product catalogs](https://docs.zernio.com/ads/list-ad-catalogs.mdx) - Lists the Meta product catalogs reachable from an ad account (owned + agency-shared catalogs of the ad account's business), for Advantage+ catalog ads (`goal: catalog_sales` on POST /v1/ads/create — e.g. vehicle inventory catalogs). Read-only; uses scopes customers already granted (no reconnect needed). Catalog contents (items, feeds) are managed in Meta Commerce Manager, not through this API. - [List TikTok Business Centers](https://docs.zernio.com/ads/list-ads-business-centers.mdx) - Returns the TikTok Business Centers (BCs) the connected `tiktokads` account can read. Each BC reports its advertiser count so callers can build agency-style pickers without re-walking `/v1/ads/accounts` per BC. TikTok-only. Solo advertisers (non-agency tokens) return an empty array. - [List ads](https://docs.zernio.com/ads/list-ads.mdx) - Returns a paginated list of ads with metrics computed over an optional date range. Use source=all to include externally-synced ads from platform ad managers. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max. To find the Zernio ad behind a comment you see in Meta Business Manager, filter by platformAdId (the Meta ad ID), effectiveObjectStoryId (Facebook), or effectiveInstagramMediaId (Instagram) — those are the post/media the ad's engagement lives on, and are also returned on each ad's `creative` object. Then call GET /v1/ads/{adId}/comments with the returned ad id. - [List associated campaigns](https://docs.zernio.com/ads/list-conversion-associations.mdx) - LinkedIn-only today. Returns the campaigns currently associated with this conversion rule. Note that auto-association on rule creation runs once at create time; campaigns created after the rule still need explicit association. - [List conversion destinations](https://docs.zernio.com/ads/list-conversion-destinations.mdx) - Returns the list of pixels (Meta), conversion actions (Google), or conversion rules (LinkedIn) accessible to the connected ads account. Use the returned `id` as `destinationId` when posting to `POST /v1/ads/conversions`. For Google and LinkedIn, each destination's `type` reflects the conversion type (PURCHASE, LEAD, SIGN_UP, etc.) — the event type is locked to the destination. For Meta, `type` is absent: pixels accept any event name per request. For LinkedIn, destinations are returned across every sponsored ad account the connected token can access; the `adAccountId` field on each destination identifies the parent ad account and is required for subsequent CRUD calls (update, delete, associations, metrics). - [List leads for a single form](https://docs.zernio.com/ads/list-form-leads.mdx) - Returns leads for one form. Serves persisted leads (ingested via the leadgen webhook) when available, falling back to a live Graph read. - [List lead forms](https://docs.zernio.com/ads/list-lead-forms.mdx) - Lists the Lead Gen forms owned by the connected Facebook Page. Requires the Ads add-on. - [List submitted leads](https://docs.zernio.com/ads/list-leads.mdx) - Returns persisted Meta Lead Gen leads for your team, newest-first, with keyset pagination on `cursor`. Leads are ingested in real time from the `leadgen` webhook. Requires the Ads add-on. - [List accounts it is shared with](https://docs.zernio.com/ads/list-tracking-tag-shared-accounts.mdx) - Meta only (platform `metaads`); other platforms return 405. - [List tracking tags](https://docs.zernio.com/ads/list-tracking-tags.mdx) - Returns the tracking tags (Meta Pixels) the connected ads account can see. Pass `?adAccountId=act_...` to scope the list to a single ad account; omit it to list every pixel reachable by the token (the name is then suffixed with the ad account it was discovered on, for disambiguation). The list view omits `code` — call `getTrackingTag` for the install snippet and full detail. Meta only today (platform `metaads`); other platforms return 405. The `accountId` must be the Meta *ads* SocialAccount created by the Ads add-on connect flow, not a Facebook/Instagram posting account. Get your `act_...` ids from `GET /v1/ads/accounts`. - [List conversion events](https://docs.zernio.com/ads/list-whatsapp-conversions.mdx) - Returns the most recent conversion events sent through `POST /v1/whatsapp/conversions` for the given WhatsApp account. Sourced from delivery logs (Axiom `late` dataset), so the visible window is bounded by log retention (about 30 days). Useful for rendering a "recent activity" panel on the conversions setup tab without standing up a parallel persistence layer. Per-event payload mirrors the structured log we write on every successful send: `eventName`, `conversationId`, `eventsReceived`, `eventsFailed`, `traceId`, `durationMs`, and the wall-clock `timestamp`. - [Remove associated campaigns](https://docs.zernio.com/ads/remove-conversion-associations.mdx) - Remove one or more campaign associations from this conversion rule. Pass `adAccountId` and `campaignIds` as query parameters (`campaignIds` is comma-separated). The route also accepts a JSON body with the same fields for clients that prefer DELETE-with-body, but the documented surface is query-only because some SDK code generators (e.g. Python) collapse query + body parameters with the same name into a single kwarg. - [Stop sharing with an account](https://docs.zernio.com/ads/remove-tracking-tag-shared-account.mdx) - `adAccountId` may be passed as a query parameter (recommended) or as a JSON body field for clients that can send DELETE bodies. Meta only (platform `metaads`); other platforms return 405. - [Search targeting interests](https://docs.zernio.com/ads/search-ad-interests.mdx) - Deprecated alias for `GET /v1/ads/targeting/search?dimension=interest`. Kept for backward compatibility, it returns the legacy `{ interests: [...] }` shape rather than the normalized `{ results: [...] }`. New integrations should use `GET /v1/ads/targeting/search` with `dimension=interest`. - [Search targeting options](https://docs.zernio.com/ads/search-ad-targeting.mdx) - Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched, `geo` (locations, further scoped by `geoType`), `interest`, `behavior`, or `income`. Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. For geo queries, `q` should contain only the locality name (e.g. `"Amsterdam"`, not `"Amsterdam, NL"`). Use `countryCode` to disambiguate. - [Send conversion events](https://docs.zernio.com/ads/send-conversions.mdx) - Relay one or more conversion events to the target ad platform's native Conversions API. Platform is inferred from the provided `accountId`. Requires the Ads add-on. Supported platforms: - Meta (`metaads`) via Graph API - Google Ads (`googleads`) via Data Manager API `ingestEvents` - LinkedIn (`linkedinads`) via `/rest/conversionEvents` - TikTok (`tiktokads`) via the Offline Events API `/offline/batch/` — OFFLINE conversions only `destinationId` semantics differ per platform: - Meta: pixel (dataset) ID, e.g. `123456789012345` - Google: conversion action resource name, e.g. `customers/1234567890/conversionActions/987654321` - LinkedIn: conversion rule ID or URN, e.g. `104012` or `urn:lla:llaPartnerConversion:104012` - TikTok: Offline Event Set ID, e.g. `7057103914977558530` TikTok notes: this path sends OFFLINE conversions (in-store / CRM / call-center), not web-pixel events. Each event must carry an email or phone (TikTok requires at least one). The connected TikTok ads account must have granted the Offline Events permission; older grants must reconnect. Callers can list valid destinations via `GET /v1/accounts/{accountId}/conversion-destinations`. All PII (email, phone, names, external IDs) is hashed with SHA-256 server-side per each platform's normalization spec, including Google's Gmail-specific dot/plus-suffix stripping. Send plaintext. LinkedIn `externalIds` are passed through as plaintext per LinkedIn's spec; only emails and phones are hashed. For LinkedIn, the connected account must have been authorized after the Conversions API rollout (i.e. the OAuth grant must include `rw_conversions`). Older accounts must reconnect. Batching is handled automatically. Meta caps at 1000 events per request and rejects the entire batch if any event is malformed. Google caps at 2000. LinkedIn caps at 5000 and is also all-or-nothing per chunk. Dedup: pass a stable `eventId` on every event. Meta and LinkedIn use it to dedupe against browser-side pixel/Insight Tag events; Google maps it to `transactionId`. Per-platform `eventName` semantics: - Meta: free-form. Standard names (Purchase, Lead, ...) match Meta's built-in events; custom strings are accepted. - Google: ignored. The conversion action's category determines the event type. Send the standard name closest to your action for documentation, but the platform will not branch on it. - LinkedIn: ignored. The conversion rule's `type` (LEAD, PURCHASE, etc.) is locked to the destination at rule-creation time. Send the standard name for documentation; LinkedIn does not branch on it. - [Send WhatsApp conversion event](https://docs.zernio.com/ads/send-whatsapp-conversion.mdx) - Forward a WhatsApp Business Messaging conversion event (`LeadSubmitted`, `Purchase`, `AddToCart`, `InitiateCheckout`, `ViewContent`) to Meta's Conversions API with `action_source = business_messaging` and `messaging_channel = whatsapp`. The endpoint looks up the originating CTWA click ID (`ctwa_clid`) captured on the first inbound message of the conversation and replays it on every event so Meta can attribute the conversion back to the Click-to-WhatsApp ad that drove the chat. Configuration prerequisite on the WhatsApp account metadata: - `metaCapiDatasetId`: the Meta dataset ID linked to the WABA. Provision one with `POST /v1/whatsapp/dataset`. The WABA ID (already set automatically at connect time) is forwarded as `user_data.whatsapp_business_account_id`, which is the per-channel attribution identifier Meta requires for WhatsApp events. No Facebook Page ID is needed (that field is the Messenger-branch identifier). Identify the conversation by either `conversationId` (preferred) or `phoneE164` (digits only, no `+`). At least one is required. If the conversation has no captured `ctwa_clid`, the request returns 422 because there is nothing to attribute. Token and dataset coupling: the WhatsApp account's accessToken must have access to the configured `metaCapiDatasetId`. By default a WABA's system-user token is scoped to the WABA's own Business Manager and cannot post to a pixel owned by a different Business; Meta returns code 100 in that case. Either share the dataset with the WhatsApp app's Business in BM, or use a dataset already in the same Business as the WABA. - [Pause or resume a campaign](https://docs.zernio.com/ads/update-ad-campaign-status.mdx) - Updates the status of all ads in a campaign. Makes one platform API call (not per-ad) since status cascades through the campaign hierarchy. Ads in terminal statuses (rejected, completed, cancelled) are automatically skipped. - [Update a campaign](https://docs.zernio.com/ads/update-ad-campaign.mdx) - Campaign-level edits. At least one of `budget` or `bidStrategy` is required. - `budget` updates the CBO (Campaign Budget Optimization) budget. For ABO campaigns (where the budget lives on the ad set), use PUT /v1/ads/ad-sets/{adSetId} instead — this endpoint will return 409 with code BUDGET_LEVEL_MISMATCH. - `bidStrategy` sets the campaign-level default bid strategy. Per Meta's spec, `bid_amount` and `bid_constraints` do NOT exist at the campaign level — pass them via PUT /v1/ads/ad-sets/{adSetId}. Meta-only for now. Other platforms return 501 Not Implemented. - [Pause or resume a single ad set](https://docs.zernio.com/ads/update-ad-set-status.mdx) - Ad-set-scoped pause/resume (doesn't touch sibling ad sets). Thin wrapper over PUT /v1/ads/ad-sets/{adSetId} for callers that only want the status toggle and prefer a symmetric URL to /v1/ads/campaigns/{campaignId}/status. - [Update an ad set](https://docs.zernio.com/ads/update-ad-set.mdx) - Ad-set-level writes. Use this for ABO budget updates, ad-set-scoped pause/resume, and bid-strategy edits. At least one of `budget`, `status`, or `bidStrategy` is required. Bid strategy compatibility (per Meta's spec): - `LOWEST_COST_WITHOUT_CAP`: no `bidAmount`, no `roasAverageFloor`. - `LOWEST_COST_WITH_BID_CAP` / `COST_CAP`: `bidAmount` REQUIRED (whole currency units). - `LOWEST_COST_WITH_MIN_ROAS`: `roasAverageFloor` REQUIRED (decimal multiplier, e.g. 2.0 = 2.0x ROAS). When updating `budget` on an ABO campaign: if the parent campaign is CBO, the response is 409 with code BUDGET_LEVEL_MISMATCH — route to PUT /v1/ads/campaigns/{campaignId} instead. - [Set ad tracking tags](https://docs.zernio.com/ads/update-ad-tracking-tags.mdx) - Unified update. Send only the fields for the ad's platform: - Meta: `urlTags` (array of {key,value}). Meta creatives are immutable, so this rebuilds the creative and repoints the ad. By DEFAULT we PRESERVE the existing creative verbatim (re-post its object_story_spec + the new url_tags, reusing the image), so you send `urlTags` ALONE — no need to read back headline/body/CTA. `creative` (headline, body, callToAction, linkUrl, imageUrl) is OPTIONAL and only needed to rebuild explicitly, or for SHARE / page-post / dark / asset_feed creatives whose object_story_spec Meta strips (those return 422 asking for `creative`). - Google: `trackingUrlTemplate` and/or `finalUrlSuffix` (full template strings; account quota applies). - LinkedIn: `dynamicValueParameters` and/or `customValueParameters` (campaign-level Dynamic UTM). - [Update ad](https://docs.zernio.com/ads/update-ad.mdx) - Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style — `headline` is ignored, `body` becomes `ad_text`). - **Pinterest / X / LinkedIn / Google**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. - [Update a conversion destination](https://docs.zernio.com/ads/update-conversion-destination.mdx) - Partial-update a conversion rule. LinkedIn-only today. Whitelisted fields: `name`, `enabled`, attribution windows, `valueType`, `value`, `attributionType`. The rule's `type` and parent ad account are intentionally not exposed for update — recreate the rule if those need to change. - [Update a tracking tag](https://docs.zernio.com/ads/update-tracking-tag.mdx) - Partial-update a pixel. Whitelisted fields: `name` (rename), `enableAutomaticMatching`, `automaticMatchingFields`, `firstPartyCookieStatus`, `dataUseSetting`. At least one is required. Returns the re-fetched canonical tag. Meta only (platform `metaads`); other platforms return 405. There is no DELETE — Meta has no API to delete a pixel. To stop using one, unshare it from your ad accounts (`DELETE .../tracking-tags/{tagId}/shared-accounts`) or disable it in Events Manager. - [Get post analytics](https://docs.zernio.com/analytics/get-analytics.mdx) - Returns analytics for posts. With postId, returns a single post. Without it, returns a paginated list with overview stats. Accepts both Zernio Post IDs and External Post IDs (auto-resolved). fromDate defaults to 90 days ago if omitted, max range 366 days. Single post lookups may return 202 (sync pending) or 424 (all platforms failed). For follower stats, use /v1/accounts/follower-stats. LinkedIn personal accounts: Analytics are only available for posts published through Zernio. LinkedIn's API only returns metrics for posts authored by the authenticated user. Organization/company page analytics work for all posts. - [Get best times to post](https://docs.zernio.com/analytics/get-best-time-to-post.mdx) - Returns the best times to post based on historical engagement data. Groups all published posts by day of week and hour (UTC), calculating average engagement per slot. Use this to auto-schedule posts at optimal times. Requires the Analytics add-on. - [Get content performance decay](https://docs.zernio.com/analytics/get-content-decay.mdx) - Returns how engagement accumulates over time after a post is published. Each bucket shows what percentage of the post's total engagement had been reached by that time window. Useful for understanding content lifespan (e.g. "posts reach 78% of total engagement within 24 hours"). Requires the Analytics add-on. - [Get daily aggregated metrics](https://docs.zernio.com/analytics/get-daily-metrics.mdx) - Returns daily aggregated analytics metrics and a per-platform breakdown. Each day includes post count, platform distribution, and summed metrics (impressions, reach, likes, comments, shares, saves, clicks, views). Defaults to the last 180 days. Requires the Analytics add-on. - [Get Facebook Page insights](https://docs.zernio.com/analytics/get-facebook-page-insights.mdx) - Returns page-level Facebook insights (media views, views, post engagements, video metrics, follower counts). Response shape matches /v1/analytics/instagram/account-insights so the same client handling works across platforms. Metric names track the current (post-November 2025) Meta Graph API. The legacy page_impressions / page_fans / page_fan_adds / page_fan_removes metrics were deprecated by Meta on November 15, 2025 and are NOT accepted by this endpoint. Use the replacements below. Because Meta did not provide direct adds/removes replacements, Zernio synthesizes followers_gained / followers_lost from the daily follower snapshotter. Max 89 days, defaults to last 30 days. Requires the Analytics add-on. - [Get follower stats](https://docs.zernio.com/analytics/get-follower-stats.mdx) - Returns follower count history and growth metrics for connected social accounts. Requires analytics add-on subscription. Follower counts are refreshed once per day. - [Get GBP performance metrics](https://docs.zernio.com/analytics/get-google-business-performance.mdx) - Returns daily performance metrics for a Google Business Profile location. Metrics include impressions (Maps/Search, desktop/mobile), website clicks, call clicks, direction requests, conversations, bookings, and food orders. Data may be delayed 2-3 days. Max 18 months of historical data. Requires the Analytics add-on. - [Get GBP search keywords](https://docs.zernio.com/analytics/get-google-business-search-keywords.mdx) - Returns search keywords that triggered impressions for a Google Business Profile location. Data is aggregated monthly. Keywords below a minimum impression threshold set by Google are excluded. Max 18 months of historical data. Requires the Analytics add-on. - [Get Instagram insights](https://docs.zernio.com/analytics/get-instagram-account-insights.mdx) - Returns account-level Instagram insights such as reach, views, accounts engaged, and total interactions. These metrics reflect the entire account's performance across all content surfaces (feed, stories, explore, profile), and are fundamentally different from post-level metrics. Data may be delayed up to 48 hours. Max 90 days, defaults to last 30 days. Requires the Analytics add-on. - [Get Instagram demographics](https://docs.zernio.com/analytics/get-instagram-demographics.mdx) - Returns audience demographic insights for an Instagram account, broken down by age, city, country, and/or gender. Requires at least 100 followers. Returns top 45 entries per dimension. Data may be delayed up to 48 hours. Requires the Analytics add-on. - [Get Instagram follower history](https://docs.zernio.com/analytics/get-instagram-follower-history.mdx) - Returns a daily running Instagram follower count time series, served from Zernio's cross-platform daily snapshotter. Exists because Meta removed follower_count from the /insights endpoint in Graph API v22+ and never exposed a historical daily series via any public API. Response envelope matches /v1/analytics/instagram/account-insights so the same client handling works. Max 89 days, defaults to last 30 days. Requires the Analytics add-on. - [Get LinkedIn aggregate stats](https://docs.zernio.com/analytics/get-linkedin-aggregate-analytics.mdx) - Returns aggregate analytics across all posts for a LinkedIn personal account. Only includes posts published through Zernio (LinkedIn API limitation). Org accounts should use /v1/analytics instead. Requires r_member_postAnalytics scope. Saves (POST_SAVE) and sends (POST_SEND) are available for personal accounts; organization pages always return 0 for these two metrics because LinkedIn does not expose them on the organization analytics endpoint. - [Get LinkedIn org analytics](https://docs.zernio.com/analytics/get-linkedin-org-aggregate-analytics.mdx) - Returns aggregate analytics for a LinkedIn organization page. Parallel to /v1/accounts/{id}/linkedin-aggregate-analytics (which handles personal accounts only). Backed by LinkedIn's organizationalEntityShareStatistics, organizationalEntityFollowerStatistics, and organizationPageStatistics endpoints. Response shape matches /v1/analytics/instagram/account-insights. Max 89 days, defaults to last 30 days. Requires the Analytics add-on. Scope requirements: r_organization_social, r_organization_followers, and r_organization_admin must all be present on the account. Accounts connected before these scopes were included in the OAuth flow will return 412 with a reauth hint. Enforced by this endpoint: - Page-view metrics accept only metricType=total_value (LinkedIn omits per-day segmentation even when the API is called with DAY granularity, so a time-series response would be meaningless). - Date range capped at 89 days. LinkedIn-side platform limits (not re-enforced here, but worth knowing for larger ranges in a future release): - Follower stats: rolling 12-month window, end must be no later than 2 days ago. - Share stats: rolling 12-month window. - [Get LinkedIn post stats](https://docs.zernio.com/analytics/get-linkedin-post-analytics.mdx) - Returns analytics for a specific LinkedIn post by URN. Works for both personal and organization accounts. Saves and sends are only populated for personal accounts (LinkedIn does not expose these metrics on the organization analytics endpoint). - [Get LinkedIn post reactions](https://docs.zernio.com/analytics/get-linkedin-post-reactions.mdx) - Returns individual reactions for a specific LinkedIn post, including reactor profiles (name, headline/job title, profile picture, profile URL, reaction type). Only works for organization/company page accounts. LinkedIn restricts reaction data for personal profiles (r_member_social_feed is a closed permission). - [Get post analytics timeline](https://docs.zernio.com/analytics/get-post-timeline.mdx) - Returns a daily timeline of analytics metrics for a specific post, showing how impressions, likes, and other metrics evolved day-by-day since publishing. Each row represents one day of data per platform. For multi-platform Zernio posts, returns separate rows for each platform. Requires the Analytics add-on. - [Get frequency vs engagement](https://docs.zernio.com/analytics/get-posting-frequency.mdx) - Returns the correlation between posting frequency (posts per week) and engagement rate, broken down by platform. Helps find the optimal posting cadence for each platform. Each row represents a specific (platform, posts_per_week) combination with the average engagement rate observed across all weeks matching that frequency. Requires the Analytics add-on. - [Get TikTok account-level insights](https://docs.zernio.com/analytics/get-tiktok-account-insights.mdx) - Returns account-level TikTok insights from /v2/user/info/ (live) plus historical time series joined from Zernio's daily snapshotter (AccountStats). Response shape matches /v1/analytics/instagram/account-insights. Max 89 days, defaults to last 30 days. Requires the Analytics add-on and the user.info.stats scope on the account (412 if missing). Scope intentionally narrow. TikTok's public API exposes only the four counter metrics below. The deep metrics that live in TikTok Studio are NOT available on any public TikTok API, even for Business accounts: - profile_views - account-level impressions / reach - follower inflow / outflow breakdown - video watch time, average watch time, full-watched rate - impression_sources (FYP / Following / Hashtag / Search / Personal profile) TikTok's Research API doesn't expose those fields either, and is restricted to non-commercial academic use per TikTok's eligibility policy. There is no public API workaround. Post-level metrics (views, likes, comments, shares per video) are available via /v1/analytics?postId=... from TikTok's /v2/video/query/. - [Get YouTube channel insights](https://docs.zernio.com/analytics/get-youtube-channel-insights.mdx) - Returns channel-scoped aggregate metrics from YouTube Analytics API v2. Saves you from looping /v1/analytics/youtube/daily-views over every video when you only need channel totals. Response shape matches /v1/analytics/instagram/account-insights so the same client handling works. Requires yt-analytics.readonly scope (412 with reauthorizeUrl if missing). Data has a 2-3 day delay (endDate is clamped accordingly). Max 89 days, defaults to last 30 days. Requires the Analytics add-on. NOT exposed: impressions (Studio thumbnail impressions) and impressionsClickThroughRate. YouTube Analytics API v2 does not expose these for any principal type, not channel owners, not Partner Program channels, not content owners with CMS access. The only way to get them is Studio CSV export. This is a Google-side limitation. - [Get YouTube daily views](https://docs.zernio.com/analytics/get-youtube-daily-views.mdx) - Returns daily view counts for a YouTube video including views, watch time, and subscriber changes. Requires yt-analytics.readonly scope (re-authorization may be needed). Data has a 2-3 day delay. Max 90 days, defaults to last 30 days. - [Get YouTube demographics](https://docs.zernio.com/analytics/get-youtube-demographics.mdx) - Returns audience demographic insights for a YouTube channel, broken down by age, gender, and/or country. Age and gender values are viewer percentages (0-100). Country values are view counts. Data is based on signed-in viewers only, with a 2-3 day delay. Requires the Analytics add-on. - [Get YouTube video retention curve](https://docs.zernio.com/analytics/get-youtube-video-retention.mdx) - Returns the audience retention curve for a single YouTube video, plus the video's duration for rendering the curve on a time axis. The curve has up to 100 points (elapsedVideoTimeRatio 0.01-1.0) aggregated over the whole date range; YouTube does not support per-day retention breakdowns. audienceWatchRatio is the absolute share of viewers watching at that point in the video and can exceed 1 (rewinds and looping, common on Shorts). relativeRetentionPerformance compares against videos of similar length (0 = worst, 0.5 = median, 1 = best). YouTube returns an empty curve for videos with very few views or before analytics processing completes (2-3 day delay). Requires yt-analytics.readonly scope (re-authorization may be needed). - [Sync an external post](https://docs.zernio.com/analytics/sync-external-posts.mdx) - Fetch an account's latest external posts (published directly on the platform, not through Zernio) on demand, so a just-published post is retrievable within seconds instead of waiting for the background sync (which refreshes each account at most every ~90 minutes). Primary use case: verifying a submitted post. When a user publishes on the platform and immediately pastes the post URL into your app, call this with `accountId` plus `url` (or `postId`) to confirm the post exists and return its metadata. Behavior: - We check our stored copy first and return immediately if the post is already known (no platform call). - Otherwise we fetch the account's latest posts live from the platform, then match and return the submitted post. - Requests are debounced per account (~15s): if the account was just synced, the live fetch is skipped. `accountId` is required — a post URL or id alone cannot be resolved to an account, and the account must be connected to Zernio (we use its token to read the platform). Supported for every platform with a listing API (Instagram, Facebook, TikTok, YouTube, X, Threads, Pinterest, Reddit, Bluesky, Google Business, and LinkedIn organization accounts; LinkedIn personal accounts are not supported). `url` accepts any format the platform uses (e.g. `instagram.com/p/…`, `instagram.com/reel/…`, `youtu.be/…`, `youtube.com/shorts/…`, `tiktok.com/@user/video/…`, and `vm.tiktok.com` short links). Pass `postId` (the platform media/video id) as an alternative locator. Note: post-level analytics (reach, impressions) still carry the platform's own delay (e.g. ~24h on Instagram). This endpoint confirms the post exists and returns its metadata plus basic engagement (likes, comments), not delayed insights. - [Add recipients to a broadcast](https://docs.zernio.com/broadcasts/add-broadcast-recipients.mdx) - Add recipients by contact IDs, raw phone numbers, or from the broadcast's segment filters. - [Cancel broadcast](https://docs.zernio.com/broadcasts/cancel-broadcast.mdx) - Cancel a scheduled or in-progress broadcast. Already-sent messages are not affected. - [Create broadcast draft](https://docs.zernio.com/broadcasts/create-broadcast.mdx) - Create a broadcast in draft status. Add recipients and then send or schedule it. - [Delete broadcast](https://docs.zernio.com/broadcasts/delete-broadcast.mdx) - Permanently delete a broadcast. Only drafts can be deleted. - [Get broadcast details](https://docs.zernio.com/broadcasts/get-broadcast.mdx) - Returns a broadcast with its full configuration and delivery stats. - [List broadcast recipients](https://docs.zernio.com/broadcasts/list-broadcast-recipients.mdx) - Returns recipients for a broadcast with individual delivery status. Filter by status. - [List broadcasts](https://docs.zernio.com/broadcasts/list-broadcasts.mdx) - Returns broadcasts with delivery stats. Filter by status, platform, or profile. - [Schedule broadcast for later](https://docs.zernio.com/broadcasts/schedule-broadcast.mdx) - Schedule a draft broadcast to be sent at a future date and time. - [Send broadcast now](https://docs.zernio.com/broadcasts/send-broadcast.mdx) - Immediately start sending a draft broadcast to its recipients. - [Update broadcast](https://docs.zernio.com/broadcasts/update-broadcast.mdx) - Update a broadcast's name, message, template, or segment filters. Only draft broadcasts can be updated. - [Create comment-to-DM automation](https://docs.zernio.com/comment-automations/create-comment-automation.mdx) - Create a keyword-triggered DM automation on an Instagram or Facebook account. When someone comments a matching keyword (or, with `trigger: story_reply`, replies to your Instagram story with one), they automatically receive a DM. Triggers (`trigger`): * `comment` (default): fires on keyword comments on a post or reel. * `story_reply`: fires when someone replies to your Instagram story with a keyword, and answers them with a DM. Set `platformPostId` to a story media id to scope to one story, or omit it to match replies to any story. Targeting (comment trigger): * Per-post: set `platformPostId` to scope to one specific post (only one active per-post automation is allowed per post). * Account-wide ("any post"): omit `platformPostId` (and `postId`). The automation evaluates every comment on every post on the account. You can stack unlimited account-wide automations, each with its own keyword set, and they all run independently. Per-post automations take priority on their post. Links in the DM's buttons can be click-tracked (`linkTracking`, on by default) and clickers optionally tagged (`clickTag`) for segmentation. Stats returned include delivered, read, and link clicks. - [Delete automation](https://docs.zernio.com/comment-automations/delete-comment-automation.mdx) - Permanently delete an automation and all its trigger logs. - [Get automation details](https://docs.zernio.com/comment-automations/get-comment-automation.mdx) - Returns an automation with its configuration, stats, and recent trigger logs. - [List automation logs](https://docs.zernio.com/comment-automations/list-comment-automation-logs.mdx) - Paginated list of every comment that triggered this automation, with send status and commenter info. - [List comment-to-DM automations](https://docs.zernio.com/comment-automations/list-comment-automations.mdx) - List all comment-to-DM automations for a profile. Returns automations with their stats. - [Update automation settings](https://docs.zernio.com/comment-automations/update-comment-automation.mdx) - Update an automation's keywords, DM message, inline buttons, comment reply, or active status. Pass `buttons: []` to clear all buttons. When `buttons` is non-empty, `dmMessage` (the new one if you're changing it, otherwise the stored one) must be 640 characters or less. - [Delete comment](https://docs.zernio.com/comments/delete-inbox-comment.mdx) - Delete a comment on a post. Supported by Facebook, Instagram, Bluesky, Reddit, YouTube, and LinkedIn. Requires accountId and commentId query parameters. - [Get post comments](https://docs.zernio.com/comments/get-inbox-post-comments.mdx) - Fetch comments for a specific post. Requires accountId query parameter. - [Hide comment](https://docs.zernio.com/comments/hide-inbox-comment.mdx) - Hide a comment on a post. Supported by Facebook, Instagram, Threads, and X/Twitter. Hidden comments are only visible to the commenter and page admin. For X/Twitter, the reply must belong to a conversation started by the authenticated user. - [Like comment](https://docs.zernio.com/comments/like-inbox-comment.mdx) - Like or upvote a comment on a post. Supported platforms: Facebook, Twitter/X, Bluesky, Reddit. For Bluesky, the cid (content identifier) is required in the request body. - [List commented posts](https://docs.zernio.com/comments/list-inbox-comments.mdx) - Returns posts with comment counts from all connected accounts. Aggregates data across multiple accounts. For users with the Ads add-on (Metronome plans always qualify), the user's Meta ads (boosted/dark posts) are included too. There's one row per (ad, placement-with-comments): an ad that runs on both Facebook feed and Instagram feed produces up to two rows (the Page dark post and the IG media have separate comment threads), each flagged `isAd: true` with `adId` and `placement` (`id` is `{adId}:{placement}`). Use `?platform=metaads` to return *only* ad rows; passing `facebook`/`instagram` returns *organic* posts only (no ads); omitting `platform` returns both. Fetch a row's thread from GET /v1/ads/{adId}/comments?placement={placement}. Ad comment counts are read with the Marketing API token (Facebook side) or the connected Instagram account's token (Instagram side); a row whose count can't be read is omitted. - [Reply to comment](https://docs.zernio.com/comments/reply-to-inbox-post.mdx) - Post a reply to a post or specific comment. Requires accountId in request body. - [Send private reply](https://docs.zernio.com/comments/send-private-reply-to-comment.mdx) - Send a private message to the author of a comment. Supported on Instagram and Facebook only. One reply per comment, must be sent within 7 days. Optionally attach interactive elements: `quickReplies` (chips above the keyboard, max 13) or `buttons` (1-3 inline postback/url buttons rendered in the same bubble via Meta's button_template). Buttons are recommended for cold reach since chips do not render in the Instagram Message Requests folder. `quickReplies` and `buttons` are mutually exclusive. - [Unhide comment](https://docs.zernio.com/comments/unhide-inbox-comment.mdx) - Unhide a previously hidden comment. Supported by Facebook, Instagram, Threads, and X/Twitter. - [Unlike comment](https://docs.zernio.com/comments/unlike-inbox-comment.mdx) - Remove a like from a comment. Supported platforms: Facebook, Twitter/X, Bluesky, Reddit. For Bluesky, the likeUri query parameter is required. - [Bulk create contacts](https://docs.zernio.com/contacts/bulk-create-contacts.mdx) - Import up to 1000 contacts at a time. Skips duplicates. - [Create contact](https://docs.zernio.com/contacts/create-contact.mdx) - Create a new contact. Optionally create a platform channel in the same request by providing accountId, platform, and platformIdentifier. - [Delete contact](https://docs.zernio.com/contacts/delete-contact.mdx) - Permanently deletes a contact and all associated channels. - [List channels for a contact](https://docs.zernio.com/contacts/get-contact-channels.mdx) - Returns all messaging channels linked to a contact (e.g. Instagram DM, Telegram, WhatsApp). - [Get contact](https://docs.zernio.com/contacts/get-contact.mdx) - Returns a contact with all associated messaging channels. - [List contacts](https://docs.zernio.com/contacts/list-contacts.mdx) - List and search contacts for a profile. Supports filtering by tags, platform, subscription status, and full-text search. - [Update contact](https://docs.zernio.com/contacts/update-contact.mdx) - Update one or more fields on a contact. Only provided fields are changed. - [Check Telegram status](https://docs.zernio.com/connect/complete-telegram-connect.mdx) - Poll this endpoint to check if a Telegram access code has been used to connect a channel/group. Recommended polling interval: 3 seconds. Status values: pending (waiting for user), connected (channel/group linked), expired (generate a new code). - [Complete number selection](https://docs.zernio.com/connect/complete-whatsapp-phone-selection.mdx) - Bind a specific WhatsApp phone number to the Zernio profile after the user picks one from `listWhatsAppPhoneNumbers`. Exchanges the short-lived OAuth token for a long-lived token, subscribes the WABA to webhooks, and creates the SocialAccount. - [Set TikTok brand identity](https://docs.zernio.com/connect/configure-tiktok-ads-brand-identity.mdx) - Set or update the Brand Identity (display name + avatar) for a `tiktokads` SocialAccount. TikTok requires every ad to carry an `identity_id + identity_type` pair. The Brand Identity is the CUSTOMIZED_USER alternative to attributing ads to a real @username (TT_USER). This route uploads the supplied image to TikTok, creates the identity via `/v2/identity/create/`, and caches the resulting `identity_id` on the account so subsequent `POST /v1/ads/create` calls can opt into it via `identityType: 'CUSTOMIZED_USER'`. Configurable on every `tiktokads` account, including linked-mode ones (those with a posting account on the same profile). Configuration is idempotent and harmless when posting is also connected: the default ad-create path still prefers TT_USER, and CUSTOMIZED_USER is only used per-ad when the caller explicitly opts in. TikTok identities are immutable post-creation. Re-saving creates a new identity on TikTok and swaps the cached id; the old identity stays orphaned on TikTok's side (harmless, no billing impact). Alternative: pass `brandIdentity` directly on `POST /v1/ads/create` to configure on first ad creation in a single round-trip. - [Connect ads for a platform](https://docs.zernio.com/connect/connect-ads.mdx) - Unified ads connection endpoint. Creates a dedicated ads SocialAccount for the specified platform. Same-token platforms (facebook, instagram, linkedin, pinterest): Creates an ads SocialAccount (metaads, linkedinads, pinterestads) with a copied OAuth token from the parent posting account. If the ads account already exists, returns alreadyConnected: true. No extra OAuth needed. Separate-token platforms (tiktok, twitter): Starts the platform-specific marketing API OAuth flow and creates an ads SocialAccount (tiktokads, xads) with its own token. If the ads account already exists, returns alreadyConnected: true. - tiktok: accountId is OPTIONAL. With accountId, the new tiktokads account links to that posting account (parentAccountId set) — Spark Ads + standalone ads using the posting TT_USER identity become available. Without accountId, ads-only mode kicks in: the new tiktokads account has parentAccountId=null and standalone ads use a synthetic CUSTOMIZED_USER ("Brand Identity"); Spark Ads are unavailable because TikTok requires a posting account for them. The Brand Identity is configured separately via PATCH /v1/connect/tiktok-ads (or inline on POST /v1/ads/create via the brandIdentity field). - twitter (X Ads): accountId is REQUIRED. There's no ads-only mode — tweets need to be authored by a real X user. Standalone platforms (googleads): Starts the Google Ads OAuth flow and creates a standalone ads SocialAccount (googleads) with no parent. If the account already exists, returns alreadyConnected: true. Ads accounts appear as regular SocialAccount documents with ads platform values (e.g., metaads, tiktokads) in GET /v1/accounts. - [Connect Bluesky account](https://docs.zernio.com/connect/connect-bluesky-credentials.mdx) - Connect a Bluesky account using identifier (handle or email) and an app password. To get your userId for the state parameter, call GET /v1/users which includes a currentUserId field. - [Connect WhatsApp via credentials](https://docs.zernio.com/connect/connect-whatsapp-credentials.mdx) - Connect a WhatsApp Business Account by providing Meta credentials directly. This is the headless alternative to the Embedded Signup browser flow. To get the required credentials: 1. Go to Meta Business Suite (business.facebook.com) 2. Create or select a WhatsApp Business Account 3. In Business Settings > System Users, create a System User 4. Assign it the whatsapp_business_management and whatsapp_business_messaging permissions 5. Generate a permanent access token 6. Get the WABA ID from WhatsApp Manager > Account Tools > Phone Numbers 7. Get the Phone Number ID from the same page (click on the number) - [Get OAuth connect URL](https://docs.zernio.com/connect/get-connect-url.mdx) - Initiate an OAuth connection flow. Returns an authUrl to redirect the user to. Standard flow: Zernio hosts the selection UI, then redirects to your redirect_url. Headless mode (headless=true): user is redirected to your redirect_url with OAuth data for custom UI. Use the platform-specific selection endpoints to complete. - [List Facebook pages](https://docs.zernio.com/connect/get-facebook-pages.mdx) - Returns all Facebook pages the connected account has access to, including the currently selected page. - [List GBP locations](https://docs.zernio.com/connect/get-gmb-locations.mdx) - Returns Google Business Profile locations the connected account can access, plus the currently selected location. The list is bounded (see hasMore); for accounts that own many locations, use the search or filter query params to find a specific one instead of loading them all. - [List LinkedIn orgs](https://docs.zernio.com/connect/get-linkedin-organizations.mdx) - Returns LinkedIn organizations (company pages) the connected account has admin access to. - [Get pending OAuth data](https://docs.zernio.com/connect/get-pending-oauth-data.mdx) - Fetch pending OAuth data for headless mode using the pendingDataToken from the redirect URL. **Scope**: This endpoint is used for LinkedIn organizations, Snapchat profiles, and Pinterest boards, where the selection list is too large to fit in URL params. The redirect carries a `pendingDataToken` instead of the full payload; the response includes the corresponding selection array (e.g. `boards` for Pinterest). WhatsApp, Facebook, Google Business and other platforms pass selection state directly via URL query params on the redirect (`profileId`, `tempToken`, `step`), no pending record is created, so this endpoint will return 404 for those flows. Use the platform-specific selection endpoint instead (e.g. `/v1/connect/whatsapp/select-phone-number`). Token is one-time use and expires after 10 minutes. No authentication required. - [List Pinterest boards](https://docs.zernio.com/connect/get-pinterest-boards.mdx) - Returns the boards available for a connected Pinterest account. Use this to get a board ID when creating a Pinterest post. - [List subreddit flairs](https://docs.zernio.com/connect/get-reddit-flairs.mdx) - Returns available post flairs for a subreddit. Some subreddits require a flair when posting. - [List Reddit subreddits](https://docs.zernio.com/connect/get-reddit-subreddits.mdx) - Returns the subreddits the connected Reddit account can post to. Use this to get a subreddit name when creating a Reddit post. - [Generate Telegram code](https://docs.zernio.com/connect/get-telegram-connect-status.mdx) - Generate an access code (valid 15 minutes) for connecting a Telegram channel or group. Add the bot as admin, then send the code + @yourchannel to the bot. Poll PATCH /v1/connect/telegram to check status. - [List YouTube playlists](https://docs.zernio.com/connect/get-youtube-playlists.mdx) - Returns the playlists available for a connected YouTube account. Use this to get a playlist ID when creating a YouTube post with the playlistId field. - [Complete OAuth callback](https://docs.zernio.com/connect/handle-oauth-callback.mdx) - Exchange the OAuth authorization code for tokens and connect the account to the specified profile. - [Connect Telegram directly](https://docs.zernio.com/connect/initiate-telegram-connect.mdx) - Connect a Telegram channel/group directly using the chat ID. Alternative to the access code flow. The bot must already be an admin in the channel/group. - [List Facebook pages](https://docs.zernio.com/connect/list-facebook-pages.mdx) - Returns the list of Facebook Pages the user can manage after OAuth. Extract tempToken and userProfile from the OAuth redirect params and pass them here. Use the X-Connect-Token header if connecting via API key. - [List GBP locations](https://docs.zernio.com/connect/list-google-business-locations.mdx) - For headless flows. Returns the list of GBP locations the user can manage. Use pendingDataToken (from the OAuth callback redirect) to list locations without consuming the token, so it remains available for select-location. Use X-Connect-Token header if connecting via API key. - [List LinkedIn orgs](https://docs.zernio.com/connect/list-linkedin-organizations.mdx) - Fetch full LinkedIn organization details (logos, vanity names, websites) for custom UI. No authentication required, just the tempToken from OAuth. - [List Pinterest boards](https://docs.zernio.com/connect/list-pinterest-boards-for-selection.mdx) - For headless flows. Returns Pinterest boards the user can post to. Use X-Connect-Token from the redirect URL. - [List Snapchat profiles](https://docs.zernio.com/connect/list-snapchat-profiles.mdx) - For headless flows. Returns Snapchat Public Profiles the user can post to. Use X-Connect-Token from the redirect URL. - [List numbers for selection](https://docs.zernio.com/connect/list-whatsapp-phone-numbers.mdx) - Fetch the WhatsApp phone numbers available across the user's WhatsApp Business Accounts (WABAs) after a headless OAuth flow. WhatsApp OAuth grants access at the WABA level. When a connected WABA has 2 or more phone numbers, you must call this endpoint to list them and then `POST /v1/connect/whatsapp/select-phone-number` to bind one to the Zernio profile. Single-phone WABAs auto-complete during the OAuth callback and never reach this endpoint. Use the `profileId` and `tempToken` returned in the headless redirect (`step=select_phone_number`). Alternative: if you already know `wabaId` and `phoneNumberId` (e.g. from Meta Business Suite), use `connectWhatsAppCredentials` instead, which skips this two-step flow. - [Select Facebook page](https://docs.zernio.com/connect/select-facebook-page.mdx) - Complete the headless flow by saving the user's selected Facebook page. Pass the userProfile from the OAuth redirect and use X-Connect-Token if connecting via API key. - [Select GBP location](https://docs.zernio.com/connect/select-google-business-location.mdx) - Complete the headless GBP flow by saving the user's selected location. The pendingDataToken is returned in your redirect URL after OAuth completes (step=select_location). Tokens and profile data are stored server-side, so only the pendingDataToken is needed here. Use X-Connect-Token header if connecting via API key. - [Select LinkedIn org](https://docs.zernio.com/connect/select-linkedin-organization.mdx) - Complete the LinkedIn connection flow. Set accountType to "personal" or "organization" to connect as a company page. Use X-Connect-Token if connecting via API key. - [Select Pinterest board](https://docs.zernio.com/connect/select-pinterest-board.mdx) - Complete the Pinterest connection flow. After OAuth, use this endpoint to save the selected board and complete the account connection. Use the X-Connect-Token header if you initiated the connection via API key. - [Select Snapchat profile](https://docs.zernio.com/connect/select-snapchat-profile.mdx) - Complete the Snapchat connection flow by saving the selected Public Profile. Snapchat requires a Public Profile to publish content. Use X-Connect-Token if connecting via API key. - [Update Facebook page](https://docs.zernio.com/connect/update-facebook-page.mdx) - Switch which Facebook Page is active for a connected account. - [Update GBP location](https://docs.zernio.com/connect/update-gmb-location.mdx) - Switch which GBP location is active for a connected account. - [Switch LinkedIn account type](https://docs.zernio.com/connect/update-linkedin-organization.mdx) - Switch a LinkedIn account between personal profile and organization (company page) posting. - [Set default Pinterest board](https://docs.zernio.com/connect/update-pinterest-boards.mdx) - Sets the default board used when publishing pins for this account. - [Set default subreddit](https://docs.zernio.com/connect/update-reddit-subreddits.mdx) - Sets the default subreddit used when publishing posts for this Reddit account. - [Set default YouTube playlist](https://docs.zernio.com/connect/update-youtube-default-playlist.mdx) - Sets the default playlist used when publishing videos for this account. When a post does not specify a playlistId, the default playlist is not automatically used (it is stored for client-side convenience). - [Clear custom field value](https://docs.zernio.com/custom-fields/clear-contact-field-value.mdx) - Remove a custom field value from a contact. The field definition is not affected. - [Create custom field](https://docs.zernio.com/custom-fields/create-custom-field.mdx) - Create a new custom field definition. Supported types are text, number, date, boolean, and select. - [Delete custom field](https://docs.zernio.com/custom-fields/delete-custom-field.mdx) - Delete a custom field definition and remove its values from all contacts. - [List custom field definitions](https://docs.zernio.com/custom-fields/list-custom-fields.mdx) - Returns all custom field definitions. Optionally filter by profile. - [Set custom field value](https://docs.zernio.com/custom-fields/set-contact-field-value.mdx) - Set or overwrite a custom field value on a contact. The value type must match the field definition. - [Update custom field](https://docs.zernio.com/custom-fields/update-custom-field.mdx) - Update a custom field definition. The field type cannot be changed after creation. - [Assign a role to a guild member](https://docs.zernio.com/discord/add-discord-member-role.mdx) - Assign one role to one member. Idempotent on Discord's side — re-running on a member who already has the role is a 204 no-op. Path shape mirrors Discord's own API (`PUT /guilds/{guild}/members/{user}/roles/{role}`) for zero-translation mental mapping. Bot needs MANAGE_ROLES permission in the guild AND its highest role must be above the target role (Discord hierarchy rule). The `@everyone` role (where roleId == guildId) cannot be assigned. - [Create a Discord scheduled event](https://docs.zernio.com/discord/create-discord-scheduled-event.mdx) - Create a guild scheduled event. Three event types, selected via the discriminator on `entity.type`: - `external` — off-platform (Zoom, in-person, livestream). Requires both `location` and `endsAt`. Most common type for scheduler integrations. - `voice` — hosted in a Discord voice channel. Requires `channelId`. - `stage` — hosted in a Discord stage channel. Requires `channelId`. Bot needs MANAGE_EVENTS in the guild. Existing installs (pre-events PR) need a re-invite OR a server admin manually granting the permission — see route header for details. - [Delete a Discord scheduled event](https://docs.zernio.com/discord/delete-discord-scheduled-event.mdx) - Hard-delete an event. Use PATCH with `status: 'cancelled'` instead if you want the event preserved in the guild's history. - [List Discord guild channels](https://docs.zernio.com/discord/get-discord-channels.mdx) - Returns the text, announcement, and forum channels in the connected Discord guild. Use this to discover available channels when switching the connected channel via PATCH /v1/accounts/{accountId}/discord-settings. - [Get a Discord scheduled event](https://docs.zernio.com/discord/get-discord-scheduled-event.mdx) - [Get Discord account settings](https://docs.zernio.com/discord/get-discord-settings.mdx) - Returns the current Discord account settings including webhook identity (display name and avatar), connected channel, and guild information. - [List Discord guild members](https://docs.zernio.com/discord/list-discord-guild-members.mdx) - Cursor-paginated list of guild members. Returns Discord's raw member objects so callers can build community-ops automation (e.g. "add role to all members joined in the last 7 days") on the actual platform shape. **Important:** this endpoint requires the privileged "Server Members Intent" enabled on the Discord app (Developer Portal → Bot tab → toggle "Server Members Intent" ON, then Save). Without it, Discord returns an empty array with no error. Verify the intent is enabled before relying on this endpoint. Pagination: pass `after` = the last `user.id` from the previous page. Omit on the first call. Response includes a `nextCursor` and `hasMore` flag so callers don't need to know Discord's pagination shape. - [List Discord guild roles](https://docs.zernio.com/discord/list-discord-guild-roles.mdx) - Returns all roles in a Discord guild. Useful for building role-mention pickers, role-permission UIs, or finding the role ID before calling the role-assign endpoint. Roles are returned unordered — sort client-side by `position` if you need Discord's UI ordering. Caller must pass `accountId` of a Discord SocialAccount bound to this guild (route verifies team access + guild match). - [List pinned messages](https://docs.zernio.com/discord/list-discord-pinned-messages.mdx) - Returns the channel's pinned messages, sorted most-recently-pinned first. Discord caps a channel at 50 pinned messages and returns the full list unpaginated. Bot needs READ_MESSAGE_HISTORY in the channel (granted by default BOT_PERMISSIONS). - [List Discord scheduled events](https://docs.zernio.com/discord/list-discord-scheduled-events.mdx) - Return all scheduled events in the guild. Events are distinct from messages — they appear in the server's Events panel and Discord auto-notifies interested members ahead of start time. Pass `withUserCount=true` to include `user_count` (number of members who RSVP'd) on each event. Useful for surfacing engagement. - [Pin a Discord message](https://docs.zernio.com/discord/pin-discord-message.mdx) - Pin a specific message in a channel. Path shape mirrors Discord's own API (`PUT /channels/{cid}/pins/{mid}`). Idempotent — re-pinning an already-pinned message is a 204 no-op. Constraints: - Bot needs MANAGE_MESSAGES in the channel. - 50-pin cap per channel — hitting it returns 400 (Discord-side). Caller should unpin one first. - [Remove a role from a guild member](https://docs.zernio.com/discord/remove-discord-member-role.mdx) - Remove one role from one member. Idempotent — removing a role the member doesn't have returns 204 no-op. Same permission + hierarchy constraints as the PUT counterpart. - [Send a Discord Direct Message](https://docs.zernio.com/discord/send-discord-direct-message.mdx) - Send a 1:1 Direct Message from the bot to a Discord user (by snowflake ID). Supports the same payload shape as channel posts — content, embeds, media attachments, and TTS. Constraints (Discord platform limits): - The bot can only DM users it shares at least one guild with. - If the recipient has DMs disabled for non-friends, Discord returns 403 (surfaces as a 502 platform error). - `content` capped at 2,000 chars. - At least one of `content`, `embeds`, or `attachments` is required. - The recipient must be identified by Discord snowflake ID (not username). This is a dedicated endpoint rather than a `POST /v1/posts` variant because DMs are 1:1 operational messages (onboarding, billing reminders, support pings) with a different lifecycle than scheduled channel posts. DMs are not persisted to `Post` / `ExternalPost` and are always sent immediately. - [Unpin a Discord message](https://docs.zernio.com/discord/unpin-discord-message.mdx) - Unpin a message. Same MANAGE_MESSAGES permission requirement as pin. Idempotent — unpinning a non-pinned message is a 204 no-op. - [Update a Discord scheduled event](https://docs.zernio.com/discord/update-discord-scheduled-event.mdx) - Patch any subset of fields. Passing `status: 'cancelled'` is how you cancel an event — Discord doesn't have a dedicated cancel endpoint, it's a status transition. Most status transitions Discord enforces (you can't go SCHEDULED → COMPLETED directly). The common consumer case is SCHEDULED → CANCELED. - [Update Discord settings](https://docs.zernio.com/discord/update-discord-settings.mdx) - Update Discord account settings. Supports two operations (can be combined): 1. **Webhook identity** - Set the default display name and avatar that appear as the message author on every post. These are account-level defaults; individual posts can override them via platformSpecificData.webhookUsername / webhookAvatarUrl. 2. **Switch channel** - Move the connection to a different channel in the same guild. A new webhook is automatically created in the target channel. - [Batch get reviews](https://docs.zernio.com/google-business/batch-get-google-business-reviews.mdx) - Fetches reviews across multiple locations in a single request. More efficient than calling GET /gmb-reviews per location for multi-location businesses. Returns a flat list of individual reviews, each tagged with its review resource name. Note: this endpoint does not return aggregate metrics (averageRating / totalReviewCount). For those, use the single-location GET /gmb-reviews endpoint. - [Complete a verification](https://docs.zernio.com/google-business/complete-google-business-verification.mdx) - Completes a PENDING verification by submitting the PIN/code Google sent the business (postcard code, SMS PIN, etc.). On success the verification moves to COMPLETED. - [Upload photo](https://docs.zernio.com/google-business/create-google-business-media.mdx) - Creates a media item (photo) for a location from a publicly accessible URL. Categories determine where the photo appears: COVER, PROFILE, LOGO, EXTERIOR, INTERIOR, FOOD_AND_DRINK, MENU, PRODUCT, TEAMS, ADDITIONAL. - [Create action link](https://docs.zernio.com/google-business/create-google-business-place-action.mdx) - Creates a place action link for a location. Available action types: APPOINTMENT, ONLINE_APPOINTMENT, DINING_RESERVATION, FOOD_ORDERING, FOOD_DELIVERY, FOOD_TAKEOUT, SHOP_ONLINE. - [Delete photo](https://docs.zernio.com/google-business/delete-google-business-media.mdx) - Deletes a photo or media item from a GBP location. - [Delete action link](https://docs.zernio.com/google-business/delete-google-business-place-action.mdx) - Deletes a place action link (e.g. booking or ordering URL) from a GBP location. - [Delete a review reply](https://docs.zernio.com/google-business/delete-google-business-review-reply.mdx) - Removes the business owner reply from a Google Business review. The review itself remains. - [Fetch verification options](https://docs.zernio.com/google-business/fetch-google-business-verification-options.mdx) - Reports the verification methods Google currently offers for the location. Non-mutating (nothing is sent to the business). `languageCode` is required; service-area ("CUSTOMER_LOCATION_ONLY") businesses also require `context.address`, otherwise Google returns 400. - [Get attribute metadata](https://docs.zernio.com/google-business/get-gmb-attribute-metadata.mdx) - Returns metadata about which Google Business Profile attributes are available for a location or business category. Use this endpoint to discover valid attribute names, value types, and allowed enum values before reading or writing via gmb-attributes. Two mutually exclusive query modes: **Location mode**: pass `locationId` (or rely on the account's stored `selectedLocationId`). Google returns attributes valid for that specific location. **Category mode**: pass `categoryName` (must start with `categories/`) and `regionCode`. Google returns attributes valid for that category across the given region. `languageCode` is optional in category mode. Both modes support `pageSize` and `pageToken` for pagination. - [Get attributes](https://docs.zernio.com/google-business/get-google-business-attributes.mdx) - Returns GBP location attributes (amenities, services, accessibility, payment types). Available attributes vary by business category. - [Get food menus](https://docs.zernio.com/google-business/get-google-business-food-menus.mdx) - Returns food menus for a GBP location including sections, items, pricing, and dietary info. Only for locations with food menu support. - [Get location details](https://docs.zernio.com/google-business/get-google-business-location-details.mdx) - Returns detailed GBP location info (hours, description, phone, website, categories, services). Use readMask to request specific fields. - [Get reviews](https://docs.zernio.com/google-business/get-google-business-reviews.mdx) - Returns reviews for a GBP account including ratings, comments, and owner replies. Use nextPageToken for pagination. - [Get services](https://docs.zernio.com/google-business/get-google-business-services.mdx) - Gets the services offered by a Google Business Profile location. Returns an array of service items (structured or free-form with optional price). - [Get verification state](https://docs.zernio.com/google-business/get-google-business-verifications.mdx) - Returns the location's Voice of Merchant state plus its verification history. `voiceOfMerchantState.hasVoiceOfMerchant` tells you whether the listing is verified and published; when it is false, `verify` reports whether a verification is already pending. Each entry in `verifications` has a `state` of PENDING, COMPLETED, or FAILED. - [List media](https://docs.zernio.com/google-business/list-google-business-media.mdx) - Lists media items (photos) for a Google Business Profile location. Returns photo URLs, descriptions, categories, and metadata. - [List action links](https://docs.zernio.com/google-business/list-google-business-place-actions.mdx) - Lists place action links for a Google Business Profile location. Place actions are the booking, ordering, and reservation buttons that appear on your listing. - [Reply to a review](https://docs.zernio.com/google-business/reply-to-google-business-review.mdx) - Posts (or updates) the business owner reply to a Google Business review. The reply is associated with the account's currently selected location (set via /v1/accounts/{accountId}/gmb-locations). Calling this endpoint a second time on the same review overwrites the previous reply (PUT semantics on Google's side). - [Start a verification](https://docs.zernio.com/google-business/start-google-business-verification.mdx) - Starts a verification for the location. This is a mutating action: depending on `method`, Google mails a postcard, places a call, or sends an SMS/email to the business. Submit the resulting code with POST /gmb-verifications/{verificationId}/complete. Use POST /gmb-verifications/options first to discover which methods are eligible. - [Update attributes](https://docs.zernio.com/google-business/update-google-business-attributes.mdx) - Updates location attributes (amenities, services, etc.). The attributeMask specifies which attributes to update (comma-separated). - [Update food menus](https://docs.zernio.com/google-business/update-google-business-food-menus.mdx) - Updates food menus for a GBP location. Send the full menus array. Use updateMask for partial updates. - [Update location details](https://docs.zernio.com/google-business/update-google-business-location-details.mdx) - Updates GBP location details. The updateMask field is required and specifies which fields to update. This endpoint proxies Google's Business Information API locations.patch, so any valid updateMask field is supported. Common fields: regularHours, specialHours, profile.description, websiteUri, phoneNumbers, categories, serviceItems. - [Update action link](https://docs.zernio.com/google-business/update-google-business-place-action.mdx) - Updates a place action link (change URL or action type). Only the fields included in the request body will be updated. - [Replace services](https://docs.zernio.com/google-business/update-google-business-services.mdx) - Replaces the entire service list for a location. Google's API requires full replacement; individual item updates are not supported. Each service can be structured (using a predefined serviceTypeId) or free-form (custom label). - [Get conversation analytics](https://docs.zernio.com/inbox-analytics/get-inbox-conversation-analytics.mdx) - Per-conversation inbox analytics. The inbox analog of /v1/analytics/post-timeline — one conversation, daily totals, source mix. The {conversationId} path param accepts EITHER the Mongo `_id` of the Conversation document OR its `platformConversationId` (the same identity used by metadata.conversationId at ingest time). Ownership is verified in MongoDB against the caller's team before the Tinybird query fires. Max date range is 365 days. - [Get day × hour heatmap](https://docs.zernio.com/inbox-analytics/get-inbox-heatmap.mdx) - Day-of-week × hour-of-day breakdown of inbox messages. Buckets are sparse — only cells with at least one event are returned; clients zero-fill the rest to render the full 7×24 grid. The `dow` field follows ClickHouse's `toDayOfWeek` convention (1 = Monday … 7 = Sunday). Max date range is 365 days. - [Get inbox response-time stats](https://docs.zernio.com/inbox-analytics/get-inbox-response-time.mdx) - Time-to-first-response stats. Pairs each received message with the next sent message in the same conversation and reports the delta as both summary statistics and a fixed-bucket histogram suited for the analytics page's TTR chart. `sampleSize` reflects only conversations that received AND got a reply in the window — received-but-never-answered conversations are excluded. Compare against /v1/analytics/inbox/volume's `summary.received` to compute reply rate. Max date range is 365 days. - [Get inbox source breakdown](https://docs.zernio.com/inbox-analytics/get-inbox-source-breakdown.mdx) - Breakdown of inbox messages by their lineage source (the `metadata.source` field set at ingest time: human / workflow / sequence / broadcast / comment_automation / api / contact / platform). Each source row also carries a per-platform sub-split. Max date range is 365 days. - [Get top accounts by inbox volume](https://docs.zernio.com/inbox-analytics/get-inbox-top-accounts.mdx) - Leaderboard of social accounts by inbox message volume. Decorates each row with display labels from the live SocialAccount record (so the UI shows username + displayName, not just an ID). Accounts that no longer map to a SocialAccount surface as "(disconnected)" so the row stays visible. Max date range is 365 days. - [Get inbox messaging volume](https://docs.zernio.com/inbox-analytics/get-inbox-volume.mdx) - Daily inbox messaging volume + breakdowns. Folds the raw messaging events into three projections so the client can render the volume chart, KPI strip, and per-platform stacked bar from a single call. Max date range is 365 days. - [List conversation analytics](https://docs.zernio.com/inbox-analytics/list-inbox-conversation-analytics.mdx) - Per-conversation listing with per-row totals + first/last message timestamps. The inbox analog of GET /v1/analytics (posts listing) — same filter shape, same pagination, same sort/order semantics. Use as the entry point for the per-conversation analytics drawer at /v1/analytics/inbox/conversations/{conversationId}. Rows are enriched with the conversation's participant info (`participantName`, `participantUsername`, `participantPicture`) and last-message preview by joining the Conversation document scoped to the caller's team. Max date range is 365 days. - [Get Instagram story insights](https://docs.zernio.com/instagram/get-instagram-story-insights.mdx) - Returns metrics for a single story. The `source` field discriminates between three states: - `live` — fetched from Meta in real time (story is still active) - `cached` — fetched from a persisted `story_insights` webhook payload (story has expired but we received its final-state metrics from Meta) - `unavailable` — story has expired and we never received its webhook payload (for example, the account connected after the story expired) Field semantics follow Meta's API. Counts below 5 may be returned as 0 due to Meta's privacy floor on small audiences. The `navigation` field is the sum of `tapsForward + tapsBack + exits + swipesForward`. - [List active Instagram stories](https://docs.zernio.com/instagram/list-instagram-stories.mdx) - Returns the IG Business/Creator account's currently-active stories. Meta keeps stories live for 24h; expired stories are not returned. Limitations propagated from Meta (these are NOT bugs): - 24h window only - Live videos excluded - Reshared stories not returned - `mediaUrl` may be null if Meta flagged the story for copyright - `caption`, `likeCount`, `commentsCount` do not apply to story media - [Create invite token](https://docs.zernio.com/invites/create-invite-token.mdx) - Generate a secure invite link to grant team members access to your profiles. Invites expire after 7 days and are single-use. - [Resolve LinkedIn mention](https://docs.zernio.com/linkedin-mentions/get-linkedin-mentions.mdx) - Converts a LinkedIn profile or company URL to a URN for @mentions in posts. How to use LinkedIn @mentions (2-step workflow): 1. Call this endpoint with the LinkedIn profile/company URL to get the mention URN and format. 2. Embed the returned mentionFormat (e.g. @[Vincent Jong](urn:li:person:xxx)) directly in your post's content field. Example: - Resolve: GET /v1/accounts/{id}/linkedin-mentions?url=linkedin.com/in/vincentjong&displayName=Vincent Jong - Returns: mentionFormat: "@[Vincent Jong](urn:li:person:xxx)" - Use in post content: "Great talk with @[Vincent Jong](urn:li:person:xxx) today!" Important: The mentions array field in POST /v1/posts is stored for reference only and does NOT trigger @mentions on LinkedIn. You must embed the mention format directly in the content text. Requirements: - Person mentions require the LinkedIn account to be admin of at least one organization. This is a LinkedIn API limitation: the only endpoints that resolve profile URLs to member URNs (vanityUrl, peopleTypeahead) are scoped to organization followers. There is no public LinkedIn API to resolve a vanity URL without organization context. - Organization mentions (e.g. @Microsoft) work without this requirement. - For person mentions to be clickable, the displayName parameter must exactly match the name shown on their LinkedIn profile. - Person mentions DO work when published from personal profiles (the URN just needs to be valid). The limitation is only in the resolution step (URL to URN), not in publishing. - [List activity logs](https://docs.zernio.com/logs/list-logs.mdx) - Unified logs endpoint. Returns logs for publishing, connections, webhooks, and messaging. Filter by type, platform, status, and time range. Logs are retained for 90 days. - [Get upload URL](https://docs.zernio.com/media/get-media-presigned-url.mdx) - Get a presigned URL to upload files directly to cloud storage (up to 5GB). Returns an uploadUrl and publicUrl. PUT your file to the uploadUrl, then use the publicUrl in your posts. - [List mentions](https://docs.zernio.com/mentions/list-inbox-mentions.mdx) - Returns mentions of your connected organization accounts, delivered via platform webhooks. Currently supports LinkedIn organization mentions. Requires Inbox addon. - [Add reaction](https://docs.zernio.com/messages/add-message-reaction.mdx) - Add an emoji reaction to a message. Platform support: - Telegram: Supports a subset of Unicode emoji reactions - WhatsApp: Supports any standard emoji (one reaction per message per sender) - All others: Returns 400 (not supported) - [Create conversation](https://docs.zernio.com/messages/create-inbox-conversation.mdx) - Initiate a new direct message conversation with a specified user. If a conversation already exists with the recipient, the message is added to the existing thread. Supported platforms: X/Twitter, Bluesky, Reddit, and WhatsApp. Other platforms return PLATFORM_NOT_SUPPORTED. WhatsApp: this is the endpoint for sending an approved template message to a phone number. Provide templateName, templateLanguage, and templateParams (body variable values), with the recipient phone in participantId. A template is required because WhatsApp does not permit freeform messages to open a conversation; a missing template returns TEMPLATE_REQUIRED. Templates with media headers (image, video, document) are handled automatically: Zernio reads the approved template definition and fills the header at send time. Calling this for a number you already have a thread with simply sends the template into that thread, which also makes it the way to re-engage a contact after the 24-hour customer-service window has closed. Once the recipient replies (opening the 24h window), send freeform messages with the send-message endpoint (POST /v1/inbox/conversations/{conversationId}/messages). Template fields are accepted on the JSON body only, not on multipart requests. DM eligibility (X/Twitter): Before sending, the endpoint checks if the recipient accepts DMs from your account (via the receives_your_dm field). If not, a 422 error with code DM_NOT_ALLOWED is returned. You can skip this check with skipDmCheck: true if you have already verified eligibility. X API tier requirement: DM write endpoints require X API Pro tier ($5,000/month) or Enterprise access. This applies to BYOK (Bring Your Own Key) users who provide their own X API credentials. Rate limits: 200 requests per 15 minutes, 1,000 per 24 hours per user, 15,000 per 24 hours per app (shared across all DM endpoints). - [Delete message](https://docs.zernio.com/messages/delete-inbox-message.mdx) - Delete a message from a conversation. Platform support varies: - Telegram: Full delete (bot's own messages anytime, others if admin) - X/Twitter: Full delete (own DM events only) - Bluesky: Delete for self only (recipient still sees it) - Reddit: Delete from sender's view only - Facebook, Instagram, WhatsApp: Not supported (returns 400) - [Edit message](https://docs.zernio.com/messages/edit-inbox-message.mdx) - Edit the text and/or reply markup of a previously sent Telegram message. Only supported for Telegram. Returns 400 for other platforms. - [List messages](https://docs.zernio.com/messages/get-inbox-conversation-messages.mdx) - Fetch messages for a specific conversation, with cursor-based pagination and ordering control. Pagination: pass `pagination.nextCursor` from a prior response back as the `cursor` query param to fetch the next page. The cursor is opaque; do not parse or construct it client-side. Sort order: defaults to `asc` (oldest first, chat style). For the "show me the latest messages" pattern, pass `?sortOrder=desc&limit=N`. Twitter, Instagram, Telegram, WhatsApp and Reddit honor the requested order from the local message store. For Facebook and Bluesky, the upstream APIs only return newest-first and have no order parameter — sort order is best-effort and only reverses items within a single page (pages still walk newest→oldest). The response field `sortOrderApplied` tells you what was actually applied. Reddit threads are paginated client-side because Reddit's API has no per-thread cursor. Very long threads may be upstream-truncated by Reddit's inbox/sent windows (~100 most-recent items each); this is a Reddit platform limitation. Twitter/X limitation: X's encrypted "X Chat" messages are not accessible via the API. Conversations where the other participant uses encrypted X Chat may only show your outgoing messages. See the list conversations endpoint for more details. This endpoint is read-only and does NOT mark messages as read or send read receipts. To mark a conversation read (and send WhatsApp blue ticks on eligible accounts), call `POST /v1/inbox/conversations/{conversationId}/read`. - [Get conversation](https://docs.zernio.com/messages/get-inbox-conversation.mdx) - Retrieve details and metadata for a specific conversation. Requires accountId query parameter. - [List conversations](https://docs.zernio.com/messages/list-inbox-conversations.mdx) - Fetch conversations (DMs) from all connected messaging accounts in a single API call. Supports filtering by profile and platform. Results are aggregated and deduplicated. Supported platforms: Facebook, Instagram, Twitter/X, Bluesky, Reddit, Telegram. Twitter/X limitation: X has replaced traditional DMs with encrypted "X Chat" for many accounts. Messages sent or received through encrypted X Chat are not accessible via X's API (the /2/dm_events endpoint only returns legacy unencrypted DMs). This means some Twitter/X conversations may show only outgoing messages or appear empty. This is an X platform limitation that affects all third-party applications. See X's docs on encrypted messaging for more details. - [Mark a conversation as read](https://docs.zernio.com/messages/mark-conversation-read.mdx) - Marks all unread incoming messages in the conversation as read. For WhatsApp, this also sends read receipts (blue ticks) to the contact, EXCEPT on coexistence accounts (where the WhatsApp Business app on the customer's phone owns read state and we never override it). This is the explicit, human-driven counterpart to `GET .../messages`, which is side-effect-free and does NOT mark anything read. Call this when a user actually views the conversation. - [Remove reaction](https://docs.zernio.com/messages/remove-message-reaction.mdx) - Remove a reaction from a message. Platform support: - Telegram: Send empty reaction array to clear - WhatsApp: Send empty emoji to remove - All others: Returns 400 (not supported) - [Send message](https://docs.zernio.com/messages/send-inbox-message.mdx) - Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ "elements": [{ "name": ..., "language": ..., "components": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). - [Send typing indicator](https://docs.zernio.com/messages/send-typing-indicator.mdx) - Show a typing indicator in a conversation. Platform support: - Facebook Messenger: Shows "Page is typing..." for 20 seconds - Telegram: Shows "Bot is typing..." for 5 seconds - WhatsApp: Shows "typing..." for up to 25 seconds. Requires a recent inbound message in the conversation (Meta references the inbound message id) and also marks that message as read as a side-effect. - All others: Returns 200 but no-op (platform doesn't support it) Typing indicators are best-effort. The endpoint always returns 200 even if the platform call fails. - [Update conversation status](https://docs.zernio.com/messages/update-inbox-conversation.mdx) - Archive or activate a conversation. Requires accountId in request body. - [Upload media file](https://docs.zernio.com/messages/upload-media-direct.mdx) - Upload a media file using API key authentication and get back a publicly accessible URL. The URL can be used as attachmentUrl when sending inbox messages. Files are stored in temporary storage and auto-delete after 7 days. Maximum file size is 25MB. Unlike /v1/media/upload (which uses upload tokens for end-user flows), this endpoint uses standard Bearer token authentication for programmatic use. - [Bulk upload from CSV](https://docs.zernio.com/posts/bulk-upload-posts.mdx) - Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts. - [Create post](https://docs.zernio.com/posts/create-post.mdx) - Create and optionally publish a post. Immediate posts (`publishNow: true`) include `platformPostUrl` in the response. Content is optional when media is attached or all platforms have `customContent`. See each platform's schema for media constraints. ## Idempotency Two layers of duplicate-protection apply, so safe-to-retry callers (network blips, n8n / Zapier retries, etc.) don't accidentally double-post. **1. Same-request idempotency (5-minute window).** Pass an `x-request-id` header to mark a logical request. If a second request arrives with the same `x-request-id` while the first is in-flight (or within ~5 minutes of completion), we return **HTTP 200** with the original post in the `existingPost` field — no new post is created. The official Zernio SDKs auto-generate a unique `x-request-id` per call. If you're using a generic HTTP client (curl, n8n's HTTP node, Zapier, custom code), either: - Set a unique `x-request-id` per logical call (recommended — UUIDv4 is fine) - Or simply omit the header — we'll treat each request as new **Common pitfall**: if your workflow tool uses a single execution-level request ID and reuses it across multiple HTTP nodes (e.g. one ID for the whole run, shared across 6 different platform calls), every call after the first will look like a retry of the first and return its post. Generate a fresh ID per node. **2. Content-hash dedup (24-hour window).** Independently, we hash `(platform, accountId, content + media URLs)` and reject duplicates within 24 hours with **HTTP 409**. This catches genuine "same content posted twice to the same account" cases regardless of `x-request-id`. Returns `error`, `accountId`, `platform`, and `existingPostId` so you can find the original. To intentionally re-post identical content within 24h, change something (the caption, the media, the account) — the dedup is keyed on the full content fingerprint. Order: same-`x-request-id` retries (200) are checked first; if no idempotency match, the content-hash dedup (409) runs. - [Delete post](https://docs.zernio.com/posts/delete-post.mdx) - Delete a draft or scheduled post from Zernio. Published posts cannot be deleted; use the Unpublish endpoint instead. Upload quota is automatically refunded. - [Edit published post](https://docs.zernio.com/posts/edit-post.mdx) - Edit a published post on a social media platform. Currently only supported for X (Twitter). Requirements: - Connected X account must have an active X Premium subscription - Must be within 1 hour of original publish time - Maximum 5 edits per tweet (enforced by X) - Text-only edits (media changes are not supported) The post record in Zernio is updated with the new content and edit history. - [Get post](https://docs.zernio.com/posts/get-post.mdx) - Fetch a single post by ID. For published posts, this returns platformPostUrl for each platform. - [List posts](https://docs.zernio.com/posts/list-posts.mdx) - Returns a paginated list of posts. Published posts include platformPostUrl with the public URL on each platform. - [Retry failed post](https://docs.zernio.com/posts/retry-post.mdx) - Immediately retries publishing a failed post. Returns the updated post with its new status. - [Unpublish post](https://docs.zernio.com/posts/unpublish-post.mdx) - Deletes a published post from the specified platform. The post record in Zernio is kept but its status is updated to cancelled. Not supported on Instagram, TikTok, or Snapchat. Threaded posts delete all items. YouTube deletion is permanent. - [Update post metadata](https://docs.zernio.com/posts/update-post-metadata.mdx) - Updates metadata of a published video on the specified platform without re-uploading. Currently only supported for YouTube. At least one updatable field is required. Two modes: 1. Post-based (video published through Zernio): pass the Zernio postId in the URL and platform in the body. 2. Direct video ID (video uploaded outside Zernio, e.g. directly to YouTube): use _ as the postId, and pass videoId + accountId + platform in the body. The accountId is the Zernio social account ID for the connected YouTube channel. - [Update post](https://docs.zernio.com/posts/update-post.mdx) - Update an existing post. Draft, scheduled, failed, partial, and cancelled posts can be edited. Published posts can only have their recycling config updated. - [Create profile](https://docs.zernio.com/profiles/create-profile.mdx) - Creates a new profile with a name, optional description, and color. - [Delete profile](https://docs.zernio.com/profiles/delete-profile.mdx) - Permanently deletes a profile. Active connected accounts block deletion (returns 400) - disconnect them first. Any remaining disconnected accounts and provisioned WhatsApp numbers are moved to another of your profiles (a new one is created only if needed), never deleted. - [Get profile](https://docs.zernio.com/profiles/get-profile.mdx) - Returns a single profile by ID, including its name, color, and default status. - [List profiles](https://docs.zernio.com/profiles/list-profiles.mdx) - Returns profiles sorted by creation date. Use includeOverLimit=true to include profiles that exceed the plan limit. - [Update profile](https://docs.zernio.com/profiles/update-profile.mdx) - Updates a profile's name, description, color, or default status. - [Create schedule](https://docs.zernio.com/queue/create-queue-slot.mdx) - Create an additional queue for a profile. The first queue created becomes the default. Subsequent queues are non-default unless explicitly set. - [Delete schedule](https://docs.zernio.com/queue/delete-queue-slot.mdx) - Delete a queue from a profile. Requires queueId to specify which queue to delete. If deleting the default queue, another queue will be promoted to default. - [Get next available slot](https://docs.zernio.com/queue/get-next-queue-slot.mdx) - Returns the next available queue slot for preview purposes. To create a queue post, use POST /v1/posts with queuedFromProfile instead of scheduledFor. - [List schedules](https://docs.zernio.com/queue/list-queue-slots.mdx) - Returns queue schedules for a profile. Use all=true for all queues, or queueId for a specific one. Defaults to the default queue. - [Preview upcoming slots](https://docs.zernio.com/queue/preview-queue.mdx) - Returns the next N upcoming queue slot times for a profile as ISO datetime strings. - [Update schedule](https://docs.zernio.com/queue/update-queue-slot.mdx) - Create a new queue or update an existing one. Without queueId, creates/updates the default queue. With queueId, updates a specific queue. With setAsDefault=true, makes this queue the default for the profile. - [Get subreddit feed](https://docs.zernio.com/reddit-search/get-reddit-feed.mdx) - Fetch posts from a subreddit feed. Supports sorting, time filtering, and cursor-based pagination. - [Search posts](https://docs.zernio.com/reddit-search/search-reddit.mdx) - Search Reddit posts using a connected account. Optionally scope to a specific subreddit. - [Delete review reply](https://docs.zernio.com/reviews/delete-inbox-review-reply.mdx) - Delete a reply to a review (Google Business only). Requires accountId in request body. - [List reviews](https://docs.zernio.com/reviews/list-inbox-reviews.mdx) - Fetch reviews from all connected Facebook Pages and Google Business accounts. Aggregates data with filtering and sorting options. Supported platforms: Facebook, Google Business. - [Reply to review](https://docs.zernio.com/reviews/reply-to-inbox-review.mdx) - Post a reply to a review. Requires accountId in request body. - [Activate sequence](https://docs.zernio.com/sequences/activate-sequence.mdx) - Start a draft or paused sequence. The sequence must have at least one step. - [Create sequence](https://docs.zernio.com/sequences/create-sequence.mdx) - Create a multi-step messaging sequence. Each step has a delay and a message or WhatsApp template. - [Delete sequence](https://docs.zernio.com/sequences/delete-sequence.mdx) - Permanently delete a sequence. Active enrollments are stopped. - [Enroll contacts in a sequence](https://docs.zernio.com/sequences/enroll-contacts.mdx) - Enroll one or more contacts into a sequence. Contacts already enrolled are skipped. - [Get sequence with steps](https://docs.zernio.com/sequences/get-sequence.mdx) - Returns a sequence with all its steps and enrollment stats. - [List enrollments for a sequence](https://docs.zernio.com/sequences/list-sequence-enrollments.mdx) - Returns enrolled contacts with their progress, status, and next scheduled step. - [List sequences](https://docs.zernio.com/sequences/list-sequences.mdx) - Returns sequences with enrollment stats. Filter by status, platform, or profile. - [Pause sequence](https://docs.zernio.com/sequences/pause-sequence.mdx) - Pause an active sequence. Enrolled contacts stop receiving messages until the sequence is reactivated. - [Unenroll contact](https://docs.zernio.com/sequences/unenroll-contact.mdx) - Remove a contact from a sequence. No further messages will be sent to this contact. - [Update sequence](https://docs.zernio.com/sequences/update-sequence.mdx) - Update a sequence's name, steps, or exit conditions. Steps can only be modified while the sequence is draft or paused. - [Bookmark a tweet](https://docs.zernio.com/twitter-engagement/bookmark-post.mdx) - Bookmark a tweet by ID. Requires the bookmark.write OAuth scope. Rate limit: 50 requests per 15-min window. - [Follow a user](https://docs.zernio.com/twitter-engagement/follow-user.mdx) - Follow a user on X/Twitter. Requires the follows.write OAuth scope. For protected accounts, a follow request is sent instead (pending_follow will be true). - [Remove bookmark](https://docs.zernio.com/twitter-engagement/remove-bookmark.mdx) - Remove a bookmark from a tweet. - [Retweet a post](https://docs.zernio.com/twitter-engagement/retweet-post.mdx) - Retweet (repost) a tweet by ID. Rate limit: 50 requests per 15-min window. Shares the 300/3hr creation limit with tweet creation. - [Undo retweet](https://docs.zernio.com/twitter-engagement/undo-retweet.mdx) - Undo a retweet (un-repost a tweet). - [Unfollow a user](https://docs.zernio.com/twitter-engagement/unfollow-user.mdx) - Unfollow a user on X/Twitter. - [Get plan and usage stats](https://docs.zernio.com/usage/get-usage-stats.mdx) - Returns the current plan name, billing period, plan limits, and usage counts. The response shape depends on the account's `billingSystem`: * Stripe users: per-period `usage.uploads` / `usage.profiles` counters. * Metronome (usage-based) users: `usage.connectedAccounts`, `usage.xApiCallsByOperation` (per-operation X API call counts — resolve keys via `GET /v1/billing/x-pricing`), plus a `spend` block with `currentPeriodCents`, `xSpendCents`, and `xSpendLimitCents`. The legacy `usage.xApiCalls` 3-tier aggregate is still emitted for back-compat but excludes the $0.200 URL tier and any future tiers — new clients should consume `xApiCallsByOperation` only. - [Get X/Twitter API pricing table](https://docs.zernio.com/usage/get-xapi-pricing.mdx) - Returns Zernio's canonical X/Twitter API pricing table. Each X action has its own Metronome product and its own rate, and Zernio passes X API costs through at exact rates with zero markup. The response is identical for every authenticated user (pricing is universal), so it is safe to cache on the client for the duration of a billing period. To compute your own per-operation spend, pair this endpoint with `GET /v1/usage-stats` — that endpoint returns `usage.xApiCallsByOperation` keyed by the same `operation` field you get here. - [Get user](https://docs.zernio.com/users/get-user.mdx) - Returns a single user's details by ID, including name, email, and role. - [List users](https://docs.zernio.com/users/list-users.mdx) - Returns all users in the workspace including roles and profile access. Also returns the currentUserId of the caller. - [Validate media URL](https://docs.zernio.com/validate/validate-media.mdx) - Check if a media URL is accessible and return metadata (content type, file size) plus per-platform size limit comparisons. Performs a HEAD request (with GET fallback) to detect content type and size. Rejects private/localhost URLs for SSRF protection. Platform limits are sourced from each platform's actual upload constraints. - [Validate character count](https://docs.zernio.com/validate/validate-post-length.mdx) - Check weighted character count per platform and whether the text is within each platform's limit. Twitter/X uses weighted counting (URLs = 23 chars via t.co, emojis = 2 chars). All other platforms use plain character length. Returns counts and limits for all 15 supported platform variants. - [Validate post content](https://docs.zernio.com/validate/validate-post.mdx) - Dry-run the full post validation pipeline without publishing. Catches issues like missing media for Instagram/TikTok/YouTube, hashtag limits, invalid thread formats, Facebook Reel requirements, and character limit violations. Accepts the same body as POST /v1/posts. Does NOT validate accounts, process media, or track usage. This is content-only validation. Returns errors for failures and warnings for near-limit content (>90% of character limit). - [Check subreddit existence](https://docs.zernio.com/validate/validate-subreddit.mdx) - Check if a subreddit exists and return basic info (title, subscriber count, NSFW status, post types allowed). When accountId is provided, uses authenticated Reddit OAuth API with automatic token refresh (recommended). Falls back to Reddit's public JSON API, which may be unreliable from server IPs. Returns exists: false for private, banned, or nonexistent subreddits. - [Create webhook](https://docs.zernio.com/webhooks/create-webhook-settings.mdx) - Create a new webhook configuration. Maximum 10 webhooks per user. `name`, `url` and `events` are required. `url` must be a valid URL and `events` must contain at least one event. Whitespace is trimmed from `url` before validation. Webhooks are automatically disabled after 10 consecutive delivery failures. - [Delete webhook](https://docs.zernio.com/webhooks/delete-webhook-settings.mdx) - Permanently delete a webhook configuration. - [List webhook delivery logs](https://docs.zernio.com/webhooks/get-webhook-logs.mdx) - Retrieve recorded webhook delivery attempts for the authenticated user, most recent first. Logs are retained for 30 days. Supports filtering by status, event type, webhook ID, and event ID, plus offset-based pagination. - [List webhooks](https://docs.zernio.com/webhooks/get-webhook-settings.mdx) - Retrieve all configured webhooks for the authenticated user. Supports up to 10 webhooks per user. - [Send test webhook](https://docs.zernio.com/webhooks/test-webhook.mdx) - Send a test webhook to verify your endpoint is configured correctly. The test payload includes event: "webhook.test" to distinguish it from real events. - [Update webhook](https://docs.zernio.com/webhooks/update-webhook-settings.mdx) - Update an existing webhook configuration. All fields except `_id` are optional; only provided fields will be updated. When provided, `name` must be 1-50 characters, `url` must be a valid URL, and `events` must contain at least one event. Whitespace is trimmed from `url` before validation. Webhooks are automatically disabled after 10 consecutive delivery failures. - [Activate workflow](https://docs.zernio.com/workflows/activate-workflow.mdx) - Validate the graph is runnable and set the workflow live. Once active, matching inbound messages start executions. Idempotent. - [Create workflow](https://docs.zernio.com/workflows/create-workflow.mdx) - Create a branching conversation workflow (draft) from a node/edge graph. Created in `draft` status; activate it to start matching inbound messages. The graph is validated structurally; completeness (a trigger node + reachable entry) is required at activation. - [Delete workflow](https://docs.zernio.com/workflows/delete-workflow.mdx) - Permanently delete a workflow and all of its executions. - [Duplicate a workflow](https://docs.zernio.com/workflows/duplicate-workflow.mdx) - Create an independent copy of a workflow's graph, name, description, and account binding. The copy is created in `draft` status with fresh execution counters and a new id — execution history is NOT copied. Useful for branching off a known-good workflow before making experimental edits. - [Get a specific workflow version](https://docs.zernio.com/workflows/get-workflow-version.mdx) - Returns the full snapshot for a single historical version, including the graph. - [Get workflow with graph](https://docs.zernio.com/workflows/get-workflow.mdx) - Returns a workflow including its full node/edge graph and run stats. - [Get an execution's timeline](https://docs.zernio.com/workflows/list-workflow-execution-events.mdx) - Returns the per-step run-log for a single workflow execution: trigger fired, each node visited, edge handles taken, errors, and durations. Backed by Tinybird (90-day retention). Used by the Runs UI drawer to render the timeline. - [List workflow runs](https://docs.zernio.com/workflows/list-workflow-executions.mdx) - Returns recent executions (runs) with their status, current node, and accumulated variables. - [List a workflow's version history](https://docs.zernio.com/workflows/list-workflow-versions.mdx) - Returns the snapshot history. A new version is recorded automatically before every PATCH to `nodes` / `edges` / `entryNodeId`, and explicitly when a previous version is restored. Lightweight list — call `getWorkflowVersion` for the full snapshot graph. - [List workflows](https://docs.zernio.com/workflows/list-workflows.mdx) - Returns workflows with run stats. Filter by status or profile. - [Pause workflow](https://docs.zernio.com/workflows/pause-workflow.mdx) - Stop matching new inbound messages. In-flight executions continue to completion. Idempotent. - [Restore a workflow version](https://docs.zernio.com/workflows/restore-workflow-version.mdx) - Replace the current graph with the named version's snapshot. Before the swap, the current graph is itself snapshotted as a new version, so a restore is reversible. The workflow must be in `draft` or `paused` status (same gate as a normal graph edit). The returned workflow carries `restoredFromVersion` so the UI can surface which version was rolled back to. - [Manually start a workflow run](https://docs.zernio.com/workflows/trigger-workflow.mdx) - Kick off a run without waiting for an inbound message (useful for testing). Target an existing conversation by `conversationId`, or — WhatsApp only — a phone number via `to` (a conversation is found or created). `text` seeds the run's `lastMessage` variable. The graph must be runnable. - [Update workflow](https://docs.zernio.com/workflows/update-workflow.mdx) - Update name, description, the graph, or reassign to a different account. The graph can only be modified while the workflow is draft or paused. Account swaps re-validate the graph against the new platform (so e.g. moving from WhatsApp to Facebook surfaces a `start_call` node as an error instead of silently saving an unrunnable graph). - [Add participants](https://docs.zernio.com/whatsapp/add-whatsapp-group-participants.mdx) - Add participants to a WhatsApp group. Maximum 8 participants per request. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Approve join requests](https://docs.zernio.com/whatsapp/approve-whatsapp-group-join-requests.mdx) - Approve pending join requests for a WhatsApp group. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Block users](https://docs.zernio.com/whatsapp/block-whatsapp-users.mdx) - Block one or more WhatsApp users on this number. Blocked users cannot message your number or see that you are online, and your sends to them return an error. Meta constraints, surfaced per-user in `failed` (the request itself still succeeds for the rest of the batch): - Only users who messaged your business within the last 24 hours can be blocked (failures outside the window report "Re-engagement required"). - Up to 1,000 users per request; the blocklist caps at 64,000. - Other WhatsApp Business accounts cannot be blocked. - [Check country availability](https://docs.zernio.com/whatsapp/check-whatsapp-number-availability.mdx) - Pre-purchase check, so you can warn BEFORE a customer invests in KYC (regulated review is async, 1-3 days). Tells you whether we have deliverable inventory, and what address the customer needs: - `addressConstraint: geo` → the registered address MUST be in one of the returned `areas` (the only place we have stock). A different-area address passes pre-approval but the number can never be assigned. - `addressConstraint: country` → any in-country address works. - `addressConstraint: none` → field-only / instant country, no address. Call this before starting the KYC form for regulated countries. - [Provision CTWA dataset](https://docs.zernio.com/whatsapp/create-whatsapp-dataset.mdx) - Creates (or fetches, if one already exists) the Meta dataset that Click-to-WhatsApp ad events are reported against via the Conversions API, and persists its ID on the account as `metadata.metaCapiDatasetId`. The call is GET-first idempotent — a WABA can only own one CTWA dataset, so a second call after a successful provision is a safe no-op that returns the same ID with `created: false`. Requires the connected WhatsApp account's token to carry the `whatsapp_business_manage_events` permission. If the permission is missing the endpoint returns 422 with a message asking the user to reconnect the account. - [Create flow](https://docs.zernio.com/whatsapp/create-whatsapp-flow.mdx) - Create a new WhatsApp Flow in DRAFT status. Optionally clone an existing flow. After creating, upload a Flow JSON definition, then publish to make it sendable. - [Create group](https://docs.zernio.com/whatsapp/create-whatsapp-group-chat.mdx) - Create a new WhatsApp group chat. Returns the group ID and optionally an invite link. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Create invite link](https://docs.zernio.com/whatsapp/create-whatsapp-group-invite-link.mdx) - Create a new invite link for a WhatsApp group. The previous link is revoked. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Create a hosted KYC link](https://docs.zernio.com/whatsapp/create-whatsapp-number-kyc-link.mdx) - Create a single-use, 7-day hosted KYC link that your end customer completes WITHOUT a Zernio login — useful when the person who holds the ID and address is not your team. They fill the regulated verification on a Zernio-hosted page; the number provisions under YOUR account once they submit. Only regulated (KYC) countries are valid: a country that does not require KYC returns 400. White-label the page with `branding` (your company name, logo, brand color). Supply `redirect_url` to send the end customer back to your own site after a successful submit (completion params are appended — see below). Listen for the `whatsapp.number.kyc_submitted` webhook to react when the form is completed. - [Start a sandbox activation](https://docs.zernio.com/whatsapp/create-whatsapp-sandbox-session.mdx) - Creates (or refreshes) a pending sandbox session for the given phone and immediately fires the verified sandbox template from the shared sandbox number to that phone. The session activates when the phone owner replies to that WhatsApp message — the reply itself is proof of ownership. One phone per user: if the caller already has a non-expired session for a DIFFERENT phone, the request is rejected with `invalid_field_value` (the message names the existing phone so it can be revoked first). Re-creating a session for the SAME phone is idempotent and refreshes the verification template. If Meta rejects the template send (not a WhatsApp number, paused WABA, token issue), the pending row is rolled back and the Meta error message is returned in `error` so the caller knows why. - [Create template](https://docs.zernio.com/whatsapp/create-whatsapp-template.mdx) - Create a new message template. Supports two modes: Custom template: Provide components with your own content. Submitted to Meta for review (can take up to 24h). Library template: Provide library_template_name instead of components to use a pre-built template from Meta's template library. Library templates are pre-approved (no review wait). You can optionally customize parameters and buttons via library_template_body_inputs and library_template_button_inputs. Browse available library templates at: https://business.facebook.com/wa/manage/message-templates/ - [Delete business username](https://docs.zernio.com/whatsapp/delete-whatsapp-business-username.mdx) - Release the currently claimed WhatsApp Business username from the account. After deletion the username becomes available for other accounts to claim. - [Delete flow](https://docs.zernio.com/whatsapp/delete-whatsapp-flow.mdx) - Delete a DRAFT flow. This is irreversible. Only flows in DRAFT status can be deleted. - [Delete group](https://docs.zernio.com/whatsapp/delete-whatsapp-group-chat.mdx) - Delete a WhatsApp group and remove all participants. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Revoke a sandbox session](https://docs.zernio.com/whatsapp/delete-whatsapp-sandbox-session.mdx) - Hard-deletes the session. The user loses the ability to send to that phone via the sandbox until they re-activate it. Existing conversations and messages already exchanged with that phone are untouched — revocation only blocks FUTURE sends. Sessions belonging to other users cannot be revoked; the response is the same 400 as "session not found" so existence isn't leaked. - [Delete template](https://docs.zernio.com/whatsapp/delete-whatsapp-template.mdx) - Permanently delete a message template by name. - [Deprecate flow](https://docs.zernio.com/whatsapp/deprecate-whatsapp-flow.mdx) - Deprecate a PUBLISHED flow. This is irreversible. Deprecated flows cannot be sent or opened, but existing active sessions may continue until they complete. - [Disable calling on a number](https://docs.zernio.com/whatsapp/disable-whatsapp-calling.mdx) - Disable calling. Sends calling.status=DISABLED to Meta (best-effort) and flips the local `callingEnabled` flag off. forwardTo and SIP creds are preserved so a re-enable does not lose the destination. - [Enable calling on a number](https://docs.zernio.com/whatsapp/enable-whatsapp-calling.mdx) - Enable WhatsApp Business Calling on a connected number. Configures Meta calling.status=ENABLED with our Telnyx SIP endpoint, fetches and stores the Meta-issued SIP password (encrypted), and snapshots the customer's forward-to destination. - [Check if a user is blocked](https://docs.zernio.com/whatsapp/get-whatsapp-block-status.mdx) - Definitive blocked-state lookup for a single contact. Meta exposes no membership endpoint, so this reads Zernio's blocklist mirror (kept in sync by the block/unblock endpoints; the first call per account backfills the mirror from Meta's full list). Constant-time regardless of blocklist size. - [List blocked users](https://docs.zernio.com/whatsapp/get-whatsapp-blocked-users.mdx) - List the WhatsApp users blocked on this number. Cursor-paginated; pass `nextCursor` back as `after` to fetch the next page. The blocklist holds up to 64,000 users. - [Get business profile](https://docs.zernio.com/whatsapp/get-whatsapp-business-profile.mdx) - Retrieve the WhatsApp Business profile for the account (about, address, description, email, websites, etc.). - [Get username suggestions](https://docs.zernio.com/whatsapp/get-whatsapp-business-username-suggestions.mdx) - Retrieve a list of available WhatsApp Business username suggestions based on the account's business profile name. Use these to help users discover valid, unclaimed usernames. - [Get business username](https://docs.zernio.com/whatsapp/get-whatsapp-business-username.mdx) - Fetch the current WhatsApp Business username and its approval status. Username status can be `approved` (active), `reserved` (pending activation), or `none` (no username set). - [Estimate per-minute cost](https://docs.zernio.com/whatsapp/get-whatsapp-call-estimate.mdx) - Returns a zero-markup estimated cost for an outbound call to the given destination, broken down by Meta + Telnyx + recording line items. Costs are pass-through, no margin applied. - [Check call permission](https://docs.zernio.com/whatsapp/get-whatsapp-call-permissions.mdx) - Returns the permission state and the list of available actions for a given consumer wa_id (e.g. `start_call`, `send_call_permission_request`). Use this before placing a call to decide whether to prompt for consent first. - [Get a single call](https://docs.zernio.com/whatsapp/get-whatsapp-call.mdx) - [Get calling config for an account](https://docs.zernio.com/whatsapp/get-whatsapp-calling-config.mdx) - Returns the local calling configuration snapshot for the connected WhatsApp account: whether calling is enabled, the forward-to destination URI, recording opt-in state, the WhatsAppPhoneNumber doc id (use as `{id}` on the calling-config write endpoints) and whether SIP digest credentials are stored (the encrypted password itself is never returned). - [Get CTWA conversions dataset](https://docs.zernio.com/whatsapp/get-whatsapp-dataset.mdx) - Returns the Meta Click-to-WhatsApp conversions dataset currently linked to the WhatsApp account, if one has been provisioned. Reads only from the stored `metadata.metaCapiDatasetId` — never hits Meta, never creates a dataset. Use this to detect whether `POST /v1/whatsapp/conversions` is configured for an account. - [Get display name status](https://docs.zernio.com/whatsapp/get-whatsapp-display-name.mdx) - Fetch the current display name and its Meta review status for a WhatsApp Business account. Display name changes require Meta approval and can take 1-3 business days. - [Get flow JSON asset](https://docs.zernio.com/whatsapp/get-whatsapp-flow-json.mdx) - Get the flow JSON asset metadata, including a temporary download URL for the Flow JSON file. - [Get flow preview URL](https://docs.zernio.com/whatsapp/get-whatsapp-flow-preview.mdx) - Get Meta's public web-preview URL for a flow (drafts included), embeddable as an interactive iframe. The link is reused across calls (valid ~30 days); pass invalidate=true to mint a fresh one (the previous link stops working). - [Get flow](https://docs.zernio.com/whatsapp/get-whatsapp-flow.mdx) - Get details for a specific flow, including status, categories, validation errors, and preview URL. - [Get group info](https://docs.zernio.com/whatsapp/get-whatsapp-group-chat.mdx) - Retrieve metadata about a WhatsApp group including subject, description, participants, and settings. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Look up a library template](https://docs.zernio.com/whatsapp/get-whatsapp-library-template.mdx) - Look up a single pre-approved Template Library template by its exact name, to introspect its structure before importing it. Most importantly it returns the template's `buttons`: a library template with `URL` / `PHONE_NUMBER` buttons must be created with a matching `library_template_button_inputs` array (see Create Template), or Meta rejects it. Use this to discover which inputs to collect. - [Get number status](https://docs.zernio.com/whatsapp/get-whatsapp-number-info.mdx) - Live snapshot of a connected number straight from Meta: the phone-number node (display number, display name + approval, quality rating, messaging-limit tier, throughput, official-business badge, connection status, health_status) and its owning WhatsApp Business Account (name, business verification, timezone, health_status). Fetched live because Meta updates quality/tier/name/health over time; the call also refreshes the cached values shown on the connection card. - [Get KYC form spec](https://docs.zernio.com/whatsapp/get-whatsapp-number-kyc-form.mdx) - For a Tier 3/4 country, the fields the end customer must provide (Telnyx regulatory requirements) before a number can be ordered: text, date, address, or file (document) per requirement. - [Get declined requirements](https://docs.zernio.com/whatsapp/get-whatsapp-number-remediation.mdx) - For a number in `regulatory_declined`, returns ONLY the requirements the reviewer flagged declined, as a form spec (same shape as the KYC form GET). The customer fixes just those — Telnyx supports correcting a declined requirement group and re-submitting it (no new number/group). Falls back to the full spec if the provider exposes no per-requirement flags. - [Get phone number](https://docs.zernio.com/whatsapp/get-whatsapp-phone-number.mdx) - Retrieve the current status of a purchased phone number. Poll this to track Meta pre-verification (US sync path) and, for regulated (Tier 3/4) numbers, the async lifecycle: pending_regulatory → active (or regulatory_declined). When a regulated number has an Onfido ID step, `onfidoVerificationUrl` appears here once the order is placed — forward it to the end user. (Or subscribe to the whatsapp.number.* webhooks instead of polling.) - [List phone numbers](https://docs.zernio.com/whatsapp/get-whatsapp-phone-numbers.mdx) - List all WhatsApp phone numbers purchased by the authenticated user. By default, released numbers are excluded. Connected (bring-your-own) numbers are returned in the separate `connected` array — they are not billed and have no provisioning lifecycle. - [Get template](https://docs.zernio.com/whatsapp/get-whatsapp-template.mdx) - Retrieve a single message template by name. - [List templates](https://docs.zernio.com/whatsapp/get-whatsapp-templates.mdx) - List all message templates for the WhatsApp Business Account (WABA) associated with the given account. Templates are fetched directly from the WhatsApp Cloud API. - [Initiate outbound call](https://docs.zernio.com/whatsapp/initiate-whatsapp-call.mdx) - Initiates an outbound Business-Initiated Call. The Telnyx-side SIP leg is originated server-side (Option B: SIP-first). Telnyx INVITEs Meta directly over TLS:5061 with the SIP digest credentials we captured at calling-enablement time). No client-side SDP is required; pass only `accountId` and `to`. To send the consumer the call-consent prompt instead of placing a call, pass `action: "send_call_permission_request"` (+ optional `bodyText`). The consumer must tap Allow in WhatsApp before `start_call` is permitted; Meta limits the prompt to 1 per consumer per 24h (2 per 7 days) and requires an open 24h service window. - [List call history for an account](https://docs.zernio.com/whatsapp/list-whatsapp-calls.mdx) - Compact history listing for a single connected account. Results are scoped to the resolved SocialAccount; profile-scoped team members cannot read calls on sibling accounts. - [List conversion events](https://docs.zernio.com/whatsapp/list-whatsapp-conversions.mdx) - Returns the most recent conversion events sent through `POST /v1/whatsapp/conversions` for the given WhatsApp account. Sourced from delivery logs (Axiom `late` dataset), so the visible window is bounded by log retention (about 30 days). Useful for rendering a "recent activity" panel on the conversions setup tab without standing up a parallel persistence layer. Per-event payload mirrors the structured log we write on every successful send: `eventName`, `conversationId`, `eventsReceived`, `eventsFailed`, `traceId`, `durationMs`, and the wall-clock `timestamp`. - [List flow responses](https://docs.zernio.com/whatsapp/list-whatsapp-flow-responses.mdx) - List the responses customers submitted when completing a flow (parsed from the nfm_reply messages received via webhook), newest first. Scope to a single flow with `flowId` — this matches responses whose flow_token carries the `:` prefix that Zernio stamps on auto-generated tokens at send time. Responses sent with a custom integrator-supplied flow_token are not attributed to a flow. - [List flow versions](https://docs.zernio.com/whatsapp/list-whatsapp-flow-versions.mdx) - List the flow's version history (the clone lineage Zernio tracks, since Meta has no native versioning), newest version first. Each entry is enriched with the version's live name and status from Meta. A flow with no lineage returns just itself as version 1. - [List flows](https://docs.zernio.com/whatsapp/list-whatsapp-flows.mdx) - List all WhatsApp Flows for the Business Account (WABA) associated with the given account. - [List active groups](https://docs.zernio.com/whatsapp/list-whatsapp-group-chats.mdx) - List active WhatsApp group chats for a business phone number. These are actual WhatsApp group conversations on the platform. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [List join requests](https://docs.zernio.com/whatsapp/list-whatsapp-group-join-requests.mdx) - List pending join requests for a WhatsApp group (only for groups with approval_required mode). Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [List offerable number countries](https://docs.zernio.com/whatsapp/list-whatsapp-number-countries.mdx) - The WhatsApp number countries available to purchase, each with its flat monthly price (cents), regulatory tier, whether it needs end-user KYC (Tier 3/4), and whether outbound calling is available (not BIC-blocked). Drives the country picker. Tier-4 countries appear only when enabled. - [List your sandbox sessions](https://docs.zernio.com/whatsapp/list-whatsapp-sandbox-sessions.mdx) - Returns all of the authenticated user's non-expired sandbox sessions (pending + active) plus the sandbox phone number. In practice there is at most one session per user since the sandbox is one-phone-per-user; the array shape is preserved for forward compatibility. - [Publish flow](https://docs.zernio.com/whatsapp/publish-whatsapp-flow.mdx) - Publish a DRAFT flow. This is irreversible. Once published, the flow and its JSON become immutable and the flow can be sent to users. To update a published flow, create a new flow (optionally cloning this one via cloneFlowId). - [Purchase phone number](https://docs.zernio.com/whatsapp/purchase-whatsapp-phone-number.mdx) - Initiate purchasing a WhatsApp phone number. Payment-first flow: the user does not pick a specific number. The system either creates a Stripe Checkout Session (first number) or increments the existing subscription quantity and provisions inline (subsequent numbers). Requires a paid plan. The maximum number of phone numbers is determined by the user's plan. - [Reject join requests](https://docs.zernio.com/whatsapp/reject-whatsapp-group-join-requests.mdx) - Reject pending join requests for a WhatsApp group. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Release phone number](https://docs.zernio.com/whatsapp/release-whatsapp-phone-number.mdx) - Release a purchased phone number. This will: 1. Disconnect any linked WhatsApp social account 2. Decrement the Stripe subscription quantity (or cancel if last number) 3. Release the number from Telnyx 4. Mark the number as released - [Resubmit a declined number](https://docs.zernio.com/whatsapp/remediate-whatsapp-number.mdx) - Submit corrected values/documents for the declined requirement(s). We PATCH them onto the SAME requirement group and re-submit it for approval; the number goes `regulatory_declined` → `pending_regulatory`. No new number and no new billing. Body shape matches the KYC submit (values / documents / address) — send only the corrected fields. - [Remove participants](https://docs.zernio.com/whatsapp/remove-whatsapp-group-participants.mdx) - Remove participants from a WhatsApp group. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Search available numbers](https://docs.zernio.com/whatsapp/search-available-whatsapp-numbers.mdx) - Search the provider's inventory for numbers available to purchase in a country (default US). Optional filters narrow the results. The country must be offerable (see GET /v1/whatsapp/phone-numbers/countries). - [Send WhatsApp conversion event](https://docs.zernio.com/whatsapp/send-whatsapp-conversion.mdx) - Forward a WhatsApp Business Messaging conversion event (`LeadSubmitted`, `Purchase`, `AddToCart`, `InitiateCheckout`, `ViewContent`) to Meta's Conversions API with `action_source = business_messaging` and `messaging_channel = whatsapp`. The endpoint looks up the originating CTWA click ID (`ctwa_clid`) captured on the first inbound message of the conversation and replays it on every event so Meta can attribute the conversion back to the Click-to-WhatsApp ad that drove the chat. Configuration prerequisite on the WhatsApp account metadata: - `metaCapiDatasetId`: the Meta dataset ID linked to the WABA. Provision one with `POST /v1/whatsapp/dataset`. The WABA ID (already set automatically at connect time) is forwarded as `user_data.whatsapp_business_account_id`, which is the per-channel attribution identifier Meta requires for WhatsApp events. No Facebook Page ID is needed (that field is the Messenger-branch identifier). Identify the conversation by either `conversationId` (preferred) or `phoneE164` (digits only, no `+`). At least one is required. If the conversation has no captured `ctwa_clid`, the request returns 422 because there is nothing to attribute. Token and dataset coupling: the WhatsApp account's accessToken must have access to the configured `metaCapiDatasetId`. By default a WABA's system-user token is scoped to the WABA's own Business Manager and cannot post to a pixel owned by a different Business; Meta returns code 100 in that case. Either share the dataset with the WhatsApp app's Business in BM, or use a dataset already in the same Business as the WABA. - [Send flow message](https://docs.zernio.com/whatsapp/send-whatsapp-flow-message.mdx) - Send a published flow as an interactive message with a CTA button. When the recipient taps the button, the flow opens natively in WhatsApp. Flow responses are received via webhooks. - [Set business username](https://docs.zernio.com/whatsapp/set-whatsapp-business-username.mdx) - Claim or transfer a WhatsApp Business username for the account. Username rules: 3-35 characters, letters/digits/period/underscore only, must contain at least one letter, no leading or trailing periods, no consecutive periods, no `www` prefix, no domain TLD suffix (e.g. `.com`). If the desired username is currently held by another account, pass `transferAction: "force_transfer"` to request a transfer. On failure the API returns a standard error envelope with one of these codes: `whatsapp_username_unavailable` (already taken and transfer not requested), `whatsapp_username_ineligible` (account not eligible to claim a username), or `whatsapp_username_transfer_required` (username is held elsewhere; retry with `force_transfer`). - [Submit KYC](https://docs.zernio.com/whatsapp/submit-whatsapp-number-kyc.mdx) - Submit the end customer's KYC (textual values, uploaded documents, address) for a Tier 3/4 country. Documents are streamed straight to the number provider and are not stored by Zernio. Builds + submits a regulatory requirement group and claims a pending_regulatory slot; the number is ordered + activated once the provider approves (asynchronous). A customer may hold several same-country numbers in review at once; a double-submit of the SAME attempt is deduped via `submissionId`. For an ID-card document requirement, carriers commonly require BOTH sides: combine the front and back into a single file before uploading (the dashboard does this automatically). A one-sided ID is a common decline reason; fix it via POST /v1/whatsapp/phone-numbers/{id}/remediate. Before submitting, call GET /v1/whatsapp/phone-numbers/availability to check the country has deliverable inventory and, for geographic-match countries, which area the address must be in — otherwise the submission can pass review yet never be assignable a number. - [Unblock users](https://docs.zernio.com/whatsapp/unblock-whatsapp-users.mdx) - Unblock one or more previously blocked WhatsApp users on this number. Up to 1,000 users per request; per-user failures are reported in `failed` without failing the rest of the batch. - [Update business profile](https://docs.zernio.com/whatsapp/update-whatsapp-business-profile.mdx) - Update the WhatsApp Business profile. All fields are optional; only provided fields will be updated. Constraints: about max 139 chars, description max 512 chars, max 2 websites. - [Update calling config](https://docs.zernio.com/whatsapp/update-whatsapp-calling.mdx) - Update fields on an already-enabled number. Only fields present in the body are written; `undefined` leaves the stored value alone, explicit `null` clears a nullable field. No Meta side effect, this only changes local routing state consumed by the Telnyx webhook handler. - [Request display name change](https://docs.zernio.com/whatsapp/update-whatsapp-display-name.mdx) - Submit a display name change request for the WhatsApp Business account. The new name must follow WhatsApp naming guidelines (3-512 characters, must represent your business). Changes require Meta review and approval, which typically takes 1-3 business days. - [Update flow](https://docs.zernio.com/whatsapp/update-whatsapp-flow.mdx) - Update metadata (name, categories) of a DRAFT flow. Published flows are immutable. - [Update group settings](https://docs.zernio.com/whatsapp/update-whatsapp-group-chat.mdx) - Update the subject, description, or join approval mode of a WhatsApp group. Not available on [Coexistence](/platforms/whatsapp/connection#whatsapp-business-app-coexistence) numbers. Requires a Cloud API-only number. - [Update template](https://docs.zernio.com/whatsapp/update-whatsapp-template.mdx) - Update a message template's components. Only certain fields can be updated depending on the template's current approval state. Approved templates can only have components updated. - [Upload flow JSON](https://docs.zernio.com/whatsapp/upload-whatsapp-flow-json.mdx) - Upload or update the Flow JSON for a DRAFT flow. The Flow JSON defines all screens, components (text inputs, dropdowns, date pickers, etc.), and navigation. Meta validates the JSON on upload and returns any validation errors. See: https://developers.facebook.com/docs/whatsapp/flows/reference/flowjson - [Upload a KYC document](https://docs.zernio.com/whatsapp/upload-whatsapp-number-kyc-document.mdx) - Upload ONE document and get back its provider document id, to reference from POST /v1/whatsapp/phone-numbers/kyc via `documents[].documentId`. Send the RAW file bytes as the request body (not base64); put the filename in the `X-Filename` header. Uploading documents one-per-request keeps each request under the ~4.5MB body limit. The document streams straight to the number provider and is not stored by Zernio. - [Upload profile picture](https://docs.zernio.com/whatsapp/upload-whatsapp-profile-photo.mdx) - Upload a new profile picture for the WhatsApp Business Profile. Uses Meta's resumable upload API under the hood: creates an upload session, uploads the image bytes, then updates the business profile with the resulting handle. - [Pre-validate KYC address](https://docs.zernio.com/whatsapp/validate-whatsapp-number-kyc-address.mdx) - Optional early check for the address step of a Tier 4 (end-user identity) registration: validates a postal address for deliverability BEFORE the full KYC submit, so it can be corrected before any documents are uploaded. The full submit (POST /v1/whatsapp/phone-numbers/kyc) re-validates the address, so this call is purely a fast feedback path and skipping it is safe. Only the postal address is sent (no documents, no gov-ID fields). A region (`administrative_area`) is required by the validator; when it is omitted the pre-check is skipped and `{ ok: true, skipped: true }` is returned (the final submit still validates). - [Connecting Accounts](https://docs.zernio.com/guides/connecting-accounts.mdx) - How to connect social media accounts using OAuth flows, headless mode, and non-OAuth platforms - [Error Handling](https://docs.zernio.com/guides/error-handling.mdx) - Error envelope, stable codes, and HTTP status codes returned by the Zernio API - [Media Uploads](https://docs.zernio.com/guides/media-uploads.mdx) - How to upload images, videos, and documents for use in posts - [Platform Settings](https://docs.zernio.com/guides/platform-settings.mdx) - Configure Twitter threads, Instagram Stories, TikTok privacy, YouTube visibility, and LinkedIn settings when posting via the Zernio API. - [Queue Scheduling](https://docs.zernio.com/guides/queue-scheduling.mdx) - Drip-feed posts automatically using profile queues instead of computing schedule times yourself - [Rate Limits](https://docs.zernio.com/guides/rate-limits.mdx) - API rate limits by plan, posting velocity limits, and how to handle throttling - [Analytics](https://docs.zernio.com/platforms/google-business/analytics.mdx) - Google Business performance and search keyword analytics - [Business Profile Management](https://docs.zernio.com/platforms/google-business/business-profile.mdx) - Manage location details, attributes, services, menus, media, reviews, and verifications - [Event & Offer Posts](https://docs.zernio.com/platforms/google-business/events-offers.mdx) - Create event and offer posts via topicType - [Inbox](https://docs.zernio.com/platforms/google-business/inbox.mdx) - Reviews and Q&A in the inbox - [Google Business](https://docs.zernio.com/platforms/google-business.mdx) - Schedule and automate Google Business Profile posts with Zernio API - [Multi-Location Posting](https://docs.zernio.com/platforms/google-business/multi-location.mdx) - Post to many business locations at once - [Posts & Content Types](https://docs.zernio.com/platforms/google-business/posts.mdx) - Create updates, offers, CTAs, and other Google Business post types - [Media & Limits](https://docs.zernio.com/platforms/google-business/reference.mdx) - Media requirements, platform-specific fields, and common errors - [Ad Comments](https://docs.zernio.com/platforms/meta-ads/ad-comments.mdx) - Read and manage comments on your Meta ads - [Custom Audiences](https://docs.zernio.com/platforms/meta-ads/audiences.mdx) - Build custom and lookalike audiences - [Boost a Post](https://docs.zernio.com/platforms/meta-ads/boost.mdx) - Turn an existing organic post into a paid ad - [Campaigns & Ad Sets](https://docs.zernio.com/platforms/meta-ads/campaigns.mdx) - Create standalone campaigns and manage campaigns, ad sets, and budgets - [Conversions API](https://docs.zernio.com/platforms/meta-ads/capi.mdx) - Send server-side conversion events to Meta - [Catalog Ads](https://docs.zernio.com/platforms/meta-ads/catalog-ads.mdx) - Advantage+ catalog ads — dynamic product and vehicle ads from a Meta product catalog - [Conversion Campaigns](https://docs.zernio.com/platforms/meta-ads/conversion-campaigns.mdx) - Conversion campaigns and promoted objects - [Creative Testing](https://docs.zernio.com/platforms/meta-ads/creative-testing.mdx) - Run multi-creative campaigns to test variations - [Creatives](https://docs.zernio.com/platforms/meta-ads/creatives.mdx) - Attach creatives, video creatives, and placement asset customization - [Click-to-WhatsApp Ads](https://docs.zernio.com/platforms/meta-ads/ctwa.mdx) - Create ads that open a WhatsApp conversation - [Meta Ads](https://docs.zernio.com/platforms/meta-ads.mdx) - Create and boost Facebook + Instagram ads via Zernio API - [Lead Gen Forms](https://docs.zernio.com/platforms/meta-ads/lead-forms.mdx) - Create and manage Meta lead generation forms - [Meta Pixels](https://docs.zernio.com/platforms/meta-ads/pixels.mdx) - Create and manage Meta Pixels - [Media Requirements](https://docs.zernio.com/platforms/meta-ads/reference.mdx) - Image and video requirements for Meta ads - [Targeting](https://docs.zernio.com/platforms/meta-ads/targeting.mdx) - Interest, demographic, and behavior targeting - [Ad URL Tracking Tags](https://docs.zernio.com/platforms/meta-ads/tracking-tags.mdx) - Attach click-URL tracking parameters to ads - [Analytics & Engagement](https://docs.zernio.com/platforms/twitter/analytics-engagement.mdx) - Tweet analytics and engagement actions - [Fields, Geo & Polls](https://docs.zernio.com/platforms/twitter/fields-polls.mdx) - Platform-specific fields, geo-restriction, polls, and media URL requirements - [Inbox](https://docs.zernio.com/platforms/twitter/inbox.mdx) - Direct messages in the inbox - [Twitter/X](https://docs.zernio.com/platforms/twitter.mdx) - Schedule and automate Twitter/X posts with Zernio API - [Media & Video](https://docs.zernio.com/platforms/twitter/media.mdx) - Media requirements and long video uploads (Premium) - [Posts & Editing](https://docs.zernio.com/platforms/twitter/posts.mdx) - Create tweets, threads, and edit published tweets - [Limits & Errors](https://docs.zernio.com/platforms/twitter/reference.mdx) - What you cannot do and common errors - [Replies & Quotes](https://docs.zernio.com/platforms/twitter/replies-quotes.mdx) - Reply tweets and quote reposts - [Broadcasts](https://docs.zernio.com/platforms/whatsapp/broadcasts.mdx) - Send WhatsApp template messages to many recipients with per-recipient variables and scheduling - [Calling](https://docs.zernio.com/platforms/whatsapp/calling.mdx) - Inbound and outbound WhatsApp voice calling - [Connection & Setup](https://docs.zernio.com/platforms/whatsapp/connection.mdx) - Connect a WhatsApp Business Account via redirect flow, headless credentials, or the dashboard - [Contacts & Profile](https://docs.zernio.com/platforms/whatsapp/contacts.mdx) - Manage your WhatsApp contact list and business profile - [Click-to-WhatsApp Ads](https://docs.zernio.com/platforms/whatsapp/ctwa.mdx) - Capture CTWA clicks and forward conversion events to Meta for attribution - [Flows](https://docs.zernio.com/platforms/whatsapp/flows.mdx) - Build interactive WhatsApp Flows: forms, surveys, and booking experiences - [Group Chats](https://docs.zernio.com/platforms/whatsapp/groups.mdx) - Create and manage WhatsApp group chats, participants, and invite links - [Inbox](https://docs.zernio.com/platforms/whatsapp/inbox.mdx) - Receive and reply to WhatsApp direct messages - [WhatsApp](https://docs.zernio.com/platforms/whatsapp.mdx) - Send WhatsApp broadcasts, manage templates, contacts, and conversations with Zernio API - [Phone Numbers](https://docs.zernio.com/platforms/whatsapp/phone-numbers.mdx) - Purchase, verify, KYC, and release WhatsApp phone numbers for your WABA - [Pricing & Costs](https://docs.zernio.com/platforms/whatsapp/pricing.mdx) - What Zernio and Meta each charge for WhatsApp - [Media & Limits](https://docs.zernio.com/platforms/whatsapp/reference.mdx) - Media requirements, analytics support, and common errors - [Sandbox](https://docs.zernio.com/platforms/whatsapp/sandbox.mdx) - Test WhatsApp sending against a sandbox number before going to production - [Templates](https://docs.zernio.com/platforms/whatsapp/templates.mdx) - Create, list, and import Meta-approved WhatsApp message templates - [Chat SDK](https://docs.zernio.com/resources/integrations/chat-sdk.mdx) - Build chatbots that work across Instagram, Facebook, Telegram, WhatsApp, Twitter/X, Bluesky, and Reddit through a single Chat SDK adapter. - [Integrations](https://docs.zernio.com/resources/integrations.mdx) - Automate social media posting via n8n, Make.com, Zapier, or OpenClaw. Schedule and cross-post to Twitter, Instagram, LinkedIn, TikTok & 10 more. - [Make](https://docs.zernio.com/resources/integrations/make.mdx) - Native Make.com app for social media automation. 20+ modules for Twitter, Instagram, LinkedIn, TikTok, YouTube, Pinterest, Reels & Stories. - [n8n](https://docs.zernio.com/resources/integrations/n8n.mdx) - Verified n8n node for social media automation. Post to Twitter, Instagram, LinkedIn, TikTok & more with scheduling, media uploads, webhooks, and cross-posting. - [OpenClaw](https://docs.zernio.com/resources/integrations/openclaw.mdx) - ClawHub skill for social media automation via natural language. Post to Twitter, Instagram, LinkedIn & 11 more platforms. Scheduling, cross-posting & analytics. - [Zapier](https://docs.zernio.com/resources/integrations/zapier.mdx) - Native Zapier app for social media automation. Trigger posts from Google Sheets, Notion, RSS, Ghost & 7,000+ apps. Scheduling, Reels, Stories & Pinterest. - [Migrate from Ayrshare](https://docs.zernio.com/resources/migrations/migrating-from-ayrshare.mdx) - Step-by-step guide to migrate from Ayrshare to Zernio API ## Full Documentation For the complete documentation in a single file, see: https://docs.zernio.com/llms-full.txt