OmniSocialsOmniSocials
DocumentationAPI reference
Help centerSupport
  • Documentation
  • API reference
Developers
  • Quickstart
  • API reference
  • SDKs
  • MCP server
  • CLI
For AI agents
  • Docs for AI agents
  • llms.txt
  • OpenAPI spec
  • Postman collection
Product
  • OmniSocials
  • Pricing
  • Changelog
  • Help center
Company
  • Support
  • Privacy policy
  • Terms of service

© 2026 OmniSocials

OmniSocials on GitHubOmniSocials on XOmniSocials on LinkedIn
Overview
Get started
SDKs
CLI
MCPDocs for AI agentsWebhooks
Guides
Platforms
Integrations
Migrate
    From AyrshareFrom ZernioFrom Upload-PostFrom Postiz
Plans and billing
GlossaryChangelogAPI reference
Migrate

Migrate from Upload-Post to the OmniSocials API

This guide is for developers who post through the Upload-Post API and want to move to the OmniSocials API. Upload-Post has a separate multipart endpoint for each content type and picks the profile with a user field. OmniSocials has one JSON endpoint for every post type, and the API key itself picks the workspace. Media goes in as a URL or as an ID from an earlier upload. Social accounts are connected in the OmniSocials dashboard, not through a connect URL. Upload-Post facts on this page come from docs.upload-post.com and were checked on October 21, 2026.

Concepts

Upload-PostOmniSocialsNotes
API key (Authorization: Apikey ...)API key (Authorization: Bearer omsk_live_...)An OmniSocials key belongs to one workspace.
Profile (the user field, a username)WorkspaceEach workspace has its own API key. There is no user field.
Social accounts on a profileAccounts in a workspaceOne account per channel ID per workspace.
Connect URL (generate-jwt, oauth/{platform}/start)Dashboard connectionAccounts are connected only in the dashboard, never through the API.
request_id and job_idPost idOne ID for drafts, scheduled posts, and published posts.
Separate upload endpoints for video, photos, text, and documentsPOST /posts/createOne endpoint. type picks a feed post, story, or reel.
Facebook page, LinkedIn page, and Google Business location IDs per requestChosen when the account is connectedA workspace posts to one Facebook Page, one LinkedIn page, and one Google Business location.
QueueNoneGET /analytics/best-times recommends slots. You pick the time.

Authentication

Text
Upload-Post: Authorization: Apikey YOUR_API_KEY OmniSocials: Authorization: Bearer omsk_live_...

With Upload-Post, one key serves every profile, and each request names the profile in user. An OmniSocials key is bound to one workspace, chosen when you create the key under Settings → API. To serve several brands, create one workspace and one key per brand, and store the key where you stored the Upload-Post username. GET /accounts returns workspace_id and workspace_name, so you can check which workspace a key belongs to.

Keys have scopes, such as posts:write and media:write. A key's scopes cannot be edited later. See Authentication.

Endpoint mapping

OmniSocials paths are relative to https://api.omnisocials.com/v1. Upload-Post paths are relative to https://api.upload-post.com.

Upload-PostOmniSocialsNotes
POST /api/upload (video)POST /posts/createPass the video in media_urls or media_ids. Use type: "reel" for TikTok videos, Instagram reels, and YouTube Shorts.
POST /api/upload_photosPOST /posts/createImages in media_urls or media_ids. Two or more images publish as a carousel where the platform supports it.
POST /api/upload_textPOST /posts/createNo media. Instagram, TikTok, Pinterest, and YouTube need media.
POST /api/upload_documentPOST /posts/createPass a PDF. On LinkedIn it publishes as a document. PPT and DOC files are not accepted.
GET /api/uploadposts/statusGET /posts/{id}Read status, published_urls, and errors.
GET /api/uploadposts/scheduleGET /posts?status=scheduledPage with limit (max 100) and offset.
GET /api/uploadposts/schedule/<job_id>GET /posts/{id}
PATCH /api/uploadposts/schedule/<job_id>PATCH /posts/{id}Drafts and scheduled posts only. Media and channels can change too.
DELETE /api/uploadposts/schedule/<job_id>DELETE /posts/{id}Cancels a scheduled publish. On a published post it removes the post from OmniSocials only.
GET /api/uploadposts/historyGET /posts?status=publishedGET /posts/recent-platform reads recent posts made outside OmniSocials.
GET /api/analytics/{profile_username}GET /analytics/accounts, GET /analytics/overview
GET /api/uploadposts/post-analytics/{request_id}GET /analytics/posts/{id}GET /analytics/posts?ids= takes up to 100 post IDs.
GET /api/uploadposts/meGET /accountsReturns the workspace and its connected accounts.
GET /api/uploadposts/pinterest/boardsGET /accounts/{id}A Pinterest account carries a boards array. Boards cannot be created through the API.
GET /api/uploadposts/facebook/pages, GET /api/uploadposts/linkedin/pagesNoneThe page is chosen when the account is connected.
POST /api/uploadposts/users and profile CRUDNoneManage workspaces in the dashboard.
POST /api/uploadposts/users/generate-jwt, POST /api/uploadposts/oauth/{platform}/startNoneConnect accounts in the dashboard.
DELETE /api/uploadposts/users/socialNoneDisconnect accounts in the dashboard.
/api/uploadposts/queue/*None
Notification settingsPOST /webhooks, GET, PATCH, DELETE /webhooks/{id}See Webhooks.

Create a post

The same post in both APIs: one video to TikTok and YouTube, scheduled for 08:00 UTC on November 2, 2026.

Upload-Post sends the file and the fields in one multipart request:

TerminalTerminal
curl -X POST https://api.upload-post.com/api/upload \ -H "Authorization: Apikey $UPLOAD_POST_API_KEY" \ -F "user=acme" \ -F "platform[]=tiktok" \ -F "platform[]=youtube" \ -F "video=@/path/to/launch.mp4" \ -F "title=Launch day behind the scenes" \ -F "scheduled_date=2026-11-02T08:00:00Z"

OmniSocials takes JSON. Upload the file first, then create the post with the returned ID:

TerminalTerminal
curl -X POST https://api.omnisocials.com/v1/media/upload \ -H "Authorization: Bearer $OMNISOCIALS_API_KEY" \ -F "file=@/path/to/launch.mp4" curl -X POST https://api.omnisocials.com/v1/posts/create \ -H "Authorization: Bearer $OMNISOCIALS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "reel", "content": "Launch day behind the scenes", "accounts": ["tiktok", "youtube"], "media_ids": ["123"], "youtube": { "title": "Launch day behind the scenes" }, "schedule_at": "2026-11-02T08:00:00Z" }'

Replace 123 with data.id from the upload response. If the video is already at a public URL, skip the upload and pass "media_urls": ["https://example.com/launch.mp4"] instead. On YouTube, content becomes the video description and youtube.title the title.

The create call answers with a 201 and the post under data. Publishing always runs in the background. Read the outcome with GET /posts/{id} or a post.published webhook.

Field mapping

Upload-Post fieldOmniSocials fieldNotes
userNoneThe API key selects the workspace.
platform[]accountsA JSON array. x and google_business keep their names. Alias: channels.
videomedia_urls or media_idsA URL, or the ID of an earlier upload. The file itself is not sent in the post request.
photos[]media_urls or media_idsUp to 10 URLs per post.
documentmedia_urls or media_ids with a PDFOne image per page. A LinkedIn document on LinkedIn.
titlecontentThe post text. A string, or an object with default and channel keys.
[platform]_title, such as x_titlecontent.x, content.linkedin, and so onPer-channel text. On YouTube, set the title in youtube.title.
descriptioncontentOn YouTube, content becomes the description.
scheduled_dateschedule_atISO 8601 in UTC. Alias: scheduled_at.
timezoneNoneConvert to UTC before you send.
first_comment, [platform]_first_commentfirst_comment under the channel key, such as instagram.first_commentInstagram, Facebook, LinkedIn, YouTube, TikTok, and Telegram.
privacy_leveltiktok.privacy_level, youtube.privacy_status
pinterest_board_idpinterest.board_idRequired on every Pinterest post.
facebook_page_idNoneThe Page is chosen when Facebook is connected.
target_linkedin_page_idlinkedin_page in accountslinkedin is the personal profile.
gbp_location_idNoneThe location is chosen when Google Business is connected.
add_to_queue, max_posts_per_slotNone
async_uploadNonePublishing is always asynchronous.
external_id, request_id, Idempotency-KeyNoneStore the returned post id next to your own ID.

Media and scheduling

Media. Upload-Post takes the file inside the post request. OmniSocials keeps media and posts apart:

  • media_urls on the post. Pass public URLs and OmniSocials downloads them. Up to 10 files, each up to 100 MB.
  • POST /media/upload. A multipart upload with a file field, up to 100 MB. Use data.id in media_ids.
  • POST /media/upload-from-url. OmniSocials fetches a public URL of up to 1 GB. Files above about 100 MB come back with status: "processing". Poll GET /media/{id} until it is ready.
  • POST /media/upload-from-base64. For a client that holds the file as base64.

A file in the library can be used on many posts, so upload once when the same video goes out more than once. The largest file OmniSocials takes is 1 GB. Platform limits, such as video length, are checked when a post is scheduled or published. See Media.

Scheduling. Send schedule_at as an ISO 8601 time in UTC. OmniSocials publishes within one minute of that time. There is no timezone field and no queue. A time in the past returns 400 validation_error. To publish now, send publish_now: true, or call POST /posts/create-and-publish. A post with neither schedule_at nor publish_now is saved as a draft.

Webhooks

Register a webhook with POST /webhooks. Webhooks belong to the workspace of the key that creates them. The response returns a secret once. Store it.

TerminalTerminal
curl -X POST https://api.omnisocials.com/v1/webhooks \ -H "Authorization: Bearer $OMNISOCIALS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-app.com/webhooks/omnisocials", "events": ["post.published", "post.failed"] }'
Upload-Post eventOmniSocials eventNotes
upload_completedpost.published, post.failedpost.published fires when at least one channel succeeds. A partial publish has data.status set to warning. Check each entry in data.targets.
social_account_connected, social_account_disconnected, social_account_reauth_requiredNonePoll GET /accounts and check needs_reconnect.
Nonepost.scheduledSent when a post is scheduled through the API.
Nonepost.approved, post.rejectedApproval workflow outcomes.

Signatures. Both APIs sign the same string: the timestamp, a dot, and the raw body, with HMAC-SHA256 and your webhook secret. Only the headers change. Upload-Post sends X-Upload-Post-Signature: sha256=<hex> and X-Upload-Post-Timestamp. OmniSocials sends one header, X-OmniSocials-Signature: t=<timestamp>,v1=<hex>. Deduplicate on X-OmniSocials-Delivery. See Webhooks for verification code.

Delivery. Answer with a 2xx within 10 seconds. Failed deliveries are retried twice, after 2 seconds and then 5 more. After that the event is dropped. Webhook URLs must use HTTPS.

Platform coverage

As of October 21, 2026, from docs.upload-post.com and the OmniSocials platforms page.

PlatformUpload-PostOmniSocials
FacebookYes (facebook)Yes (facebook), Pages
InstagramYes (instagram), no text-only postsYes (instagram), Business and Creator accounts
ThreadsYes (threads)Yes (threads)
LinkedInYes (linkedin), profiles and pagesYes, profile (linkedin) and company page (linkedin_page)
YouTubeYes (youtube)Shorts only (youtube)
TikTokYes (tiktok)Yes (tiktok)
PinterestYes (pinterest)Yes (pinterest)
BlueskyYes (bluesky)Yes (bluesky)
XYes (x)Yes (x)
Google Business ProfileYes (google_business)Yes (google_business)
TelegramYes (telegram)Yes (telegram), a channel or group
MastodonYes (mastodon)Yes (mastodon)
RedditListed, currently unavailableComing soon
SnapchatNot listedComing soon
DiscordYes (discord)No
WordPressYes (wordpress)No
Slack, Nostr, Lemmy, Dev.to, Hashnode, Whop, ListmonkText postsNo

What is different

  • Account connection. OmniSocials has no generate-jwt or OAuth start endpoint. Accounts are connected in the dashboard. If your product lets end users connect their own accounts through your app, OmniSocials does not support that today.
  • No profiles API. Workspaces are created in the dashboard, and each API key reaches one workspace.
  • One account per channel. A workspace posts to one account per channel ID, including one Facebook Page, one LinkedIn page, and one Google Business location. Pages cannot be picked per request.
  • JSON, not multipart. Posts are JSON. Media is a URL or an ID from an earlier upload.
  • File size. The largest file OmniSocials takes is 1 GB, through upload-from-url. Direct uploads and media_urls stop at 100 MB per file.
  • YouTube is Shorts only, up to 3 minutes. Documents must be PDF.
  • Rate limit. OmniSocials allows 100 requests per minute per key. Upload-Post documents 60 to 1,000 requests per minute, by plan and number of profiles. Limits are per key on OmniSocials, so you can split heavy work across keys. See Rate limits and errors.
  • No queue, timezone field, or idempotency key.
  • X links. X posts whose text contains a link use prepaid credits. Posts without a link do not. See X.
  • Fewer webhook events. There are no account events.
  • Error shape. Upload-Post errors use success, message, and error_code. OmniSocials errors nest under error, with code, message, and optional details. Branch on error.code.
  • Fewer channels. Discord, WordPress, Slack, and the other text-only channels are not part of OmniSocials. Reddit is not live yet.
  • No test mode. Neither API documents one. On OmniSocials, use drafts or a workspace with test accounts.
  • What OmniSocials adds. A Social inbox API for DMs and comments, approval workflows with post.approved and post.rejected events, alt text per image, PDF to carousel on Instagram, TikTok, Threads, and Pinterest, hashtag sets, and Instagram comment-to-DM automations.

Migration steps

  1. Create an OmniSocials account. Add one workspace for each Upload-Post profile.
  2. Connect each social account in the dashboard, under Settings → Organisation → Workspaces. Pick the Facebook Page, LinkedIn page, and Google Business location there.
  3. Create one API key per workspace under Settings → API. Start with posts:write, posts:read, media:write, accounts:read, and webhooks:manage.
  4. Replace each Upload-Post username in your config with that workspace's key.
  5. Call GET /accounts with each key to see the connected channels. For Pinterest, copy the board IDs from GET /accounts/{id}.
  6. Replace the four upload calls with one POST /posts/create. Send JSON. Move files to media_urls, or upload them first and pass media_ids. Rename the fields with the field mapping table.
  7. Convert scheduled_date and timezone to a UTC schedule_at.
  8. Register your webhooks with POST /webhooks. Swap the signature check and map the events.
  9. Recreate the posts that are still scheduled in Upload-Post with schedule_at. Then cancel them with DELETE /api/uploadposts/schedule/<job_id>, so nothing publishes twice.
  10. Test with drafts first, since there is no test mode. Then publish one post with publish_now: true and check published_urls on GET /posts/{id}.

Posts without schedule_at or publish_now are drafts and never publish on their own. Use them to check your field mapping against real accounts.

Last modified on October 21, 2026
From ZernioFrom Postiz
On this page
  • Concepts
  • Authentication
  • Endpoint mapping
  • Create a post
  • Field mapping
  • Media and scheduling
  • Webhooks
  • Platform coverage
  • What is different
  • Migration steps