Guides

Hosted MCP server

Connect Claude and ChatGPT by signing in to Postiv, choosing a workspace, and approving access. API keys remain available for other clients.

Bring your Postiv workspace into the AI app you already use. Connect your LinkedIn profile or Company Page in Postiv first.

Connect Postiv to Claude

Open the setup link with Postiv and the server URL already filled in, then sign in. No client ID or secret needed.

Add Postiv to Claude

MCP server URL

https://postiv.ai/mcp

  1. 1
    Choose Add Postiv to Claude. Check that the name is Postiv and the server URL is https://postiv.ai/mcp, then choose Continue.
    See screenshot
    Claude with the Add custom connector dialog prefilled with Postiv and https://postiv.ai/mcp
  2. 2
    Use OAuth with automatic client registration if Claude asks how to authenticate. Leave the optional client ID and client secret blank, then finish adding the connector.
  3. 3
    Choose Connect on the Postiv connector. Sign in to Postiv, select your workspace, review the permissions, and choose Connect workspace.
    See screenshot
    Postiv consent screen showing Claude as the requesting app, the workspace picker, and Read & write or Read only permissions
  4. 4
    Enable Postiv in a new conversation and ask it to confirm your workspace and list your LinkedIn profiles.

If the link does not open the form, go to Claude → Customize → Connectors → Add custom connector, name it Postiv, and paste the MCP server URL. If Postiv already exists, keep using that connector; no reconnect is needed.

Having trouble with OAuth?

For manual setup, choose Always required and Use your own OAuth client (or open Advanced settings in older Claude versions). Enter the public client ID below and leave the client secret empty. Existing manual OAuth connections remain supported.

Public OAuth client ID

3db7f794-4990-4a61-a4e9-855d0c052eb5

Check your connection

First message to your assistant

Confirm my Postiv workspace and list my connected LinkedIn profiles. Do not create or change anything.

Permissions and reconnecting

Read & write is selected by default for new connections and allows creating, editing, deleting, scheduling, and publishing content, plus approvals and engagement actions. Choose Read only if you only need research and reporting.

Existing connections keep their original permissions. To change workspace or access, revoke the connection in Postiv and reconnect. Older Claude and ChatGPT connections using the same manual client can share an authorization, so revoking that shared authorization can disconnect both. Connections using separate automatically registered clients have separate authorizations.

Manage connected apps
Connection troubleshooting
No tools in the conversation
Refresh the connection’s tools, then enable Postiv in a new chat.
Wrong workspace or read-only access
Revoke the connection in Postiv and reconnect with the intended workspace and permissions.
Invalid redirect URI
Send the exact callback URL shown by your AI app to Postiv support.

Optional Postiv skill pack

Download the Postiv skill pack for guided content workflows. Install it through your AI app’s skill installation flow, if supported. It does not connect your account or change permissions. You can use Postiv without it.

Available tools

Tools use the approved workspace permissions. Normal tools return data without UI. Only show_post, show_image, show_carousel, show_inspiration, show_visual_templates, and show_media_upload open widgets. render_carousel prepares exports without displaying them. Refresh your connector to load these tool definitions; upload_media is a deprecated non-rendering handoff.

ToolScopeDescription
show_postposts:readOpen an editable card for an existing post id. Ordinary create/get/update calls do not display UI.
show_imageposts:readDisplay a saved image using source=image or asset and its id. Does not generate or edit.
show_carouselposts:readDisplay current saved carousel/infographic exports. Run render_carousel first if exports are missing or stale. Showing does not render.
show_inspirationinspiration:readDisplay ordered hit IDs from search_inspiration. Pass the same integrationId for private tracked creators (a LinkedIn profile or company page; LinkedIn only).
show_visual_templatesposts:readDisplay a template picker by format, optionally selecting styleIds and layout slideIndices. Selection does not authorize creation.
get_visual_template_pageposts:readApp-only pagination within an open picker. Returns previews without opening another widget.
upload_mediaposts:writeDeprecated, non-rendering handoff. Call show_media_upload to open the picker.
list_team_engagementsengage:readList queued engagements, eligible acting accounts, and Slack channels for a Postiv postId (LinkedIn or X), optionally narrowed to one acting account (integrationId) or channel. Each profile row has channel. A channel or account that differs from the post's channel is 400 channel_mismatch. With integrationId, Slack shares are omitted. GET /api/public/team-engagements?postId=UUID.
queue_team_engagementengage:write, posts:scheduleQueue an explicitly approved like, comment, reshare, or Slack share after publication. LinkedIn reshares create linked calendar posts with normal approvals, optional thoughts, and require a scheduledTime ISO timestamp at least two minutes in the future. They never publish before the source succeeds; if the source is late, they publish when it succeeds after the requested time. POST /api/public/team-engagements accepts postId, action, integrationId (the acting account, on the post's channel: an X account for an X post) or channelId, message, delayMinutes (0–1440), scheduledTime for reshares, and a UUID idempotencyKey. Comments require text; optional reshare thoughts must be user-approved. On X posts only repost (the teammate’s own X account reposts, no text), quote (that account publishes message followed by a link to the original post, which X shows as a quote; scheduledTime required) and slack are accepted; like and comment return X_ACTION_NOT_AVAILABLE. X reposts and quotes skip approvals, so an X account that requires approval is refused with 422 x_share_requires_approval. Reuse the key only for an identical request.
cancel_team_engagementengage:writeCancel a waiting or pending engagement by id. DELETE /api/public/team-engagements with {id}. Already sending or completed engagements cannot be cancelled.
resolve_linkedin_mentionprofiles:readLinkedIn only: an X account returns linkedin_only. Resolve a LinkedIn person, company, school or showcase URL using the posting integrationId (a LinkedIn profile or company page). Returns a URN and ready-to-insert mention token for create_post/update_post captions or comment_on_post/reply_to_comment text. Optional displayName controls the label. Personal URL lookup requires Community Management access and an administered page; unresolved URLs fail explicitly. Comment/reply tokens are converted into LinkedIn mention attributes; plain @Name is not a tag. MCP only.
suggest_replyengage:writeGenerate a reply suggestion for a comment on a workspace post from the stored post text, live comment and selected profile voice. Does not publish. Not available on X (X_ACTION_NOT_AVAILABLE). MCP only.
list_engagement_postsengage:readTeam (including your own LinkedIn profiles/pages and X accounts) or external-feed discovery. Post text and counts come from Postiv's stored records with collectedAt; neither LinkedIn nor X is read for post content. LinkedIn team comment threads and unanswered counts refresh live; X threads and mentions are stored data from periodic syncs, never a live X read. Items have channel (X items also kind, post or mentions) and results may include xInbox and xInboxNote. channel narrows the list and authorIntegrationId may be an X account. source=feed is LinkedIn only (channel x returns 400 linkedin_only). unansweredCount includes X. status=unanswered; author/list/creator/text/engagement filters; days and before/nextCursor pagination. Failed posts appear in failedItems with partial=true; a page where every post fails returns an error. MCP only.
get_post_commentsengage:readRead the complete comment thread of a workspace post by opaque postId. LinkedIn threads refresh live; X threads (replies and mentions) come from stored inbox rows with collectedAt, never a live X read. Returns commentId, parentCommentId, status and unansweredCount. commentId is a LinkedIn comment URN, or x:<accountId>:<tweetId> for X. Reading does not dismiss. External feed posts have no readable thread (external_comments_unavailable). MCP only.
comment_on_postengage:writeImmediately publish a top-level LinkedIn comment using postId, integrationId and text (1–1250 characters). X has no top-level comment (422 X_ACTION_NOT_AVAILABLE): use reply_to_comment. MCP only.
reply_to_commentengage:writeWorkspace posts only. On LinkedIn: live-check commentId on postId, automatically prefix a real tag of the comment author when their name and URN are available, publish a reply as integrationId, then refresh the thread. Pass the reply body without that prefix; existing leading author tags are not duplicated. The 1250-character limit includes the added name. On X: allowed only as a reply to a mention or reply, from the account that received it (commentId x:<accountId>:<tweetId>); text is plain, up to 280 weighted characters (a link counts 23), with no auto-prepended tag. X refuses imageSource, likeParentOnReply and LinkedIn mention tokens (400 linkedin_only). Invalid text returns invalid_comment_mention or invalid_comment_length. Published-with-warning results must not be retried. MCP only.
react_to_postengage:writeReact to postId, or to a commentId on a workspace post, as integrationId; reactionType=null removes. Not available on X (422 X_ACTION_NOT_AVAILABLE). MCP only.
dismiss_commentengage:writeMark a team comment no reply needed in Postiv, on LinkedIn or X; clears unanswered status without changing LinkedIn or X. MCP only.
delete_commentengage:writeDelete the actual LinkedIn comment using commentId and integrationId. Requires this authenticated actor’s recorded comment; supports both sources and new replies. Not available on X (422 X_ACTION_NOT_AVAILABLE). MCP only.
list_engage_feed_listsengage:readList current workspace external-feed tracking lists. LinkedIn only.
create_engage_feed_listengage:writeCreate a tracking list, maximum five per workspace. LinkedIn only. MCP only.
add_engage_feed_profileengage:writeTrack a personal LinkedIn profile, maximum thirty per list. LinkedIn only: an X URL returns linkedin_only. Discovery can be pending. MCP only.
remove_engage_feed_profileengage:writeRemove a profile from one tracking list. LinkedIn only. MCP only.
list_creator_groupsinspiration:readList the workspace creator groups with their profiles, post counts and latest post. MCP only.
get_creator_group_postsinspiration:readRead one creator group feed, 24 posts per page, filtered by member, time range, search and outliers (3x a creator’s usual engagement), sorted by recent or engagement. MCP only.
create_creator_groupinspiration:writeCreate a creator group: up to 30 groups, 30 profiles per group and 50 distinct profiles per workspace. MCP only.
update_creator_groupinspiration:writeChange a creator group; profileUrls replaces the member list. MCP only.
delete_creator_groupinspiration:writeDelete a creator group; creators and collected posts are kept. MCP only.
track_creatorinspiration:writeFollow a creator in the Inspiration library for a LinkedIn profile owner, by creatorId or profile URL. LinkedIn only: integrationId is a LinkedIn profile or company page, and an X account returns linkedin_only. MCP only.
untrack_creatorinspiration:writeStop following a creator in the Inspiration library for a LinkedIn profile owner. LinkedIn only: an X account returns linkedin_only. MCP only.
list_tracked_creatorsinspiration:readList the creators a LinkedIn profile's owner tracks in the Inspiration library: creatorId, name, handle, headline and followers. LinkedIn only: an X account returns linkedin_only. Read their posts, including outliers, with search_inspiration. MCP only.
get_workspaceworkspace:readRead the connected workspace (name, slug) and which scopes this key has. With profiles:read it also returns the connected LinkedIn and X accounts (workspace.accounts, workspace.socialSets). Call first.
submit_feedbackfeedback:writeSend explicit feedback about Postiv or Bob to the product team.
add_knowledgeknowledge:writeAdd a text document to the workspace knowledge base for retrieval by Postiv's AI.
search_knowledgeknowledge:readSemantically search the workspace knowledge base before drafting, to ground content in real facts.
search_templatesposts:readSearch Postiv's proven post-writing templates (global + workspace custom).
search_inspirationinspiration:readSearch the moderated inspiration library as data. Returns stable hit IDs; show_inspiration displays selected cards. The private tracked-creator integrationId is a LinkedIn profile or company page (LinkedIn only; an X account returns linkedin_only).
list_social_accountsprofiles:readList the connected LinkedIn profiles, company pages and X accounts with their integration ids. Each account has id, channel, provider, profileType (personal, team_member, organization_page or x_account), parentIntegrationId, name, username (X handle), headline, picture, status and socialSetId. socialSets groups the accounts of one brand, such as a LinkedIn profile and its X account. channel (linkedin or x) narrows the list, omit it for both; any other value returns 400 invalid_channel. status error on an X account means it needs reconnecting in Postiv and cannot be scheduled.
get_writing_styleprofiles:readRead the trained writing style for one account (a LinkedIn profile, company page or X account): voice, structure, examples. The result carries channel and a note; hasWritingStyle=false means no style is trained yet, so write naturally. An unknown or inaccessible account returns 404 integration_not_found.
list_content_plansplans:readList Bob's weekly content plans for an account, with pillar distribution. Bob's planner does not produce X plans yet, so an X account's plans are usually empty. An unknown account returns 404 integration_not_found.
get_content_plan_itemplans:readRead one plan item in full detail, including saved source material/research and the account's channel.
get_bob_planning_settingsplans:readRead Bob's status, cadence, pillar count, and current-week plan state for an account. For an X account generatesAutomatically stays false because Bob does not plan X posts yet.
update_bob_planning_settingsplans:writeUpdate Bob's posting cadence for an account. The cadence saves for an X account too, but Bob does not plan X posts yet.
list_pillarsplans:readList an account's recurring content pillars (summary only). An account with no pillars of its own, typically an X account linked to a LinkedIn profile, shows its social stack's shared pillars; pillarSource (account, set or none) says which.
get_pillarplans:readRead one pillar's full content and 30-day performance. Pass integrationId when the pillar came from list_pillars with pillarSource set.
list_team_briefsteam_briefs:readList team writing assignments and per-member progress.
get_team_briefteam_briefs:readRead one team brief's full instructions, deadline, and assignment progress.
create_team_briefteam_briefs:writeCreate a team writing assignment for every current workspace member (owners/admins only).
create_pillarplans:writeCreate a recurring content pillar for one account (LinkedIn profile, company page or X account). Creating the first pillar for an account that only shares its stack's pillars gives it its own, which then take precedence. The result carries channel.
update_pillarplans:writeUpdate an active content pillar while preserving system-owned learnings. Only an account's own pillars can be edited here; shared ones (pillarSource set) cannot.
archive_pillarplans:writeSoft-delete a pillar from future weekly planning. Only an account's own pillars can be archived here; shared ones (pillarSource set) cannot.
list_pending_approvalsapprovals:readList exact scheduled-post copy, refreshed media, carousel PDF, author/account details, and approval history awaiting the API-key actor's decision, for LinkedIn and X posts. Each row has channel. X rows carry format plus tweets or headline/body and no media columns: mediaType and mediaUrls are null, and mediaMetadata is only the Comment Plug override. channel and integrationId narrow the list; an account decides the channel, and a channel that contradicts it returns 400 channel_mismatch.
approve_scheduled_postapprovals:writeRecord the API-key actor's approval of a scheduled LinkedIn or X post without bypassing other approvers.
request_approval_changesapprovals:writeReturn a pending LinkedIn or X post to its author with revision feedback.
deny_scheduled_postapprovals:writeDeny an assigned scheduled LinkedIn or X post and prevent publishing.
create_scratchpad_itemscratchpad:writeSave a quick note/url/image into the org's shared scratchpad.
list_scratchpad_itemsscratchpad:readList all live scratchpad items.
update_scratchpad_itemscratchpad:writeEdit a scratchpad item's content and/or status.
delete_scratchpad_itemscratchpad:writePermanently delete a scratchpad item.
promote_scratchpad_itemscratchpad:write, knowledge:writePromote a scrap into a permanent org knowledge asset (deletes the scrap on success).
get_comment_plug_configprofiles:readRead default Comment Plug settings for one or all accounts (LinkedIn profiles and X accounts). Each row has channel and plugReady: LinkedIn needs cmmConnected, an active X account is always ready. An X plug posts as a self-reply to the first tweet. channel narrows the list.
set_comment_plug_configposts:scheduleSet an account's default Comment Plug (auto first-comment) used by future scheduled posts, for LinkedIn or X. cmmConnected is required only for enabled LinkedIn configs. X variants must fit an X reply: 280 characters, a link counts 23.
create_postposts:writeCreate a LinkedIn or X post draft. content is LinkedIn post text; for an X account it is plain text that is auto-split into tweets. For an X account pass exactly one of content, tweets (a string, or an array for a thread) or article ({ headline, body }, body in markdown). humanize and templateId are LinkedIn only (400 humanize_linkedin_only, template_linkedin_only). X drafts save as written: tweets over 280 characters are allowed in drafts, but scheduling refuses them. Results carry channel and format. For LinkedIn, the humanizer is opt-in (default false) and the supplied hook is saved as-is.
list_postsposts:readList ALL workspace posts (LinkedIn and X) one cursor-paged page at a time: published (including posts imported from LinkedIn that were never created in Postiv), scheduled, draft and failed. Filter by status, channel, account, search and period or start/end; sort by date (newest first) or rank published posts by impressions, engagements or the LinkedIn outlier sorts (a metric sort lists published posts only; with another status it is 400 invalid_sort_for_status; outlier sorts on X only are 400 unsupported_sort). Returns { posts, nextCursor, total }: repeat with nextCursor and the same filters until it is null (an invalid or mismatched cursor is 400 invalid_cursor). Each post has id (for get_post), postivPostId, analyticsPostId, channel, profile, a 300-char contentPreview, postUrl and delivery (latest publish attempt); status failed also returns scheduled posts whose latest delivery failed. Published posts carry metrics (impressions, engagements, engagementRate, reactions, comments, reshares) and, on LinkedIn, outliers, null when not measured; without analytics:read the metrics are left out.
get_postposts:readRead one post in full by a Postiv post id or an analytics post id (a post imported from LinkedIn). Returns the current content and status; an X post carries format and tweets (each { text, assets, length }), or for an article headline, body (markdown), cover, images and paragraphCount; content is plain text. parentPostId links the versions of one post across accounts. delivery describes the latest publish attempt: a failed or partially published post keeps status scheduled. A published post also carries analytics: full metrics, outliers, media URLs and refresh. LinkedIn posts get a live refresh attempt with an explicit cached fallback; X posts are never refreshed live (refresh.status is cached with reason x_periodic_sync) and only X posts published through Postiv are measured. Without analytics yet: analytics null plus analyticsUnavailableReason. Without analytics:read the analytics are left out. Unknown id: 404 post_not_found.
update_postposts:writeUpdate a draft's title/content/account; fails on scheduled/published posts. An X post takes tweets (replaces all tweets; a tweet that omits assets keeps its images, assets: [] removes them) or article (headline and markdown body; cover and inline images are kept). Omit body (or send it back unchanged) to keep the body exactly as it is. content is LinkedIn only (X returns 400 x_content_shape). Reassignment stays within a channel: use add_post_version to move a post to another channel (400 channel_mismatch), and an X post cannot be unassigned. Pass latestVersion from get_post/show_post as expectedVersion to avoid overwriting newer edits; a stale version returns 409 version_conflict with the current content (details.current, details.latestVersion). Title-only and account-only updates ignore it. Relays 400 invalid_x_content (details.issues).
add_post_versionposts:writeCreate a linked draft of the same post for another account (LinkedIn to X, X to LinkedIn, LinkedIn to LinkedIn), seeded from the source post including its image; the source post is untouched. Pass the copy already adapted for the target channel and voice (content for a LinkedIn target, tweets for an X target), never the unadapted source copy. Returns { post, rootId, issues }: when issues is set the draft kept a mechanical placeholder, and update_post with tweets fixes it. Errors: version_exists (409, that account already has a version of this post), unsupported_post_type (carousels and articles cannot get versions yet), integration_not_found, x_tweets_required (X target needs tweets), linkedin_content_required (LinkedIn target needs content), content_required, content_conflict (pass exactly one of content or tweets), invalid_integration_id, subscription_required (402). MCP only.
schedule_postposts:scheduleQueue a draft for publishing on LinkedIn or X (>=2min in the future); waits for approvers if configured. mediaType image/carousel, mediaUrls, mediaSource, carouselId and mediaData other than commentPlug are LinkedIn only (X returns 400 x_media_not_supported; X images live inside the post). commentPlug on X: each override comment is max 280 chars (invalid_comment_plug) and is posted as a self-reply to the first tweet. An X draft needs an X account, a LinkedIn draft a LinkedIn account. On LinkedIn, mediaSource also accepts exactly one url, assetId, imageId, or carouselId for PDF/video/image/carousel/infographic selection through the existing publish queue. Do not combine mediaSource with mediaType/mediaUrls/carouselId. When media is omitted, the image, video, PDF or carousel saved on a LinkedIn draft is included automatically.
unschedule_postposts:scheduleCancel a scheduled post, returning it to draft. An X post that is already sending, or whose thread is partly live, returns 409 x_delivery_started.
reschedule_postposts:scheduleMove a scheduled post to a new time. An X post that is already sending, or whose thread is partly live, returns 409 x_delivery_started.
generate_post_imageimages:writeGenerate and attach a new image, returning its saved ID and URL without UI. Use show_image for review. On LinkedIn the image is added after the images already on the post (up to 20; 409 image_limit_reached when full, before credits are spent); detach_post_media by imageId removes an old one. On an X post pass tweetIndex, or articlePlacement (cover or inline) with afterParagraph: the image is placed in the post's own tweet or article and editor-added images are kept. In a thread every tweet can have its own image: a tweetIndex replaces only a generated image already on that tweet. A scheduled or published X post is refused before credits are spent. x_image_not_placed (409) means the image is saved and attach_post_media with its imageId finishes it.
edit_post_imageimages:writeEdit an existing image with a natural-language instruction, stacking a new version. On an X post the edited version replaces the image in place, and the call is refused if the post is scheduled or published, or if the image was removed from the post (then use generate_post_image). x_image_not_placed (409) means the edit is saved and attach_post_media with its imageId finishes placing it.
list_visual_templatesposts:readList template IDs and metadata without previews. Carousels and infographics list Freeform (global:freeform, no template) first. Use show_visual_templates to open the picker.
get_visual_templateposts:readRead exact layout fields, examples and length guidance without generating previews. For global:freeform it returns the Freeform outline contract. Use show_visual_templates for visual inspection.
create_carouselposts:writeCreate a multi-slide carousel from a structured content outline (content only, never HTML). LinkedIn only: an X account returns 400 linkedin_only. styleId global:freeform designs every slide from scratch, with search-only images from per-slide assetHints.
create_infographicposts:writeCreate a single-canvas infographic (content only, never HTML), publishes as an image post. LinkedIn only: an X account returns 400 linkedin_only. styleId global:freeform designs the whole page from scratch, with search-only images from outline.assetHints.
render_carouselposts:writePrepare current PNG/PDF exports without UI. Use show_carousel to display saved exports.
get_carouselposts:readRead one carousel/infographic's slide summaries and render/PDF readiness.
edit_carousel_slideposts:writeEdit one slide (or the infographic canvas) with a natural-language instruction.
get_carousel_designposts:readRead a compact canvas object map, palette and baseVersionId without displaying images.
edit_carousel_designposts:writeApply exact design ops (set, image, hide/show, delete, add, replaceColor, order) to one slide as one version.
list_analytics_accountsanalytics:readList tracked analytics accounts for LinkedIn profiles/pages and X accounts, each with platform. channel and integrationId narrow the list. X accounts carry tracking, budgetState and a lastImport that is the last X sync; an X account without analytics returns 404 analytics_not_set_up.
get_analytics_summaryanalytics:readCached KPI totals for one account or 'all', over a period or date range. Data comes from LinkedIn imports or the periodic X sync, never a live X read. 'all' answers per channel and never sums LinkedIn and X: with both it returns { platform: 'all', channels: { linkedin, x } }. channel narrows 'all'; with a specific accountId it must match that account's channel (400 channel_mismatch). X summaries use likes, reposts, replies, quotes, bookmarks, linkClicks and profileVisits; followers is null.
get_performance_overviewanalytics:readCached day-by-day impressions/engagements time series. Same channel rules as get_analytics_summary: 'all' answers per channel, never summed, and channel narrows it. X series are by publish day, not by the day engagement happened.
get_top_postsanalytics:readDeprecated, kept for chats that still hold the old tool list: use list_posts with status published and a sort. Top posts of one analytics account or 'all' by date, engagements, impressions or the LinkedIn outlier sorts.
get_post_analyticsanalytics:readDeprecated, kept for chats that still hold the old tool list: use get_post, which returns the post with the same analytics and live LinkedIn refresh.
list_post_versionsposts:readList the stack of a post: the linked versions of one post across accounts and channels (for example a LinkedIn post and its X version), created with add_post_version. Pass any post of the stack. Returns rootId and versions, root first, each with postId, parentPostId, channel, type, format (X only), status, title, integrationId, a compact account and queue (the latest publish attempt: status, scheduledTime, lastError; null if never scheduled). No content: use get_post. A post from another workspace returns post_not_found. MCP only.
schedule_post_versionsposts:scheduleSchedule several drafts of one stack in a single call, each at its own scheduledTime and through its own account. Pass postId (any post of the stack) and items of { postId, scheduledTime, carouselId? }; carouselId (LinkedIn only) publishes that carousel with the item, and every version of one stack can publish the same carousel. The rules of schedule_post apply to every item: at least 2 minutes in the future, nothing publishes immediately, approvers wait for approval, X tweets over 280 characters cannot be scheduled. Every item is validated before anything is scheduled; a problem rejects the call with batch_validation_failed and details.results (scheduled_time_in_past, invalid_scheduled_time, not_in_family, not_draft, account_not_connected, empty_post_content). After that the posts are scheduled one by one and the call is not all-or-nothing: results holds one entry per post with outcome scheduled, pending_approval or error (error.code, error.message, for example a permission denial), and success is true only when every post was scheduled. Failed posts are not retried or rolled back. No Comment Plug, media overrides other than carouselId, publish now or integrationId here: use schedule_post for per-post options. Each LinkedIn post includes the image, video, PDF or carousel saved on its draft, as schedule_post does: a saved carousel must be rendered first or that post fails with carousel_pdf_not_ready. MCP only.
show_media_uploadposts:writeShow an inline Postiv file picker and drop zone in the conversation. Uses the MCP connection without another sign-in. Up to 20 files; images 10 MB, PDFs 50 MB, videos 200 MB. Saved asset references return to the conversation. Use when the assistant cannot read the file bytes. On an X post attach_post_media adds an uploaded image to a tweet (up to 4) or the article, or an uploaded MP4/MOV video alone to a tweet (tweetIndex says which).
prepare_media_uploadposts:writeBackground upload: request a signed multipart POST form for fileName, contentType, and bytes. Send all fields plus the file bytes, then call complete_media_upload. Also used by the inline widget.
complete_media_uploadposts:writeFinalize a transferred uploadId after server-side size, signature, actor and workspace checks. Returns a reusable assetId; retries return the same asset. Does not attach, schedule, or publish.
get_media_upload_linkposts:readLegacy web-page fallback when explicitly requested; prefer show_media_upload for the inline card. Open a workspace-specific browser page to drag and drop or select a local image (10 MB), PDF (50 MB), or video (200 MB). Sign in with the same Postiv account as the assistant. After upload, paste the asset reference back into the conversation. The assistant can use assetId to attach an image, video or PDF or mediaSource.assetId to schedule media after authorization. No public hosting required. MCP only.
list_mediaposts:readBrowse reusable images, PDFs, videos, carousels, and infographics. GET /api/public/media supports type, query, limit, and offset. Results include image, video, PDF and draft-carousel attachInput, scheduleInput for all formats, and signed preview/file URLs.
attach_post_mediaposts:write, images:writeAttach an image, video, PDF or library carousel to a draft using exactly one url, assetId, imageId, or carouselId and postId, without scheduling or AI generation. POST /api/public/posts/:id/media. On LinkedIn images, videos, PDFs and carousels persist on unscheduled drafts like the editor (a PDF publishes as a document post): an image is added after the images already on the draft (up to 20 publish as one multi-image post; 409 image_limit_reached past that) and replaces only a carousel, video or PDF, while a carousel, video or PDF replaces everything. To swap an image, attach the new one and detach_post_media the old one by imageId. On an X post it ADDS the media and keeps what is already there: an image to a tweet (max 4) or the article, or one MP4 or MOV video alone in a tweet (409 x_tweet_media_conflict when a tweet would mix them); pass tweetIndex, or articlePlacement (cover or inline) with afterParagraph. X takes images and MP4/MOV videos only (400 x_media_not_supported for PDF, carousel or infographic). media.assetId is the asset in the post (pass it to detach_post_media); media.imageId is the working image for edit_post_image. Remote raster images: 10MB; remote PDFs: 50MB; remote videos: 200MB. Infographics use schedule_post.mediaSource on LinkedIn, matching the editor scheduling flow. A scheduled or published X post returns 409 post_media_locked.
detach_post_mediaposts:writeRemove draft media without deleting its library file. DELETE /api/public/posts/:id/media. On a LinkedIn draft pass imageId (from get_post images) to remove that one image and keep the others, or omit it to remove all images, the carousel, the video and the PDF (an assetId returns 400 asset_id_not_supported; an imageId not on the draft is 404 image_not_on_post). On an X post assetId is required (400 asset_id_required): pass the assetId of the image or video to remove, from get_post tweet or article images or media.assetId. Only that one goes; the text and the other media stay.