Quickstart
Get started with the Zernio API - authenticate, connect accounts, and schedule your first post in minutes.
Zernio is one API for social publishing and customer communication: schedule posts across 14 platforms, answer DMs and comments from a unified inbox, run ads, pull analytics, and provision phone numbers for SMS, calls, and WhatsApp. This page takes you from API key to your first scheduled post — about five minutes.
Trying it out costs nothing: the first 2 connected accounts are free, no credit card required.
Base URL: https://zernio.com/api/v1
Building a product where your users connect their accounts? The flow below is the same, but you'll want one profile per customer, scoped keys, and webhook routing — start at the multi-tenant guide after your first post.
Install an SDK
npm install @zernio/nodepip install zernio-sdkPrefer another language? There are SDKs for Go, Ruby, Java, PHP, .NET, and Rust, each with its own setup page — and every example below also shows plain curl, which needs no install at all.
Authentication
All API requests require an API key. The SDKs read it from the ZERNIO_API_KEY environment variable by default.
Get Your API Key
- Sign up free or log in — no credit card needed
- Go to Settings → API Keys
- Click Create API Key
- Copy the key immediately - you won't be able to see it again
Set Up the Client
import Zernio from '@zernio/node';
const zernio = new Zernio(); // uses ZERNIO_API_KEY env varfrom zernio import Zernio
client = Zernio() # uses ZERNIO_API_KEY env var# Set your API key as an environment variable
export ZERNIO_API_KEY="sk_..."
# All requests use the Authorization header
curl https://zernio.com/api/v1/posts \
-H "Authorization: Bearer $ZERNIO_API_KEY"Key format: sk_ prefix + 64 hex characters (67 total). Keys are stored as SHA-256 hashes - they're only shown once at creation.
Security tips: Use environment variables, create separate keys per app, and rotate periodically. You can also manage keys via the API.
Key Concepts
- Profiles - Containers that group social accounts together (think "brands" or "projects")
- Accounts - Your connected social media accounts, belonging to profiles
- Posts - Content to publish, schedulable to multiple accounts across platforms simultaneously
- Queue - Optional recurring time slots for auto-scheduling posts
IDs in this API are 24-character MongoDB-style strings in an _id field (like 66a1f0c2a4b9d3e8f1a2b3c4) — each step below returns the ID the next step needs.
Step 1: Create a Profile
Profiles group your social accounts together. For example, you might have a "Personal Brand" profile with your Twitter and LinkedIn, and a "Company" profile with your business accounts.
const { data } = await zernio.profiles.createProfile({
body: {
name: 'My First Profile',
description: 'Testing the Zernio API'
}
});
console.log('Profile created:', data.profile._id);
// → Profile created: 66a1f0c2a4b9d3e8f1a2b3c4result = client.profiles.create_profile(
name="My First Profile",
description="Testing the Zernio API"
)
print(f"Profile created: {result['profile']['_id']}")
# → Profile created: 66a1f0c2a4b9d3e8f1a2b3c4curl -X POST https://zernio.com/api/v1/profiles \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My First Profile",
"description": "Testing the Zernio API"
}'Save the _id value - you'll need it for the next steps.
Step 2: Connect a Social Account
Now connect a social media account to your profile. This uses OAuth, so it will redirect to the platform for authorization.
const { data } = await zernio.connect.getConnectUrl({
path: { platform: 'twitter' },
query: { profileId: '66a1f0c2a4b9d3e8f1a2b3c4' } // the profile _id from Step 1
});
// Redirect user to this URL to authorize
console.log('Open this URL:', data.authUrl);result = client.connect.get_connect_url(
platform="twitter",
profile_id="66a1f0c2a4b9d3e8f1a2b3c4", # the profile _id from Step 1
)
print(f"Open this URL: {result['authUrl']}")# profileId is the profile _id from Step 1
curl "https://zernio.com/api/v1/connect/twitter?profileId=66a1f0c2a4b9d3e8f1a2b3c4" \
-H "Authorization: Bearer $ZERNIO_API_KEY"Open the URL in a browser to authorize Zernio to access your Twitter account. After authorization, you'll be redirected back and the account will be connected.
Available Platforms
Replace twitter with any of these:
| Platform | API Value | Guide |
|---|---|---|
| Twitter/X | twitter | Twitter/X Guide |
instagram | Instagram Guide | |
facebook | Facebook Guide | |
linkedin | LinkedIn Guide | |
| TikTok | tiktok | TikTok Guide |
| YouTube | youtube | YouTube Guide |
pinterest | Pinterest Guide | |
reddit | Reddit Guide | |
| Bluesky | bluesky | Bluesky Guide |
| Threads | threads | Threads Guide |
| Google Business | googlebusiness | Google Business Guide |
| Telegram | telegram | Telegram Guide |
| Snapchat | snapchat | Snapchat Guide |
whatsapp | WhatsApp Guide | |
| Discord | discord | Discord Guide |
Step 3: Get Your Connected Accounts
After connecting, list your accounts to get the account ID:
const { data } = await zernio.accounts.listAccounts();
for (const account of data.accounts) {
console.log(`${account.platform}: ${account._id}`);
}
// → twitter: 66b2e19d8c3f5a7e9d0b1c2dresult = client.accounts.list_accounts()
for account in result["accounts"]:
print(f"{account['platform']}: {account['_id']}")
# → twitter: 66b2e19d8c3f5a7e9d0b1c2dcurl "https://zernio.com/api/v1/accounts" \
-H "Authorization: Bearer $ZERNIO_API_KEY"Save the account _id - you need it to create posts.
Step 4: Schedule Your First Post
Now you can schedule a post! Here's how to schedule a tweet for tomorrow at noon:
// Tomorrow at 12:00 in the timezone below
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const scheduledFor = tomorrow.toISOString().slice(0, 10) + 'T12:00:00';
const { data } = await zernio.posts.createPost({
body: {
content: 'Hello world! This is my first post from the Zernio API',
scheduledFor,
timezone: 'America/New_York',
platforms: [
{ platform: 'twitter', accountId: '66b2e19d8c3f5a7e9d0b1c2d' } // from Step 3
]
}
});
console.log('Post scheduled:', data.post._id);from datetime import date, timedelta
# Tomorrow at 12:00 in the timezone below
scheduled_for = f"{date.today() + timedelta(days=1)}T12:00:00"
result = client.posts.create_post(
content="Hello world! This is my first post from the Zernio API",
scheduled_for=scheduled_for,
timezone="America/New_York",
platforms=[
{"platform": "twitter", "accountId": "66b2e19d8c3f5a7e9d0b1c2d"} # from Step 3
]
)
print(f"Post scheduled: {result['post']['_id']}")# Use any future time; it's interpreted in the timezone field
curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Hello world! This is my first post from the Zernio API",
"scheduledFor": "2027-01-01T12:00:00",
"timezone": "America/New_York",
"platforms": [
{"platform": "twitter", "accountId": "66b2e19d8c3f5a7e9d0b1c2d"}
]
}'Step 5: Confirm It Worked
Fetch the post back — its status tells you exactly where it is in the pipeline:
const { data: check } = await zernio.posts.getPost({
path: { postId: data.post._id } // the _id returned in Step 4
});
console.log(check.post.status);
// → scheduledresult = client.posts.get_post(post_id=result["post"]["_id"])
print(result["post"]["status"])
# → scheduledcurl "https://zernio.com/api/v1/posts/POST_ID" \
-H "Authorization: Bearer $ZERNIO_API_KEY"status moves through scheduled → publishing → published (or failed / partial if something goes wrong — see error handling). Once published, the response includes a platformPostUrl per platform: the live link to your post. You'll also see the post in your dashboard, and webhooks can push these status changes to you instead of polling.
That's the whole loop — profile, connected account, scheduled post, confirmation. Everything else is variations on this.
One Endpoint, Every Posting Mode
The same createPost call covers scheduling, publishing immediately, and drafts:
| You set | Result |
|---|---|
scheduledFor + timezone | Publishes automatically at that time |
publishNow: true | Publishes immediately |
| Neither | Saved as a draft to finish later |
And cross-posting is just more entries in the platforms array — same content, one call, every network:
await zernio.posts.createPost({
body: {
content: 'Cross-posting to all my accounts, right now!',
publishNow: true,
platforms: [
{ platform: 'twitter', accountId: '66b2e19d8c3f5a7e9d0b1c2d' },
{ platform: 'linkedin', accountId: '66b2e19d8c3f5a7e9d0b1c2e' },
{ platform: 'bluesky', accountId: '66b2e19d8c3f5a7e9d0b1c2f' }
]
}
});The request shape is identical in every SDK and in raw JSON. Per-platform options (first comment, board IDs, video titles) are covered in the platform guides.
Beyond Posting
Publishing is the entry point, but the same API key and connected accounts open the whole engagement surface: the unified inbox, messaging channels, automations, ads, and analytics.
Reply to a DM
Read and answer Instagram, Facebook, WhatsApp, and X conversations from one inbox:
await zernio.messages.sendInboxMessage({
path: { conversationId: '66c3d2ae7b4f6c8d0e1f2a3b' }, // from List conversations
body: {
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
message: 'Thanks for reaching out! How can we help?'
}
});client.messages.send_inbox_message(
conversation_id="66c3d2ae7b4f6c8d0e1f2a3b", # from List conversations
account_id="66b2e19d8c3f5a7e9d0b1c2d",
message="Thanks for reaching out! How can we help?",
)curl -X POST "https://zernio.com/api/v1/inbox/conversations/66c3d2ae7b4f6c8d0e1f2a3b/messages" \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"message": "Thanks for reaching out! How can we help?"
}'Find conversation IDs with List conversations.
Send an SMS
Provision a phone number, then message customers directly:
await zernio.sms.sendSms({
body: {
from: '+15551234567', // one of your SMS-enabled numbers
to: '+15557654321',
text: 'Your order has shipped!'
}
});client.sms.send_sms(
from_="+15551234567", # one of your SMS-enabled numbers
to="+15557654321",
text="Your order has shipped!",
)curl -X POST "https://zernio.com/api/v1/sms/messages" \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "+15551234567",
"to": "+15557654321",
"text": "Your order has shipped!"
}'Pull analytics
See how your posts perform across every connected account:
const { data } = await zernio.analytics.getAnalytics({
query: { sortBy: 'engagement', limit: 5 }
});result = client.analytics.get(limit=5)curl "https://zernio.com/api/v1/analytics?sortBy=engagement&limit=5" \
-H "Authorization: Bearer $ZERNIO_API_KEY"Explore the rest
Unified Inbox
DMs, comments, reviews, and mentions across every platform
WhatsApp Platform
Templates, broadcasts, flows, groups, and calling
Phone Numbers, SMS & Voice
Provision numbers, register campaigns, send SMS, place calls
Ads
Meta, TikTok, Google, LinkedIn, Pinterest, and X: campaigns, boosting, lead forms
Comment-to-DM Automations
Auto-DM people who comment on your posts
Broadcasts & Sequences
Bulk messaging campaigns and multi-step drip sequences
Workflows
Event-driven automation with branching logic
Webhooks
Real-time events for posts, messages, accounts, and more
What's Next?
Platform Guides
Platform-specific features, media requirements, and publishing options
Upload media
Add images and videos to your posts
Build for your users
One profile per customer, scoped keys, webhook routing
Track post status
Webhooks for publishing results instead of polling
Going to production? Read up on rate limits, idempotent retries, and error handling. You can also set up a posting queue, invite team members, or manage everything from the CLI.