Zernio
Zernio
Overview

Guides

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

Queue Scheduling

Give a profile recurring posting slots and create posts with queuedFromProfile so each one lands on the next free slot.


When you finish this page a profile has recurring posting slots and every post you create with queuedFromProfile lands on the next free one, in order. You need an API key, a profile id (Step 2 of the quickstart) and a connected account. This is how to drip-feed 50 posts without computing 50 values of scheduledFor.

Step 1: Create a queue

Call POST /v1/queue/slots with profileId, name, timezone and slots. Each slot is a dayOfWeek (0 is Sunday, 6 is Saturday) and a 24-hour time.

import Zernio from '@zernio/node';

const zernio = new Zernio();
const profileId = '66a1f0c2a4b9d3e8f1a2b3c4';

const { data: queue } = await zernio.queue.createQueueSlot({
  body: {
    profileId,
    name: 'Weekday mornings',
    timezone: 'America/New_York',
    slots: [
      { dayOfWeek: 1, time: '09:00' },
      { dayOfWeek: 3, time: '09:00' },
      { dayOfWeek: 5, time: '09:00' }
    ]
  }
});

const queueId = queue.schedule._id;

Response (201):

{
  "success": true,
  "schedule": {
    "_id": "66d5e3bf9a1c2d4e6f7a8b9c",
    "profileId": "66a1f0c2a4b9d3e8f1a2b3c4",
    "name": "Weekday mornings",
    "timezone": "America/New_York",
    "slots": [
      { "dayOfWeek": 1, "time": "09:00" },
      { "dayOfWeek": 3, "time": "09:00" },
      { "dayOfWeek": 5, "time": "09:00" }
    ],
    "active": true,
    "isDefault": true
  },
  "nextSlots": [
    "2027-01-04T09:00:00-05:00",
    "2027-01-06T09:00:00-05:00"
  ]
}

GET /v1/queue/slots?profileId=... returns the default queue and its next slots; add all=true to list every queue on the profile. The queue endpoints also update and delete slots.

Step 2: Create a post with queuedFromProfile

Call POST /v1/posts with queuedFromProfile set to the profile id and no scheduledFor. Zernio locks the next free slot and assigns it. Repeat the call for each post in the batch; every post takes the slot after the previous one.

const { data: queued } = await zernio.posts.createPost({
  body: {
    content: 'Post 1 of 50',
    platforms: [
      { platform: 'linkedin', accountId: '66b2e19d8c3f5a7e9d0b1c2d' }
    ],
    queuedFromProfile: profileId
  }
});

console.log(queued.post.scheduledFor);

Response (201):

{
  "message": "Post scheduled successfully",
  "post": {
    "_id": "65f1c0a9e2b5af0012ab34cd",
    "content": "Post 1 of 50",
    "status": "scheduled",
    "scheduledFor": "2027-01-04T14:00:00Z",
    "timezone": "America/New_York",
    "queuedFromProfile": "66a1f0c2a4b9d3e8f1a2b3c4",
    "queueId": "66d5e3bf9a1c2d4e6f7a8b9c",
    "platforms": [
      { "platform": "linkedin", "status": "pending" }
    ]
  }
}

A profile can have several queues. Run Step 1 again with the same profileId and a different name to add one: the first queue a profile gets is its default and every later one is not, until a PUT /v1/queue/slots with setAsDefault: true moves the flag. Pass queueId next to queuedFromProfile to target a specific queue; without it the post goes to the profile's default queue.

Step 3: Preview the next slot

Call GET /v1/queue/next-slot with profileId (and queueId for a specific queue) to show a user when their post would go out.

const { data: next } = await zernio.queue.getNextQueueSlot({
  query: { profileId }
});

console.log(next.nextSlot);

Response (200):

{
  "profileId": "66a1f0c2a4b9d3e8f1a2b3c4",
  "nextSlot": "2027-01-06T09:00:00-05:00",
  "timezone": "America/New_York",
  "queueId": "66d5e3bf9a1c2d4e6f7a8b9c",
  "queueName": "Weekday mornings"
}

Do not pass nextSlot as scheduledFor. That skips the queue lock, so 2 concurrent creates can land on the same slot. Schedule queue posts with queuedFromProfile and let Zernio assign the time.

If it fails

A 409 on PUT /v1/posts/{postId} means the new scheduledFor is already taken by another post in the same queue:

{
  "error": "This time slot is already taken in this queue. Choose a different time, send queuedFromProfile without scheduledFor to let the queue assign the next open slot, or send queueId: null to schedule this post outside the queue.",
  "type": "invalid_request_error",
  "code": "queue_slot_conflict",
  "param": "scheduledFor"
}

Pick a free time, drop scheduledFor so the queue assigns the next open slot, or send queueId: null to schedule the post outside the queue.

GET /v1/queue/next-slot answers 404 when the profile has no queue or no slot is free, and 400 when the queue is inactive (active: false) or a parameter is invalid. POST /v1/queue/slots answers 400 for a malformed slot: time must match HH:mm and dayOfWeek must be 0 to 6. The queue endpoints list every response.

Related

  • Create post: every field, including queueId.
  • Queue endpoints: list, update and delete slots.
  • Post lifecycle: what scheduled means and which webhook fires next.
  • Timezones: how timezone is read.
Was this page helpful?

Media Uploads

Upload an image, video or document with a presigned URL and attach it to a post with mediaItems.

Timezones & Scheduling

Schedule a post at a local wall-clock time with scheduledFor and timezone, and read back the UTC instant Zernio stores.

On this page

Step 1: Create a queueStep 2: Create a post with queuedFromProfileStep 3: Preview the next slotIf it failsRelated