How to use the Zernio API: media uploads, scheduling, and the defaults that bite — VidVertex Resources

How to use the Zernio API: media uploads, scheduling, and the defaults that bite

Zernio is the rare social-scheduling API where one key really does cover every network — connect the accounts once, then it's three HTTP calls from a video file to a scheduled post. Its docs are decent; what they can't give you is the integrator's view. This is that view, from a production integration posting through it daily: the full flow, and the defaults that quietly do the wrong thing.

Click to enlarge
The pre-flight summary before an upload: planned posts, duplicate and platform-limit warningsThe pre-flight summary before an upload: planned posts, duplicate and platform-limit warnings

The shape of the API: your profiles are brand containers, each holding the accounts connected to it (a TikTok login, an Instagram login, …). Posting needs an accountId; everything authenticates with one Bearer key:

Authorization: Bearer sk_your_key_here

against the base URL https://zernio.com/api/v1. Everything below is three steps: find your account IDs, upload the media, create the post.

The pipeline: inbox, stack, render, scheduleinboxnew clipsstacklayout + textsrenderone file perbrand × platformschedulecalendar, Zernioor Metricool
FIG 1From a file to a scheduled post. The API work all sits at the last station: upload the media, create the post, read it back.

Step 1: profiles and accounts

GET /profiles lists your profiles. For the accounts inside one, use the query-parameter form:

GET /accounts?profileId=PROFILE_ID
WARNING

The nested-looking route (/profiles/{id}/accounts) can answer 200 with an HTML page — the web app's catch-all swallows it — which a naive client parses as an empty result and mistakes for "no accounts connected". Stick to /accounts?profileId=, and treat a non-JSON 200 as a wrong route, not an empty answer.

The accountId values you collect here are what every post references.

Step 2: upload the media

Media goes up in a presign pair — ask for an upload slot, then PUT the bytes:

POST /media/presign
{ "filename": "clip.mp4", "contentType": "video/mp4", "size": 52428800 }

The response carries an uploadUrl and a publicUrl. PUT the file's raw bytes to uploadUrl with the same Content-Type header; when that succeeds, publicUrl is your media reference for the post.

TIP

Send the real byte size, and if you retry a failed PUT, re-open the file so the retry sends it from the start — a resumed half-stream corrupts the upload.

Step 3: create the post

POST /posts
{
  "content": "Your caption #withhashtags",
  "platforms": [
    {
      "platform": "instagram",
      "accountId": "ACCOUNT_ID",
      "platformSpecificData": { "thumbOffset": 3000 }
    }
  ],
  "mediaItems": [ { "url": "https://…/clip.mp4", "type": "video" } ],
  "scheduledFor": "2026-09-01T18:30:00",
  "timezone": "Europe/Berlin",
  "profileId": "PROFILE_ID"
}
  • scheduledFor is a local wall-clock ISO timestamp; timezone names the IANA zone it's local to.
  • Instead of scheduling: "publishNow": true posts immediately, "isDraft": true parks it as a draft.
  • One platforms entry per target network; each entry carries its own platformSpecificData.
WARNING

The default that bites hardest: a past-dated scheduledFor doesn't error — it publishes immediately. Compute your times wrong (yesterday's date, a timezone slip) and the whole batch is live within minutes instead of spread over a week. Validate "is this in the future, in that timezone?" before every create; the API won't do it for you.

The platformSpecificData that matters

This is where the silent defaults live. Field-verified against the platforms we post to:

Platform Field Why you need it
Snapchat contentType: "spotlight" The default is "story" — an unlabeled video post runs as a 24-hour story and vanishes, instead of landing in the public Spotlight feed. "saved_story" also exists (45-char title).
Facebook contentType: "reel" (+ own title) Omitted means feed post. The Reels tab, Reels ranking and the separate Reel title all hang on the explicit type.
Instagram thumbOffset (ms) Cover frame, picked as a timestamp into the uploaded video — no thumbnail hosting involved.
TikTok video_cover_timestamp_ms (ms) Same idea, TikTok's field name.
YouTube title The Short's own title. The request's top-level title is display-only; this is the one that ships. Custom thumbnails don't apply — Shorts never take them.
FB, Instagram, LinkedIn, YouTube, Threads firstComment The first comment, same field name on every network that has one. TikTok has no such field.
WARNING

firstComment is the API's name for it. The bulk CSV's column names (instagram_first_comment, youtube_pinned_comment, …) look like they should work here and don't — the field is simply ignored, and the post goes out without its comment.

The other half of "handled per platform" is the limits each one enforces itself:

FACT

Snapchat Spotlight takes 5–60 s video, one media item per post, needs a Snapchat Public Profile on the connected account, and shows 160 characters of description including hashtags. Facebook Reels take 3–60 s. Send a longer clip and the platform, not Zernio, is what rejects it — so check duration before upload, not after.

Reading posts back

GET /posts?status=scheduled&dateFrom=2026-09-01&dateTo=2026-09-30
    &page=1&limit=100&sortBy=scheduled-asc

Paginated, dates zero-padded YYYY-MM-DD. Published posts stay listable — you can build a calendar that shows the past, not just the queue.

NOTE

Three small edges. limit maxes at 500, and a larger value returns a 400 instead of being clamped. A created post's id is post._id in the response body, not something to parse out of a URL. And a 201 can carry a warnings array — ignored fields, truncated media — which is the only place the API says that something you sent was quietly dropped.

Retry rules

Same discipline as any scheduler API: reads and media uploads are safe to retry on network errors and transient statuses (408, 429, 5xx).

WARNING

POST /posts is not. Retry it only when the connection failed outright and the request provably never left — a blind retry on a lost response schedules the same post twice.

Where VidVertex fits

This API is one of VidVertex's two direct publishing paths (the other is the Metricool API; each also has a CSV route — all four are in upload modes). Paste one Zernio API key in Settings → Upload settings, point each brand at its Zernio profile, and every upload run does the whole flow above per rendered variant: presign upload, per-platform platformSpecificData (Spotlight instead of story, Reel instead of feed video, cover frames as timestamps, the first comment where the network has one), scheduled into each brand's own posting slots.

Pre-flight turns the rest of this page into a summary you read before the run: posts planned, clips too long or too short for their platform, combinations this stack already posted. Warnings only — nothing goes out unannounced.

Ready to multiply your output?

VidVertex runs on your Windows machine — your content, your accounts, no per-post fees. One subscription covers every brand, platform and language you run.