Schemas
Pagination
totalTotal number of items
limitItems per page
offsetNumber of items skipped
has_moreWhether there are more items
Post
idPost ID
statusin_approval = waiting for a reviewer in an approval workflow; PATCH /posts/{id} can still move its schedule_at without changing this status. rejected = an approver declined the post via POST /posts/{id}/reject; it will not be published. posting = a publish is in flight. warning = some platforms published and some failed (see errors for the failures, published_urls for the successes); retry the failures with POST /posts/{id}/retry. failed = every platform failed. NOTE: a failed post whose dashboard 'retry as new post' succeeded flips to published even though it has no published_urls of its own — check retries for the post that actually carries the live URLs.
typePost type. 'reel' media must be a video (MP4/MOV) — an image is rejected with 400 validation_error at schedule/publish; use 'post' to share an image. A 'story' carries 1 to 10 media items; every item is one slide and publishes as its own story, in order.
Stories only, after publishing. Per-platform list of the published slides in publish order. published_urls keeps the first slide's URL per platform; this field has every slide.
contentPost content per platform
accountsAccount IDs to post to
Per-platform media object. Keys: default, instagram, facebook, etc. Each value is an array of {url, id, channel, alt?}.
location_idInstagram location tag (Facebook Place/Page ID), echoed back from the create/update request. Omitted when not set.
collaboratorsInstagram co-author usernames (the 'Collab' feature), echoed back from the create/update request. Omitted when none set.
Instagram photo user tags, echoed back from the create/update request. Omitted when none set.
schedule_atScheduled publish time (ISO 8601)
app_urlDeep link to open this post inside the OmniSocials app, correct for the environment (staging vs production). Draft, scheduled, and failed posts open in the composer; published posts open in the details view. Hand this to the user so they can click straight through to review a draft you just created.
Live URLs of the post on each platform after publishing. Keys are platform identifiers (facebook, instagram, linkedin, linkedin_page, youtube, tiktok, pinterest, x, threads, bluesky, mastodon, google_business). Only platforms that successfully published appear; failed platforms are omitted (see errors). Empty object {} while the post is still draft, scheduled, or processing.
retry_ofPresent when this post was created by the dashboard 'retry as new post' flow: the ID of the original failed post it retries. The live platform URLs are on THIS post's published_urls.
retriesPresent on a post that has been retried as a new post: the IDs of its retry posts (newest last). A published post with empty published_urls and retries set is a resolved failure — the actual publish lives on the retry post, so don't double-count it.
created_atapproval_statusApproval workflow status. none = no approval workflow attached. pending = waiting on an approver (post status is in_approval); act on it with POST /posts/{id}/approve or /reject. approved / rejected = the workflow finished.
Per-platform user-friendly error messages, keyed by platform identifier (facebook, instagram, linkedin, linkedin_page, youtube, tiktok, pinterest, x, threads, bluesky, mastodon, google_business). Populated when status is failed or warning. Only platforms that failed appear; successful platforms are omitted (see published_urls). null while the post is still draft/scheduled/processing or every platform succeeded. A platform's entry is removed once a retry of it succeeds (via POST /posts/{id}/retry or the dashboard). Mirrors the per-platform error a user sees in the dashboard with a Retry button.
sourceOrigin of post creation: web, api, mcp, workflow, zapier, make, n8n, etc.
updated_atxX (Twitter) options on the post. Includes per-publish settings (reply_settings, made_with_ai, paid_partnership) plus the canonical thread shape. Present when the post has X-specific data; omitted otherwise.
blueskyBluesky options on the post. Present when the post is a Bluesky thread; omitted otherwise.
mastodonMastodon options on the post. Present when the post is a Mastodon thread; omitted otherwise.
threadsThreads options on the post. Present when the post is a Threads thread (multi-post chain) or carries a location tag; omitted otherwise.
instagramInstagram options on the post. Present when set; includes first_comment (the configured auto first comment) and, after publish, first_comment_result describing the outcome.
facebookFacebook options on the post — first_comment and its post-publish first_comment_result.
linkedinLinkedIn Profile options on the post — first_comment, its post-publish first_comment_result, and carousel_as_images (present when the post opts out of the default PDF document carousel).
linkedin_pageLinkedIn Company Page options on the post — first_comment, its post-publish first_comment_result, and carousel_as_images (present when the post opts out of the default PDF document carousel).
youtubeYouTube options on the post. After publish, first_comment and its first_comment_result are nested here alongside the Shorts metadata.
tiktokTikTok options on the post. After publish, first_comment and its first_comment_result are nested here alongside the TikTok publish options. First comments need the workspace's TikTok comments authorization.
FirstCommentResult
statusposted = comment is live; failed = the main post published but the comment did not (see error; retry via POST /posts/retry-first-comment); skipped = the main post did not publish so the comment was never attempted.
pendingTikTok only. true while the comment waits for TikTok to return the final video id (status is failed with an explanatory error meanwhile); the comment is posted automatically once the id resolves, usually within minutes.
comment_idurlerrorposted_atLinkedInPollFields
questionThe poll question.
options2-4 answer options.
durationHow long the poll stays open for votes.
CreatePostRequest
contentPost content. Use 'default' for all platforms, or platform-specific keys: instagram, facebook, linkedin, linkedin_page, youtube, tiktok, pinterest, x, threads, bluesky, mastodon, google_business. Coming soon: reddit, snapchat.
accountsSocial accounts to post to. Each entry is either:
- A bare platform name (e.g.
"youtube","linkedin_page"), or - The composite ID returned by
GET /v1/accountsin the form"<workspace_id>_<platform>"(e.g."844008_youtube").
The composite form's workspace prefix must match the workspace your API key belongs to. Mismatched or unknown ids return 400 validation_error with an "Unknown account/platform" message — always source ids from GET /v1/accounts for the API key in use.
typePost type: 'post' (feed), 'story' (Instagram/Facebook), 'reel' (Instagram/Facebook/YouTube/TikTok). A 'reel' must have video media (MP4/MOV); an image is rejected with 400 validation_error at schedule/publish — use 'post' to share an image. A 'story' takes 1 to 10 media items: each item is one slide, published as its own story in the order given (Instagram and Facebook have no multi-slide story container). More than 10 returns 400 validation_error.
Media IDs from POST /media/upload. Flat array or per-platform object. Any entry may be an { id, alt } object to carry a per-media accessibility description (alt text, max 1500 chars). For type 'story', each item is one slide (max 10, published in order).
External image/video/PDF URLs to download and attach (max 10 total, each file ≤ 100 MB). Flat array or per-platform object. Any entry may be a { url, alt } object to carry a per-media accessibility description (alt text, max 1500 chars) — delivered to Mastodon, Bluesky, X, Pinterest, Instagram (images) and LinkedIn (images). When using per-platform format, 'default' acts as fallback for selected platforms without their own key. A PDF URL is rasterized into one image slide per page (max 20, in order) — on LinkedIn it publishes as a swipeable document, elsewhere as an image carousel; slides inherit the entry's alt. For files over 100 MB (up to 1 GB), upload first via POST /v1/media/upload-from-url and attach the returned media id via the media field; oversized media_urls fail with code file_too_large.
schedule_atISO 8601 datetime to schedule. Omit for draft.
publish_nowSet true to publish immediately
link_urlURL to share as a rich preview card on platforms that support link-share posts (currently LinkedIn and Facebook). When set on a text post, the URL renders as a preview tile with thumbnail / title / description instead of plain text. Ignored on platforms that don't support link shares (Instagram, TikTok, etc.) and on posts that already have media attached — media takes precedence.
link_titleOptional title for the link-share preview. LinkedIn uses this directly when set. Facebook ignores this — it fetches OG metadata server-side. Omit to let LinkedIn auto-fetch the page title.
link_descriptionOptional description for the link-share preview. LinkedIn uses this when set; Facebook auto-fetches the OG description. Omit to defer to OG metadata.
link_thumbnail_urlOptional thumbnail image URL for the preview card. Currently not yet applied to LinkedIn (would require uploading to LinkedIn's image API first); included for forward compatibility.
sourceSelf-reported origin of the integration creating this post. Defaults to 'api' if omitted. Use 'zapier', 'make', 'n8n', etc. to identify your integration.
location_idInstagram only. Facebook Place/Page ID to tag the post's location with (e.g. a dealership or storefront). Applied to single-image and carousel feed posts via Instagram's content-publishing location_id. Find a Place's Page ID via Facebook's Pages Search API. Ignored by other platforms. Send an empty string on PATCH to clear it.
collaboratorsInstagram only. Up to 3 public Instagram usernames to invite as co-authors (the 'Collab' feature). Applied to image, carousel, and reel posts — NOT Stories. Invited users get an invitation in the Instagram app; once accepted, the post also appears on their profile and feed. Usernames are case-insensitive and a leading '@' is stripped. Private accounts and non-existent usernames are rejected by Instagram at publish time. Ignored by other platforms. Send an empty array on PATCH to clear collaborators.
Instagram only. Tag public Instagram accounts at specific positions on a photo. Photos only — NOT video, reels, or stories. For a single image omit image_index (or set 0); for a carousel, set image_index to the 0-based slide the tag belongs to (tags attach to that slide's image). Public accounts only; private/non-existent usernames are rejected by Instagram at publish time. Ignored by other platforms. Send an empty array on PATCH to clear tags.
hashtag_setName of a saved hashtag set (see GET /hashtag-sets) to apply to this post, matched case-insensitively. The set's tags are merged in ONCE at create time — the post stores plain text, so later edits to the set never change this post. Tags already present in a caption are skipped (case-insensitive), and hard platform caps (Instagram 30) are enforced with a 400 hashtag_limit_exceeded before the platform can reject the post. Mutually interchangeable with hashtag_set_id.
hashtag_set_idId of a saved hashtag set to apply. Same behavior as hashtag_set; pass one or the other.
hashtag_placementWhere the set's tags land. caption_append (default) appends them to each target platform's caption after a blank line. first_comment puts them in the auto first comment on comment-capable platforms (Instagram, Facebook, LinkedIn Profile/Page, YouTube, TikTok with comments enabled) — appended after any first_comment you passed explicitly — and falls back to caption_append on platforms without a comment API. Stories always use captions (first comments are never posted on Stories).
hashtag_platformsOptional subset of the post's selected platforms to apply the set to (e.g. only ["instagram", "tiktok"]). Defaults to all selected platforms.
approval_workflow_idId of an approval workflow (see GET /approval-workflows) to route this post through. The post is created with status in_approval and approval_status: pending instead of scheduled: the workflow's first-step approvers are notified (dashboard badge, email, Slack), they review it in the dashboard's Approvals page, and it publishes at schedule_at only once the last step approves it (dashboard, or POST /posts/{id}/approve). A rejection leaves it rejected. Requires schedule_at; cannot be combined with publish_now. Errors: 404 workflow_not_found (not a workflow of this company/workspace), 400 validation_error (missing schedule_at, publish_now set, or the workflow has no approvers on its first step).
Pinterest-specific options. Attach 2–5 images via media_urls.pinterest (or the flat media_urls) to publish a single carousel pin; the title, description, link, and alt_text apply to the whole pin. A single image or a single video still publishes as a normal image / video pin. Carousel constraints: carousels hard-cap at 5 images — attaching more responds 400 validation_error at create/schedule time. Pinterest's v5 API also requires every slide in a carousel pin to share the same aspect ratio (1% tolerance). If you attach mixed-ratio images and try to schedule or publish, the API responds 400 validation_error with mismatched_slides: [n, ...] listing the 1-indexed slide numbers that need to be re-cropped or removed. Both checks run when publish_now: true, when schedule_at is set, and when PATCH flips a draft to a scheduled status — drafts are exempt so you can iterate on media.
YouTube Shorts options. Only applies when type is reel and youtube is among the selected accounts.
Instagram Reel options
Facebook options
LinkedIn Profile options
LinkedIn Company Page options
linkedin_pollNon-sponsored LinkedIn poll(s) — independent per channel, keyed by linkedin (personal profile) / linkedin_page (company page). A poll is mutually exclusive with media and a link share on that channel's post — a poll takes priority over both at publish time. Requires content.linkedin (or content.default) as that channel's caption/commentary; the poll itself only carries the question/options/duration.
TikTok options
X (Twitter) options
Bluesky options
Mastodon options
Threads options: thread mode via thread_parts, location tag via location_id.
Google Business Profile options. Use to publish EVENT or OFFER posts in addition to STANDARD, attach a call-to-action button, or both. STANDARD posts can also use this object purely to add a CTA. The shape mirrors Google's LocalPost JSONB exactly; see https://developers.google.com/my-business/reference/rest/v4/accounts.locations.localPosts#LocalPost.
Caption rules (enforced at scheduling — text that violates these returns validation_error 400 before the post is saved):
• No phone numbers in the caption (use a CALL button instead).
• No inline URLs / bare domains / email addresses (use a LEARN_MORE, BOOK, SHOP, SIGN_UP, or ORDER button instead).
• Caption max 1500 characters.
• Media optional (text-only posts allowed). If attached: exactly one JPEG/PNG/WebP image (no video, no carousels).
• The workspace must have a Google Business location selected (Settings → Organisation → Workspaces → Google Business) before scheduling.
Media
idMedia ID (use this in post creation)
urlPermanent CDN URL for the media
thumbnail_urlCDN URL of the generated preview thumbnail (videos only; null for images, which use url directly)
typenameHuman-readable label set on upload or via PATCH (e.g. "pp-play5get50"). Falls back to the storage filename when unset. Search this with the search query param.
folder_idId of the folder this file lives in, or null for the root ("All media")
filenameGenerated storage filename (stable, used internally)
sizeHuman-formatted file size (e.g. "2.50 MB")
statusProcessing state. 'ready' for normal uploads (usable immediately). Large videos uploaded via URL ingestion (over 100 MB) start as 'processing' — poll get media / list media until 'ready' before using them in a post. 'failed' means the source couldn't be fetched or validated.
created_atMediaCompatibility
compatiblesummaryOne-line human summary, or null when fully compatible.
PdfUploadResult
Every page as a Media item, in page order.
media_idsSlide ids in page order — pass all of them to POST /posts.
Whether the file fits the platforms connected to your workspace. compatible is true when no connected platform would reject it.
messageFolder
idnameparent_idParent folder id, or null for a top-level folder
item_countNumber of media items directly in this folder
created_atHashtagSet
idnameSet name, unique per workspace (case-insensitive)
hashtagsOrdered tags WITHOUT the leading '#'
hashtag_countpreviewThe tags rendered as caption text, e.g. "#fitness
created_atupdated_atAccount
idAccount ID (use this when creating posts)
platformusernameSocial media username/handle
display_nameDisplay name on the platform
profile_pictureProfile picture URL
content_typesSupported content types for this platform
statusConnection status. needs_reconnect means the account is still wired up to the workspace but its OAuth token has been revoked or expired; posts to this account will fail until the user reconnects in the OmniSocials UI. Most often caused by the user changing their password, deauthorizing OmniSocials on the platform, or the token expiring without a successful refresh.
needs_reconnectConvenience boolean — true when status is needs_reconnect.
reauth_reasonShort reason from the platform (e.g. "OAuthException: Session has expired"). Present only when needs_reconnect is true. Token-health tracking exists for Instagram, Facebook, Threads, X, Pinterest, LinkedIn (profile + page); other platforms always report needs_reconnect: false.
Pinterest boards (only present for Pinterest accounts). Use board id as board_id when creating Pinterest posts.
Platform-specific details. Present for X accounts with Premium subscription.
connected_atPostAnalytics
post_idOne entry per platform the post was published to. For thread platforms (X, Bluesky, Mastodon, Threads) a post can publish as a chain of several parts; the entry sums each part's metrics so you get the thread's total (matching the in-app analytics), and reports the thread's root as platform_post_id.
AnalyticsOverview
total_poststotal_platformstotal_engagementtotal_impressionsaverage_engagement_rateEngagement rate as a percentage (0-100)
top_performing_platformAccountAnalytics
platformplatform_account_iddatemetricsAccount-level metrics for the snapshot date, as the platform reports them. Stock values: followers, following, posts, and platform extras (monthly_views, pin_count, listed, media_count, average_rating, review_count, total_views, total_videos). Day values (period: "daily"): impressions (views), reach, engagement, likes, comments, shares, saves, profile_views, link_clicks, follows_gained, follows_lost, accounts_engaged, video_views, watch_time_minutes, and Google Business calls, direction_requests, website_clicks, bookings, impressions_breakdown, search_keywords. Audience objects when available: demographics (age, gender, country, city, or LinkedIn function, seniority, industry) with demographics_unit, online_followers (UTC hour -> followers online), link_clicks_breakdown (Threads, per URL). LinkedIn profile rows keep impressions_lifetime and carry period: "lifetime" when the daily breakdown is not available. Read the note field where present.
collected_atWebhook
idurlURL to receive webhook events
eventsEvents to subscribe to
is_activelast_triggered_atfailure_countConsecutive delivery failures since the last success. Resets to 0 on any successful delivery, so 0 means currently healthy.
last_failureDetails of the most recent failed delivery. Not cleared on success, so it persists as the last known problem even when failure_count is 0. Null if no delivery has ever failed.
created_atWebhookPayload
idUnique delivery event ID (also sent as the X-OmniSocials-Delivery header)
typeEvent type
created_atEvent payload
InboxParticipant
idPlatform-scoped id of the other party
nameusernameprofile_pictureInboxConversation
conversation_idplatformtypedm = direct message; comment/mention = public interaction. LinkedIn is comment/mention only; TikTok and YouTube are comment only; X is dm only; Threads is comment (replies on your posts) and mention only.
unread_countUnread incoming messages in this conversation
postThe post a comment/mention conversation belongs to, so a reply can be drafted with the post in view ("what size is this?" needs the caption and the picture). Null for DMs. url is the public link to the post when the platform provides one (Instagram, Facebook, YouTube, TikTok, LinkedIn, Threads); media_type is the platform's label (e.g. IMAGE, VIDEO, CAROUSEL_ALBUM on Instagram) when known.
InboxPostContext
idcaptionthumbnailImage URL of the post (or the video's cover)
urlmedia_typeInboxMessage
idconversation_idplatformtypedirectiontexttimestampis_readis_repliedreactionparent_comment_idhiddenComments only: true when the comment is hidden on the platform (see POST /inbox/messages/{id}/hide). Null for DMs.
permalinkLink to the reply or mentioning post on the platform, when known
attachmentMedia sent with this message, when present. Incoming Instagram/Facebook DM images, videos, voice messages, and story mentions are re-hosted on our CDN so the URL stays valid indefinitely (the platform's own URL is short-lived). type reflects the fetched bytes, not the platform's label: a photo the platform sent under an unlabelled attachment type is image, a story mention that is really an MP4 is video. type: file covers media we could fetch but could not classify. type: link means the platform's URL did not point at media (for example a shared post that resolves to an instagram.com page); url is then the platform's own link, not re-hosted, and may require login or expire.
postThe post a comment/mention conversation belongs to, so a reply can be drafted with the post in view ("what size is this?" needs the caption and the picture). Null for DMs. url is the public link to the post when the platform provides one (Instagram, Facebook, YouTube, TikTok, LinkedIn, Threads); media_type is the platform's label (e.g. IMAGE, VIDEO, CAROUSEL_ALBUM on Instagram) when known.
InboxNextUnanswered
The unanswered incoming message itself: the customer's latest DM, or the specific comment. Its id is what POST /inbox/messages/{id}/hide and DELETE /inbox/messages/{id} take; its conversation_id is what the reply endpoint takes.
The conversation so far, oldest first (the most recent 50 messages for long DM threads).