Zernio
Zernio
Overview

Guides

ProfilesConnecting accountsMedia UploadsQueue SchedulingTimezones & SchedulingIdempotency & Safe RetriesPost LifecycleError HandlingRate LimitsPlatform Settings
Dashboard
llms.txtOpenAPI
OverviewPlatformsAPI ReferenceResources
Guides

Platform Settings

How platformSpecificData and the root-level tiktokSettings and facebookSettings objects resolve on POST /v1/posts, and which value wins when both are set.


When you finish this page you can set per-platform options in one POST /v1/posts call and say which value wins when the same option is set in two places. You need an API key and a connected account. Options go in platformSpecificData on a platforms[] entry; the fields each platform accepts are listed under "Platform fields" on its platform page, and the create post reference carries all 15 platform schemas, Discord and Slack included.

First call

One field on one platform: an Instagram post that leaves its links in the first comment.

import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data: created } = await zernio.posts.createPost({
  body: {
    content: 'Golden hour at the pier.',
    mediaItems: [{ url: 'https://cdn.example.com/pier.jpg', type: 'image' }],
    platforms: [
      {
        platform: 'instagram',
        accountId: '66b2e19d8c3f5a7e9d0b1c2e',
        platformSpecificData: { firstComment: 'Docs link in bio.' }
      }
    ],
    scheduledFor: '2027-01-01T12:00:00',
    timezone: 'America/New_York'
  }
});

console.log(created.post.status);

Response (201):

{
  "message": "Post scheduled successfully",
  "post": {
    "_id": "65f1c0a9e2b5af0012ab34cd",
    "status": "scheduled",
    "scheduledFor": "2027-01-01T17:00:00Z",
    "platforms": [
      { "platform": "instagram", "status": "pending" }
    ]
  }
}

Several platforms in one call

One post to X (platform value twitter) as a thread, to Instagram with a first comment, and to TikTok with the consent flags TikTok requires:

const { data: launch } = await zernio.posts.createPost({
  body: {
    content: 'Our API launch, in 3 posts.',
    mediaItems: [{ url: 'https://cdn.example.com/launch.mp4', type: 'video' }],
    platforms: [
      {
        platform: 'twitter',
        accountId: '66b2e19d8c3f5a7e9d0b1c2d',
        platformSpecificData: {
          threadItems: [
            { content: 'Our API launch, in 3 posts.' },
            { content: '1/ Authentication is one API key.' },
            { content: '2/ Your first post is one call.' }
          ]
        }
      },
      {
        platform: 'instagram',
        accountId: '66b2e19d8c3f5a7e9d0b1c2e',
        platformSpecificData: { firstComment: 'Docs link in bio.' }
      },
      { platform: 'tiktok', accountId: '66b2e19d8c3f5a7e9d0b1c2f' }
    ],
    tiktokSettings: {
      privacy_level: 'PUBLIC_TO_EVERYONE',
      allow_comment: true,
      allow_duet: true,
      allow_stitch: true,
      content_preview_confirmed: true,
      express_consent_given: true
    },
    scheduledFor: '2027-01-01T12:00:00',
    timezone: 'America/New_York'
  }
});

console.log(launch.post.status);

Response (201):

{
  "message": "Post scheduled successfully",
  "post": {
    "_id": "65f1c0a9e2b5af0012ab34cd",
    "status": "scheduled",
    "scheduledFor": "2027-01-01T17:00:00Z",
    "platforms": [
      { "platform": "twitter", "status": "pending" },
      { "platform": "instagram", "status": "pending" },
      { "platform": "tiktok", "status": "pending" }
    ]
  }
}

The TikTok entry above publishes only because content_preview_confirmed and express_consent_given are true and privacy_level is one of the values TikTok returns for that account in creator info. TikTok has no defaults for these three.

How it behaves

platformSpecificData belongs to one platform entry

The shape of platformSpecificData is chosen by the platform value on the same entry, so one key can mean different things on two entries of the same request. A field that lands anywhere else, such as the root of the body or the wrong entry, is ignored: the post is still created and the 201 response names the ignored field in warnings.

{
  "message": "Post scheduled successfully",
  "post": { "_id": "65f1c0a9e2b5af0012ab34cd", "status": "scheduled" },
  "warnings": [
    "Ignored root-level \"platformSpecificData\": it is only read per platform, as platforms[].platformSpecificData."
  ]
}

Three siblings on the entry override the top-level request instead of the platform: customContent replaces content, customMedia replaces mediaItems (media uploads), and a per-platform scheduledFor replaces the top-level scheduled time.

Root-level settings merge in and lose ties

Two namespaces can be sent at the root of the body instead of repeated on every entry: tiktokSettings and facebookSettings. Zernio merges each into every entry of that platform, writing it to platformSpecificData.tiktokSettings or platformSpecificData.facebookSettings. The merge runs key by key and the entry wins: a key set on the entry keeps its value, a key set only at the root is copied in.

Facebook's draft, carouselCards and colored-background options live only inside the facebookSettings namespace. Every other Facebook field sits directly on platformSpecificData.

TikTok is read from both shapes: the nested platformSpecificData.tiktokSettings object first, then any TikTok field written flat on platformSpecificData, which overrides the nested value. Names are accepted in snake_case and camelCase (privacy_level, privacyLevel).

An update replaces a whole namespace

On PUT /v1/posts/{postId} a <platform>Settings namespace you leave out is kept from the stored post, and one you send replaces the stored namespace whole; it is not deep-merged. Send every key you want to keep. A root-level namespace sent without a platforms array returns 400.

If it fails

A 400 means a field in platformSpecificData has a value the platform does not accept. code and param name the field:

{
  "error": "userTags[0].x must be between 0 and 1",
  "type": "invalid_request_error",
  "code": "invalid_field_value",
  "param": "platforms[1].platformSpecificData.userTags[0].x"
}

Fix the named field and send the request again; a 400 creates nothing. The error handling guide describes the envelope.

Related

  • Create post: every field for every platform, including Discord and Slack.
  • Platforms: what each platform does with these fields, and its media limits.
  • Media uploads: mediaItems, customMedia and thumbnails.
  • Post lifecycle: per-platform status after publishing.
Was this page helpful?

Rate Limits

Requests per minute by connected account count, the per-second window on analytics, posting velocity caps, and how to handle a 429.

Security Overview

How access to a Zernio team is protected, from sign-in methods and two-step verification to SSO, session controls, roles and the audit log.

On this page

First callSeveral platforms in one callHow it behavesplatformSpecificData belongs to one platform entryRoot-level settings merge in and lose tiesAn update replaces a whole namespaceIf it failsRelated