CLI
Install the Zernio CLI, log in, and schedule a post from the terminal with one command that prints the API response as JSON.
The Zernio CLI wraps the API for terminals and agents. Install it with npm install -g @zernio/cli. Every command prints the API response as JSON, so the output pipes into jq or straight into an agent, and the same key works for every one of the 16 platforms.
First command
Install
npm install -g @zernio/cliLog in
zernio auth:loginThe browser opens for you to authorize the CLI. Zernio creates an API key and saves it to ~/.zernio/config.json. Pass --device-name "my-server" to label the key; the default is your hostname.
To use a key you already made on API keys, run zernio auth:set --key "$ZERNIO_API_KEY" instead.
zernio auth:check calls GET /v1/users and prints {"success":true,"message":"API key is valid", ...} followed by the team's users when the key works.
Schedule a post
posts:create takes --text, one or more account ids in --accounts, and --scheduledAt. Omit --scheduledAt to publish now, or pass --draft to save a draft. Account ids come from zernio accounts:list.
zernio posts:create \
--text "Hello world. This is my first post from the Zernio CLI." \
--accounts 66b2e19d8c3f5a7e9d0b1c2d \
--scheduledAt "2027-01-01T12:00:00" \
--timezone "America/New_York" \
--prettyOutput (the 201 body of POST /v1/posts):
{
"message": "Post scheduled successfully",
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"content": "Hello world. This is my first post from the Zernio CLI.",
"status": "scheduled",
"scheduledFor": "2027-01-01T17:00:00Z",
"timezone": "America/New_York",
"platforms": [
{
"platform": "linkedin",
"accountId": { "_id": "66b2e19d8c3f5a7e9d0b1c2d", "platform": "linkedin", "username": "acme" },
"status": "pending"
}
]
}
}The CLI looks the account up, fills in its platform, and sends the request. --title, --tags and --hashtags map to the fields of the same name on Create post, and --media to its mediaItems.
A failed command prints one JSON object to stderr and exits with code 1. An unknown account id, for example:
{"error":true,"message":"Account 66b2e19d8c3f5a7e9d0b1c2e not found. Run \"zernio accounts:list\" to see available accounts.","status":404}Run zernio accounts:list and copy the _id of the account you want. A status of 401 means no valid key is configured: run zernio auth:login again.
Commands
zernio --help prints every command. They are grouped by area, one page each:
Posting commands
Profiles, accounts, connect, posts, media, queue, validation
Inbox commands
Conversations, comments, reviews, contacts, broadcasts, sequences, automations, workflows
Analytics commands
Post and inbox analytics, activity logs
Ads commands
Ads, campaigns, audiences, lead forms, conversions, tracking tags
Platform commands
WhatsApp, Google Business Profile, Discord, Instagram, Reddit, X
Management commands
Auth, API keys, users, invites, account groups, settings, webhooks
Output is compact JSON by default; add --pretty for indented output. The posts, inbox, contacts, broadcasts, sequences and automations groups are hand-written; the rest are generated from the API so the CLI covers the full surface.
How it behaves
The CLI reads the key from ZERNIO_API_KEY or ~/.zernio/config.json
Environment variables win over the config file:
| Variable | Description | Required |
|---|---|---|
ZERNIO_API_KEY | Your API key | Yes, unless a key was saved with auth:login or auth:set |
ZERNIO_API_URL | Custom API base URL | No |
LATE_API_KEY, LATE_API_URL and ~/.late/config.json are the names these three had before the rebrand from Late. The CLI reads them only when the ZERNIO_ variables and ~/.zernio/config.json are absent.
auth:login replaces the key for the same device
Running zernio auth:login again on a device that already has a key replaces that key instead of creating a second one.
Generated command names derive from the operationId
A generated command is <group>:<operation> in kebab case, so the createCtwaAd operation becomes ads:create-ctwa. Positional arguments are the path parameters (zernio posts:get <id>); body and query fields are --flags named after the API field.