Skip to content

Platform Settings

Configure Twitter threads, Instagram Stories, TikTok privacy, YouTube visibility, and LinkedIn settings when posting via the Zernio API.

When creating posts, you can provide platform-specific settings in the platformSpecificData field of each PlatformTarget. This allows you to customize how your content appears and behaves on each social network.

Twitter/X

Create multi-tweet threads with Twitter's threadItems array.

PropertyTypeDescription
threadItemsarraySequence of tweets in a thread. First item is the root tweet.
threadItems[].contentstringTweet text content
threadItems[].mediaItemsarrayMedia attachments for this tweet
geoRestrictionobjectRestrict media visibility to specific countries. Only applies when media is attached (ignored for text-only tweets). The tweet text remains visible globally.
geoRestriction.countriesstring[]Uppercase ISO 3166-1 alpha-2 codes, max 25. Example: ["US", "ES"]
json
{
  "threadItems": [
    { "content": "🧵 Here's everything you need to know about our API..." },
    { "content": "1/ First, authentication is simple..." },
    { "content": "2/ Next, create your first post..." }
  ]
}

Threads (by Meta)

Similar to Twitter, create multi-post threads on Threads.

PropertyTypeDescription
threadItemsarraySequence of posts (root then replies in order)
threadItems[].contentstringPost text content
threadItems[].mediaItemsarrayMedia attachments for this post

Facebook

PropertyTypeDescription
contentType"story"Publish as a Facebook Page Story (24-hour ephemeral)
firstCommentstringAuto-post a first comment (feed posts only, not stories)
pageIdstringTarget Page ID for multi-page posting. Use GET /v1/accounts/{id}/facebook-page to list available pages. Uses default page if omitted.
geoRestrictionobjectRestrict post visibility to specific countries (hard restriction). geoRestriction.countries: array of uppercase ISO 3166-1 alpha-2 codes, max 25. Not supported for stories.

Constraints:

  • ❌ Cannot mix videos and images in the same post
  • ✅ Up to 10 images for feed posts
  • ✅ Stories require media (single image or video)
  • ⚠️ Story text captions are not displayed
  • ⏱️ Stories disappear after 24 hours
  • 📄 Use pageId to post to multiple Facebook Pages from the same account connection
json
{
  "contentType": "story",
  "pageId": "123456789"
}

Instagram

PropertyTypeDescription
contentType"story"Publish as an Instagram Story
shareToFeedbooleanFor Reels only. When true (default), the Reel appears on both the Reels tab and profile feed. Set to false for Reels tab only.
collaboratorsstring[]Up to 3 usernames to invite as collaborators (feed/Reels only)
firstCommentstringAuto-post a first comment (not applied to Stories)
trialParamsobjectTrial Reels configuration (Reels only). Trial Reels are initially shared only with non-followers.
trialParams.graduationStrategy"MANUAL" | "SS_PERFORMANCE"MANUAL: graduate via Instagram app. SS_PERFORMANCE: auto-graduate based on performance.
userTagsarrayTag Instagram users in photos by username and position coordinates (not supported for stories or videos). For carousels, use mediaIndex to tag specific slides (defaults to 0).
userTags[].usernamestringInstagram username (@ symbol optional, auto-removed)
userTags[].xnumberX coordinate from left edge (0.0–1.0)
userTags[].ynumberY coordinate from top edge (0.0–1.0)
userTags[].mediaIndexintegerZero-based carousel slide index to tag (defaults to 0). Tags targeting video items or out-of-range indices are ignored.
audioNamestringCustom name for the original audio in Reels. Replaces the default "Original Audio" label. Only applies to Reels (video posts). Can only be set once - either during creation or later from the Instagram audio page in the app.
thumbOffsetintegerMillisecond offset from the start of the video to use as the Reel thumbnail. Only applies to Reels. If a custom thumbnail URL (instagramThumbnail in mediaItems) is provided, it takes priority. Defaults to 0 (first frame).

Constraints:

  • 📐 Feed posts require aspect ratio between 0.8 (4:5) and 1.91 (1.91:1)
  • 📱 9:16 images must use contentType: "story"
  • 🎠 Carousels support up to 10 media items
  • 🗜️ Images > 8MB auto-compressed
  • 📹 Story videos > 100MB auto-compressed
  • 🎬 Reel videos > 300MB auto-compressed
  • 🏷️ User tags: supported on images only (not stories/videos); for carousels, use userTags[].mediaIndex to tag specific slides (defaults to 0)
json
{
  "firstComment": "Link in bio! 🔗",
  "collaborators": ["brandpartner", "creator123"],
  "userTags": [
    { "username": "friend_username", "x": 0.5, "y": 0.5 }
  ]
}

LinkedIn

PropertyTypeDescription
organizationUrnstringTarget LinkedIn Organization URN for multi-organization posting. Format: urn:li:organization:123456789. Use GET /v1/accounts/{id}/linkedin-organizations to list available organizations. Uses default organization if omitted.
firstCommentstringAuto-post a first comment
disableLinkPreviewbooleanSet true to disable URL previews (default: false)
geoRestrictionobjectRestrict post visibility to specific countries (hard restriction). Organization pages only, requires 300+ targeted followers.
geoRestriction.countriesstring[]Uppercase ISO 3166-1 alpha-2 codes, max 25. Example: ["US", "ES"]

Constraints:

  • ✅ Up to 20 images per post
  • ❌ Multi-video posts not supported
  • 📄 Single PDF document posts supported
  • 🔗 Link previews auto-generated when no media attached
  • 🏢 Use organizationUrn to post to multiple organizations from the same account connection
json
{
  "firstComment": "What do you think? Drop a comment below! 👇",
  "disableLinkPreview": false
}

Reddit

PropertyTypeDescription
subredditstringTarget subreddit name (without "r/" prefix). Overrides the default subreddit configured on the account connection.
titlestringPost title (max 300 chars). Defaults to the first line of content, truncated to 300 characters.
urlstring (URI)URL for link posts. If provided (and forceSelf is not true), creates a link post instead of a text post.
forceSelfbooleanWhen true, creates a text/self post even when a URL or media is provided.
flairIdstringFlair ID for the post (required by some subreddits). Use GET /v1/accounts/{id}/reddit-flairs?subreddit=name to list available flairs.
nativeVideobooleanDefaults to true for video media items (uploads to Reddit's CDN, renders as embedded player). Set false to post as a plain link instead. Subreddits that block videos fall back automatically.
videogifbooleanWhen true, submit the native video as a silent looping videogif.
videoPosterUrlstring (URI)Custom poster/thumbnail. If omitted, Zernio auto-extracts the video's first frame.

Pinterest

PropertyTypeDescription
titlestringPin title (max 100 chars, defaults to first line of content)
boardIdstringTarget board ID (uses first available if omitted)
linkstring (URI)Destination link for the pin
coverImageUrlstring (URI)Cover image for video pins
coverImageKeyFrameTimeintegerKey frame time in seconds for video cover
json
{
  "title": "10 Tips for Better Photography",
  "boardId": "board-123",
  "link": "https://example.com/photography-tips"
}

YouTube

PropertyTypeDescription
titlestringVideo title (max 100 chars, defaults to first line of content)
visibility"public" | "private" | "unlisted"Video visibility (default: public)
madeForKidsbooleanCOPPA compliance: Set to true if video is made for kids (child-directed content). Defaults to false. Videos marked as made for kids have restricted features (no comments, no notifications, limited ad targeting).
firstCommentstringAuto-post a first comment (max 10,000 chars)
tagsstring[]Tags/keywords for the video (see constraints below)
containsSyntheticMediabooleanAI-generated content disclosure flag. Set to true if your video contains AI-generated or synthetic content that could be mistaken for real people, places, or events. This helps viewers understand when realistic content has been created or altered using AI. YouTube may add a label to videos when this is set. Added to YouTube Data API in October 2024.
categoryIdstringYouTube video category ID. Defaults to "22" (People & Blogs). Common categories: "1" (Film & Animation), "2" (Autos & Vehicles), "10" (Music), "15" (Pets & Animals), "17" (Sports), "20" (Gaming), "22" (People & Blogs), "23" (Comedy), "24" (Entertainment), "25" (News & Politics), "26" (Howto & Style), "27" (Education), "28" (Science & Technology).

Tag Constraints:

  • ✅ No count limit; duplicates are automatically removed
  • 📏 Each tag must be ≤ 100 characters
  • 📊 Combined total across all tags ≤ 500 characters (YouTube's limit)

Automatic Detection:

  • ⏱️ Videos ≤ 3 minutes → YouTube Shorts
  • 🎬 Videos > 3 minutes → Regular videos
  • 🖼️ Custom thumbnails supported for regular videos only
  • ❌ Custom thumbnails NOT supported for Shorts via API
  • 👶 madeForKids defaults to false (not child-directed)
json
{
  "title": "How to Use Our API in 5 Minutes",
  "visibility": "public",
  "madeForKids": false,
  "firstComment": "Thanks for watching! 🙏 Subscribe for more tutorials!"
}

TikTok

> ⚠️ Required Consent: TikTok posts will fail without content_preview_confirmed: true and express_consent_given: true.

TikTok settings are nested inside platformSpecificData.tiktokSettings:

PropertyTypeDescription
privacy_levelstringRequired. Must be one from your account's available options
allow_commentbooleanRequired. Allow comments on the post
allow_duetbooleanRequired for video posts
allow_stitchbooleanRequired for video posts
content_preview_confirmedbooleanRequired. Must be true
express_consent_givenbooleanRequired. Must be true
draftbooleanSend to Creator Inbox as draft instead of publishing
descriptionstringLong-form description for photo posts (max 4000 chars)
video_cover_timestamp_msintegerThumbnail frame timestamp in ms (default: 1000)
photo_cover_indexintegerCover image index for carousels (0-based, default: 0)
auto_add_musicbooleanLet TikTok add recommended music (photos only)
video_made_with_aibooleanDisclose AI-generated content
commercial_content_type"none" | "brand_organic" | "brand_content"Commercial disclosure
brand_partner_promotebooleanBrand partner promotion flag
is_brand_organic_postbooleanBrand organic post flag
media_type"video" | "photo"Optional override (defaults based on media items)

Constraints:

  • 📸 Photo carousels support up to 35 images
  • 📝 Video titles: up to 2200 characters
  • 📝 Photo titles: auto-truncated to 90 chars (use description for longer text)
  • 🔒 privacy_level must match your account's available options (no defaults)
json
{
  "accountId": "tiktok-012",
  "platformSpecificData": {
    "tiktokSettings": {
      "privacy_level": "PUBLIC_TO_EVERYONE",
      "allow_comment": true,
      "allow_duet": true,
      "allow_stitch": true,
      "content_preview_confirmed": true,
      "express_consent_given": true,
      "description": "Full description here since photo titles are limited to 90 chars..."
    }
  }
}

Google Business Profile

PropertyTypeDescription
topicType"STANDARD" | "EVENT" | "OFFER"Post type. Defaults to STANDARD if omitted. EVENT requires the event object. OFFER requires offer and optionally event for the offer period.
eventobjectEvent details. Required for EVENT, optional for OFFER. See schedule format below.
event.titlestringEvent or offer title displayed on Google Search and Maps
event.scheduleobjectDate/time range. Contains startDate, startTime, endDate, endTime. Each date field accepts { year, month, day } or an ISO 8601 string (e.g., "2026-05-15T09:00:00Z"). Time fields accept { hours, minutes } or an ISO string.
offerobjectOffer details for OFFER posts. All sub-fields optional.
offer.couponCodestringPromo/coupon code
offer.redeemOnlineUrlstring (URI)URL where the offer can be redeemed online
offer.termsConditionsstringTerms and conditions text
locationIdstringTarget Google Business location ID for multi-location posting. Format: locations/123456789. Use GET /v1/accounts/{id}/gmb-locations to list available locations. Uses default location if omitted.
languageCodestringBCP 47 language code for the post content (e.g., en, de, es, fr). If omitted, language is auto-detected from the post text.
callToAction.typeenumLEARN_MORE, BOOK, ORDER, SHOP, SIGN_UP, CALL
callToAction.urlstring (URI)Destination URL for the CTA button

Constraints:

  • ✅ Text content + single image only
  • ❌ Videos not supported
  • 🔗 CTA button drives user engagement
  • 📍 Posts appear on Google Search/Maps
  • 🗺️ Use locationId to post to multiple locations from the same account connection
json
{
  "topicType": "EVENT",
  "event": {
    "title": "Grand Opening Weekend",
    "schedule": {
      "startDate": { "year": 2026, "month": 5, "day": 15 },
      "startTime": { "hours": 9, "minutes": 0 },
      "endDate": { "year": 2026, "month": 5, "day": 16 },
      "endTime": { "hours": 17, "minutes": 0 }
    }
  },
  "callToAction": {
    "type": "LEARN_MORE",
    "url": "https://example.com/grand-opening"
  }
}

Telegram

PropertyTypeDescription
parseMode"HTML" | "Markdown" | "MarkdownV2"Text formatting mode (default: HTML)
disableWebPagePreviewbooleanSet true to disable link previews
disableNotificationbooleanSend message silently (no notification sound)
protectContentbooleanPrevent forwarding and saving of the message

Constraints:

  • 📸 Up to 10 images per post (media album)
  • 🎬 Up to 10 videos per post (media album)
  • 📝 Text-only posts: up to 4096 characters
  • 🖼️ Media captions: up to 1024 characters
  • 👤 Channel posts show channel name/logo as author
  • 🤖 Group posts show "Zernio" as the bot author
  • 📊 Analytics not available via API (Telegram limitation)
json
{
  "parseMode": "HTML",
  "disableWebPagePreview": false,
  "disableNotification": false,
  "protectContent": true
}

Snapchat

PropertyTypeDescription
contentType"story" | "saved_story" | "spotlight"Type of Snapchat content (default: story)

Content Types:

  • Story (default): Ephemeral snap visible for 24 hours. No caption/text supported.
  • Saved Story: Permanent story saved to your Public Profile. Uses post content as title (max 45 chars).
  • Spotlight: Video for Snapchat's entertainment feed. Supports description (max 160 chars) with hashtags.

Constraints:

  • 👤 Requires a Snapchat Public Profile
  • 🖼️ Media required for all content types (no text-only posts)
  • 1️⃣ Only one media item per post
  • 📸 Images: max 20 MB, JPEG/PNG format
  • 🎬 Videos: max 500 MB, MP4 format, 5-60 seconds, min 540x960px
  • 📐 Aspect ratio: 9:16 recommended
  • 🔒 Media is automatically encrypted (AES-256-CBC) before upload
json
{
  "contentType": "saved_story"
}

Bluesky

Bluesky doesn't require platformSpecificData but has important constraints:

Constraints:

  • 🖼️ Up to 4 images per post
  • 🗜️ Images > ~1MB are automatically recompressed to meet Bluesky's blob size limit
  • 🔗 Link previews auto-generated when no media is attached
json
{
  "content": "Just posted this via the Zernio API! 🦋",
  "platforms": [
    {
      "platform": "bluesky",
      "accountId": "bluesky-123"
    }
  ]
}

Complete Example

Here's a real-world example posting to multiple platforms with platform-specific settings:

json
{
  "content": "Excited to announce our new product! 🎉",
  "mediaItems": [
    { "url": "https://example.com/product.jpg", "type": "image" }
  ],
  "platforms": [
    {
      "platform": "twitter",
      "accountId": "twitter-123",
      "platformSpecificData": {
        "threadItems": [
          { "content": "Excited to announce our new product! 🎉" },
          { "content": "Here's what makes it special... 🧵" }
        ]
      }
    },
    {
      "platform": "instagram",
      "accountId": "instagram-456",
      "platformSpecificData": {
        "firstComment": "Link in bio! 🔗",
        "collaborators": ["brandpartner"]
      }
    },
    {
      "platform": "linkedin",
      "accountId": "linkedin-789",
      "platformSpecificData": {
        "firstComment": "What features would you like to see next? 👇"
      }
    },
    {
      "platform": "tiktok",
      "accountId": "tiktok-012",
      "platformSpecificData": {
        "tiktokSettings": {
          "privacy_level": "PUBLIC_TO_EVERYONE",
          "allow_comment": true,
          "allow_duet": false,
          "allow_stitch": false,
          "content_preview_confirmed": true,
          "express_consent_given": true
        }
      }
    },
    {
      "platform": "youtube",
      "accountId": "youtube-345",
      "platformSpecificData": {
        "title": "New Product Announcement",
        "visibility": "public",
        "firstComment": "Thanks for watching! Subscribe for updates! 🔔"
      }
    },
    {
      "platform": "googlebusiness",
      "accountId": "gbp-678",
      "platformSpecificData": {
        "topicType": "EVENT",
        "event": {
          "title": "New Product Launch",
          "schedule": {
            "startDate": { "year": 2026, "month": 6, "day": 1 },
            "startTime": { "hours": 10, "minutes": 0 },
            "endDate": { "year": 2026, "month": 6, "day": 1 },
            "endTime": { "hours": 18, "minutes": 0 }
          }
        },
        "callToAction": {
          "type": "SHOP",
          "url": "https://example.com/product"
        }
      }
    },
    {
      "platform": "telegram",
      "accountId": "telegram-901",
      "platformSpecificData": {
        "parseMode": "HTML",
        "disableNotification": false,
        "protectContent": false
      }
    },
    {
      "platform": "snapchat",
      "accountId": "snapchat-234",
      "platformSpecificData": {
        "contentType": "saved_story"
      }
    }
  ]
}

Rate Limits

API rate limits by plan, posting velocity limits, and how to handle throttling

API Request Limits

Rate limits are applied per API key, bucketed by your team's total connected social accounts. The more accounts you've scaled to, the higher your req/min ceiling.

Connected accountsRequests per Minute
0–2 (free tier)60
3–2,000600
2,001+1,200

Connected accounts are counted across the whole billing team (owner + invited members).

Legacy AppSumo lifetime tiers get a flat 600 req/min regardless of tier.

Per-Second Limits for Analytics Endpoints

Analytics endpoints are rate limited on a 1-second window rather than a 1-minute window. The per-second cap is derived from your req/min limit:

requests_per_second = max(2, requests_per_minute / 60)

Every plan has a floor of 2 req/s, so even free-tier keys can burst at the same baseline.

Connected accountsRequests per MinuteRequests per Second (analytics)
0–2 (free tier)602
3–2,00060010
2,001+1,20020

Legacy AppSumo lifetime tiers get a flat 10 req/s on analytics endpoints regardless of tier.

These endpoints use the per-second window:

  • GET /api/v1/analytics
  • GET /api/v1/analytics/best-time
  • GET /api/v1/analytics/content-decay
  • GET /api/v1/analytics/daily-metrics
  • GET /api/v1/analytics/post-timeline
  • GET /api/v1/analytics/posting-frequency

All other endpoints continue to use the standard 1-minute window from the table above.

Rate Limit Headers

Every API response includes these headers:

HeaderDescription
X-RateLimit-LimitYour plan's requests-per-minute limit
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Handling Rate Limits

When you exceed the limit, the API returns 429 Too Many Requests:

json
{
  "error": "Rate limit exceeded. Please try again later."
}

Best approach: check X-RateLimit-Remaining before making requests, and back off when it's low. If you receive a 429, wait until X-RateLimit-Reset before retrying.

Posting Velocity Limits

Independent of API rate limits, there are limits on how fast you can publish posts to prevent platform-level throttling:

ScenarioLimit
Posts per accountPlatform-dependent cooldown between posts
Immediate publishesSubject to platform rate limits
Bulk uploadsValidated and queued, published according to schedule

These limits protect your accounts from being flagged by social platforms. If a post is rejected due to velocity limiting, you'll receive an error explaining the cooldown period.

Analytics Data Freshness

Analytics endpoints have their own caching and refresh behavior rather than strict rate limits:

  • Post analytics - Cached for 60 minutes. Requests trigger a background refresh if cache is stale. No rate limit on API requests.
  • Follower stats - Refreshed once per day automatically.
  • YouTube daily views - Data has a 2-3 day delay from YouTube's Analytics API.

See the Analytics endpoints for details.

Tips for Staying Within Limits

  • Use pagination - Don't fetch all resources at once. Use limit and offset parameters.
  • Cache responses - Store data locally instead of re-fetching frequently.
  • Use webhooks - Subscribe to webhooks instead of polling for post status changes.
  • Batch operations - Use bulk upload instead of creating posts one at a time.