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
The channels the post targets, as a map of platform key to true or false. Every platform key is present; the channels the post publishes to are true. Requests send accounts as an array of account IDs instead (POST /posts/create, PATCH /posts/{id}).
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, telegram, discord). 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. GET /posts/{id}/approval returns the review itself: steps, approvers, the rejection reason and the comments.
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), the poll and 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 or carries a poll; omitted otherwise.
threadsThreads options on the post. Present when the post is a Threads thread (multi-post chain), carries a location tag or a poll; omitted otherwise.
telegramTelegram options on the post, and after publishing the result. Omitted when none are set.
discordDiscord options on the post, and after publishing the result. Omitted when none are set.
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.
The post's video cover exactly as stored; null when none was chosen.
facebookFacebook options on the post: first_comment, its post-publish first_comment_result, and the video thumbnail (thumbnail_type + thumb_offset / cover_url) when one is set.
linkedinLinkedIn Profile options on the post: first_comment, its post-publish first_comment_result, carousel_as_images (present when the post opts out of the default PDF document carousel) and document_source (present as slides when the post opts out of sending the kept original PDF).
linkedin_pageLinkedIn Company Page options on the post: first_comment, its post-publish first_comment_result, carousel_as_images (present when the post opts out of the default PDF document carousel) and document_source (present as slides when the post opts out of sending the kept original PDF).
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.
The comment-to-DM setup bound to this post, when one exists. Returned by GET /posts/{id} for a post that goes to Instagram or Facebook, and by create and update when the request carried comment_dm_automation. The fields are those of the first automation (Instagram first), plus platforms and automations (one per channel). Its post field is null here (the post is this one).
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_atVideoCoverEntry
typeframe uses the video frame at thumb_offset; custom uploads the image at cover_url.
thumb_offsetMilliseconds into the video (type frame).
cover_urlPublic image URL, JPEG or PNG (type custom).
VideoCover
typeframe uses the video frame at thumb_offset; custom uploads the image at cover_url.
thumb_offsetMilliseconds into the video (type frame).
cover_urlPublic image URL, JPEG or PNG (type custom).
Per-platform overrides keyed by platform id (instagram, facebook, linkedin, linkedin_page, tiktok, pinterest, youtube). An override wins over the base cover for that platform.
LinkedInPollFields
questionThe poll question.
options2-4 answer options.
durationHow long the poll stays open for votes.
XPoll
options2 to 4 answer options of up to 25 characters, all different.
duration_minutesHow long the poll stays open, in minutes (5 to 10080, 7 days).
ThreadsPoll
options2 to 4 answer options of 1 to 25 characters, all different.
MastodonPoll
optionsThe answer options, all different; count and length within the instance's limits.
expires_inHow long the poll stays open, in seconds, within the instance's range (default one day).
multipleAllow several answers per person.
hide_totalsHide the vote counts until the poll ends.
TelegramPoll
options2 to 12 answer options of up to 100 characters, all different.
open_periodSeconds the poll stays open (5 seconds to about 30 days). Leave out to keep the poll open.
multipleAllow several answers per person.
TelegramButton
textButton label.
urlLink the button opens: https://, http:// or tg://.
DiscordPoll
options2 to 10 answer options of up to 55 characters, all different.
duration_hoursHours the poll stays open (1 hour to 32 days).
multipleAllow several answers per person.
DiscordButton
textButton label (1 to 80 characters).
urlLink the button opens: https:// or http://.
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, telegram, discord. 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). Telegram and Discord have no reels: a reel that names them is still accepted, and they get the video as a normal post; send a video for them alone as a 'post'. 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 a draft without a date. With draft: true the time is kept but the post stays a draft (a planned draft on the calendar, see draft).
draftPlanned draft. With schedule_at, the post is stored as draft and keeps that time: it shows on the dashboard calendar at that slot with a dashed outline, the scheduler never publishes it, and a person schedules it from the composer (or you do with PATCH /posts/{id} and draft: false). Use it when an agent proposes a slot that a human should confirm. Not allowed with publish_now or approval_workflow_id (400 validation_error). Without schedule_at it changes nothing: that post is a draft already.
Image fit per channel, for feed images (type post) whose ratio is outside what a channel shows uncropped. auto (the default when omitted) takes the channel's rule: Instagram crops a tall or wide image to 4:5 / 1.91:1 around the subject (Instagram cuts it to that window anyway, and Meta cannot boost a feed post outside it); Pinterest keeps a Pin taller than 2:3 and only reports it. crop crops for that channel, keep sends the original. Every decision is reported in the response warnings with code: "image_fit". The crop is a file of its own for that channel only; default and the other channels keep the original. On PATCH, media_fit alone (no media) re-decides the stored images: keep gives the original back, crop crops an image that was kept.
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. LinkedIn uploads this image as the card thumbnail; without it, LinkedIn uses the page's Open Graph image, and when the upload fails the card has no image. Facebook ignores it and uses the page's Open Graph image.
Video thumbnail for a post whose media is one video. Applied on Instagram (feed videos and reels), Facebook (feed videos and reels), LinkedIn Profile and Page, TikTok, Pinterest and YouTube Shorts. On YouTube Shorts the cover shows only on channels where YouTube has enabled custom Shorts thumbnails (rolling out since July 2026, YouTube Partner Program channels first); on other channels YouTube stores it as the default thumbnail but shows a frame from the video on Shorts. TikTok only takes a frame, so a custom cover is skipped there (set a tiktok override with type frame to choose the frame). The per-platform reel fields (instagram.thumb_offset / cover_url, tiktok.video_cover_timestamp_ms, pinterest.video_cover) keep working and win over the base cover for their platform.
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, Telegram), 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).
comment_dm_automationA comment-to-DM automation bound to this post (Instagram or Facebook must be in accounts). When somebody comments one of trigger.keywords on the post once it is live, the account DMs them actions.dm.text, once per person, and optionally posts one of actions.public_reply.variations under the comment. On a Facebook Page the DM lands in Messenger. The shape is the AutomationInput of POST /automations without post_id, scope or kinds (always this post, comment trigger), plus platforms. The created automations come back as comment_dm_automation on the post. Needs the opt-in automations:write scope on the API key (403 insufficient_scope without it).
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
Telegram options (2026-10-17). Telegram posts go to the connected channel or group through the OmniSocials bot. Text up to 4,096 characters; with media, text over 1,024 characters is sent as a reply under the media (Telegram's caption limit). Media: up to 10 photos and videos (an album), one GIF, one video up to 50 MB, or files. No Stories. Views are not available to bots: analytics report reactions and subscribers.
Discord options (2026-10-22). Discord posts go to the channel the workspace connected, through that channel's webhook; the message shows the webhook's name and picture. Text up to 2,000 characters. Media: up to 10 images, GIFs and videos in one message (they may mix). A file over Discord's 20 MB attachment limit is sent differently: an image is re-encoded to fit, a video or GIF goes as a link in the text (listed in discord.result.video_links). No Stories; a reel is sent as one video message. Statistics: reactions and poll votes only (Discord gives webhooks no views). A sent message can be deleted at any time.
Threads options: thread mode via thread_parts, location tag via location_id, poll via poll.
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)
typedocument is a PDF kept as one item (see pdf): its id in media_ids expands into every page image, in order.
nameHuman-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_atPresent on a PDF document item (type document): the kept file and its rendered pages in order. Also present on a slide rendered from a PDF (type image): which original file and page it came from. The original PDF is kept in storage. When a LinkedIn post's images are exactly the rendered pages of one PDF, in order and unchanged, LinkedIn receives that original file (sharp text, working in-document links, the real download) instead of a document rebuilt from the page images. Opt out per channel with document_source: "slides" on the post's linkedin / linkedin_page options.
MediaCompatibility
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_atApprovalWorkflowApprover
idUser id of the approver
nameemailApprovalWorkflowStep
order1-based step order; steps are approved in order
namerequire_modeany = one approver of this step is enough; all = every approver must approve
ApprovalWorkflow
idPass this as approval_workflow_id on POST /posts/create
nameworkspace_idWorkspace the workflow is bound to, or null when it is available to every workspace of the company
created_atupdated_atAccount
idAccount ID (use this when creating posts)
platformusernameSocial media username/handle. Null where the account has none, such as a Discord channel (a server has no handle; the webhook name posts show is in platform_details.webhook_name).
display_nameDisplay name on the platform. Discord: the server name for a connection made with Continue with Discord, the webhook name for a pasted webhook URL.
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), Telegram (the bot was removed or lost the right to post) and Discord (the webhook was deleted in Discord); 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 a Premium subscription, and for every Telegram and Discord account.
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
PinterestProduct
pin_idUse this in pinterest.product_tags.
titledescriptionlinkThe product page the Pin links to.
image_urlA small image of the product Pin.
priceCatalog source only.
currencyCatalog source only. ISO 4217 code.
availabilityCatalog source only, as Pinterest reports it (for example IN_STOCK, OUT_OF_STOCK, PREORDER).
item_idCatalog source only. The merchant's own product id.
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 conversation_id is what the reply endpoint takes, and its id is the message_id to pass along with the reply for comment threads (so the reply lands under this comment and not under the newest one on the post); the same id is what POST /inbox/messages/{id}/hide and DELETE /inbox/messages/{id} take.
The conversation so far, oldest first (the most recent 50 messages for long DM threads).
Whether a reply can still be sent through the API. Only Instagram and Facebook DMs have a window (Meta: 24 hours after the customer's last message); every other item has open: true and closes_at: null. When open is false the item is still served (the customer is still waiting) but the reply endpoint answers 422 outside_messaging_window: answer it from the native app (that reply is mirrored into the inbox and clears the item) or mark the conversation read to skip it.
InboxCursorPagination
next_cursorPass as ?cursor= to fetch the next page; null when there are no more results
has_morelimitAutomationTrigger
kindsWhat starts the automation. comment = a comment on an Instagram post or reel, or on a Facebook Page post (needs scope). dm = a keyword in a DM to the Instagram account, in a Messenger message to the Facebook Page, or in a DM to the X account. story_reply = a keyword in a reply to an Instagram story (Instagram only: Facebook has no story replies, and a Facebook automation with story_reply answers 400 validation_error). On X only dm exists. One automation can listen to several. Default ["comment"] (pass ["dm"] on X).
scopeFor the comment kind: post = one post (pass post_id, instagram_media_id or facebook_post_id on the request), next_post = the next post the workspace publishes on the automation's platform, any = every post of the account or Page. Default post.
keywordsUp to 20 keywords (60 characters each), matched case-insensitively. Required unless match is any.
matchword (default) = the keyword stands on its own ("guide", "Guide!" match; "linkedin" does not match "link"), contains = the keyword appears anywhere, any = every comment or message with text.
AutomationActions
A public reply under the comment, only for the comment kind. One of variations is picked at random per comment.
AutomationLimits
max_sendsStop after this many DMs (the automation becomes completed). Omit for no limit.
stop_atStop at this time. Omit for no end.
AutomationStats
matchedsentskippedfailedlast_event_atAutomation
idtypeplatformThe channel the automation runs on: the connected Instagram account, the connected Facebook Page, or the connected X account. Set at create; it never changes.
statuscompleted = max_sends or stop_at was reached. A new limit or trigger starts it again.
namepost_idThe OmniSocials post the automation listens on, for the post scope. null for a post published outside OmniSocials and for the other scopes.
instagram_media_idThe Instagram media id the automation listens on. Set once the post is live on Instagram. Always null for a Facebook automation.
facebook_post_idThe Facebook Page post id ({page-id}_{post-id}) the automation listens on. Set once the post is live on the Page. Always null for an Instagram automation.
postA snapshot of the post: source (omnisocials, instagram or facebook: a post picked by id is read from that platform), id, caption, thumbnail_url, permalink, media_type and, for an OmniSocials post, status and live.
created_atupdated_atAutomationInput
nameA label for the automations list (max 120 characters).
platformThe channel the automation runs on. Default instagram. instagram_media_id implies instagram and facebook_post_id implies facebook; a body that names another platform answers 400 validation_error. On PATCH it cannot change: another platform answers 400 platform_immutable. x answers DMs to the connected X account: only the dm kind (X allows an automated DM only after the person DMed you), the workspace needs X DMs turned on in the dashboard (else 409 x_dms_off for an active automation; status: paused saves it), every answer ends with the line "Reply STOP to stop automatic messages.", and a person who replies STOP gets no automatic DM from the account again. X does not give apps the messages of an encrypted X Chat conversation, so those get no answer.
post_idFor scope post: an OmniSocials post (scheduled or live) that goes to the automation's platform. A post that does not go there answers 400 post_not_instagram or post_not_facebook. One automation per post and platform: a post that goes to Instagram and Facebook can have one of each.
instagram_media_idFor scope post on Instagram: the numeric id of a post or reel that was published outside OmniSocials (from the Instagram API, GET /me/media). The post is read from Instagram to check it belongs to the connected account.
facebook_post_idFor scope post on Facebook: the id of a post that was published on the connected Facebook Page outside OmniSocials. Pass {page-id}_{post-id} or the post id alone (the Page id is put in front). The post is read from Facebook with the Page token; a post of another Page answers 404 facebook_post_not_found. Implies platform: facebook. Pass one of post_id, instagram_media_id or facebook_post_id.
statuspaused creates the automation without turning it on. Default active.
AutomationEvent
idautomation_idkindWhat the person did.
outcomequeued = the answer waits for a free slot under the channel's send cap (X 15 per 15 minutes and 450 a day, Instagram and Facebook 180 an hour) and goes out within the hour, else it becomes skipped with rate_limited. opted_out = the person replied STOP on X (no automatic DMs to them from the account again).
reasonFor skipped: already_sent, limit_reached, stopped, window_passed (comment older than 7 days), rate_limited (the send cap stayed full for an hour), cannot_message (Meta refused the message: a Page made the comment, or the person's settings block messages), already_replied (the comment already has a private reply), dm_window_passed (their message is older than 24 hours), dms_closed (X refused: the person does not accept DMs from the account), no_credits (X DMs had no credits for the answer), opted_out (the person replied STOP before), automation_off (the automation was paused or finished while the answer waited). For failed: the platform's error text.
reason_labelThe reason in plain words.
trigger_idThe comment id or message id that started the event.
trigger_textThe comment or message text (300 characters). For dm and story_reply events it is returned only to a key with the inbox:read scope (OAuth: the social inbox permission); otherwise null.
messageThe DM that was sent.
public_replyThe public reply posted under the comment, when one was.
platform_message_idcreated_atsent_at