studio_list
Read saved carousels, thumbnails, channel art, generation progress, the shared AI credit balance and, for a key or app, today's AI-credit ceiling. Results belong only to this credential's profile.
For agents and developers
The same reference your agent reads. Plain text: /hub/llms.txt. MCP: https://www.mellow.world/mcp.
studio_list
Read saved carousels, thumbnails, channel art, generation progress, the shared AI credit balance and, for a key or app, today's AI-credit ceiling. Results belong only to this credential's profile.
studio_quote
Get the exact credit charge before generating. No credits are spent. AI-designed carousel: 2 + 10 per slide, requires count. Text/own-photo carousel outline: 2; thumbnail (cover) or illustration: 10 per variant; channel banner: 15 per variant; channel avatar: 10 per variant. A change or an improvement to a thumbnail is one image. Manual edits, export, imports and faces are free. A key or app also sees what its daily AI-credit ceiling leaves today.
studio_generate
Starts durable AI generation. Requires ai:generate AND posts:write. Quote first; pass maxCredits and a stable idempotencyKey. Ask before spending unless already delegated. kind=carousel creates 2–10 AI-designed slides, words set in one design system (optional design: a style id, or auto; a style reference image is followed), for 2+10*count credits. design=panorama draws ONE continuous 3D scene cut into the slides and sets every word in code, exactly as written: text in quotation marks in the topic is kept word for word and a number appears only if the topic has it. It takes kind=carousel, format 4:5, count 3–5 and no reference images, at the same price; anything else is refused with studio_panorama_unsupported. kind=outline uses text and optional own photos for 2 credits. kind=cover makes a video thumbnail (10 per variant): mode new (engine direct or design), remix (sourceAssetId plus faceAssetIds or characterDescription) or edit (editAssetId, at most 1 editReferenceAssetIds; a topic starting with [CTR_IMPROVE] carries a review's numbered commands). kind=banner (15) and kind=avatar (10) make YouTube channel art; brand is the channel name, tagline the banner's second line. illustration on a designed carousel redesigns that slide in its saved style. The thumbnail tools (studio_thumbnail, studio_thumbnail_remix, studio_thumbnail_edit, studio_thumbnail_improve, studio_banner, studio_avatar) are simpler doors to the same generation. References must belong to this profile. For illustration supply projectId and slideId. Failures refund once and retain completed material; the same key never charges twice. Poll studio_job. A ready result with applied=false is saved separately because newer user edits were retained. Export and publishing are separate actions.
studio_job
Read a saved generation. queued/planning/generating/saving are in progress; ready returns the saved result (a thumbnail's variants too), failed means credits were returned. This does not start another generation.
studio_project
Read a carousel, thumbnail or channel art document and revision. Text, slide order, style, format and this profile's image references are editable with studio_save. A thumbnail keeps variants (every version one request made) and history (each image it has been, oldest first: save slides[0].imageAssetId as one of them to go back). A Panorama (document.panorama present) keeps each slide's label, heading, emphasis (words of the heading set on a colored box) and blocks — up to 3 of note, pills, stat, board, steps, prompt, buttons: note {text, small?}, pills {items}, stat {value, label, small?}, board {items: two {label, value, win?}}, steps {items}, prompt {who, text}, buttons {items: two}. zone is where the art begins (pixels from the top of 1080×1350); the words are fitted above it. Its art cannot be redrawn one slide at a time.
studio_save
Save an edited Studio document at its current revision. Refuses stale revisions and image IDs belonging to another profile. Manual editing is free. No publishing or AI generation occurs. A Panorama (document.panorama present) keeps each slide's label, heading, emphasis (words of the heading set on a colored box) and blocks — up to 3 of note, pills, stat, board, steps, prompt, buttons: note {text, small?}, pills {items}, stat {value, label, small?}, board {items: two {label, value, win?}}, steps {items}, prompt {who, text}, buttons {items: two}. zone is where the art begins (pixels from the top of 1080×1350); the words are fitted above it. Its art cannot be redrawn one slide at a time. studio_export then sets the saved words exactly.
studio_export
Render the saved revision to ordered JPEG slides (free). Returns stable image URLs, caption and a thumbnailUrl for thumbnails. Channel art is exported at its own size: a banner at 2560×1440, an avatar at 800×800; Hub does not set them on the channel, the person uploads them in YouTube Studio. Use carousel media in validate_post/create_post; attach a thumbnail as thumbnailUrl on the VIDEO media item, not as a replacement for the video. Does not publish. Unsupported channel thumbnail formats are still governed by list_platforms.
studio_import
Bring a picture into this profile's Studio as a private image, for free: a YouTube video's own thumbnail (only from YouTube's image host; the same link gives the same image), a file you uploaded with request_upload_url (its mediaUrl), or the picture behind a public link (url: a picture's address, or a page that names one for sharing). Give exactly one. Returns its assetId for referenceAssetIds, studio_faces, styleFrom, a remix source or a change reference.
studio_faces
The creator's saved faces: list them, add one of this profile's images (studio_import first) with a name, or remove one. Up to 12 per profile; a thumbnail, banner or avatar takes up to 2. Free. Adding and removing need media:write; removing takes a face off the list and the image stays private to the profile.
studio_thumbnail
Make 1–3 new video thumbnails from an idea. Thumbnails are made the YGen way: with engine=direct (the default without a look) the person's words go straight to the image model — put words for the picture in quotation marks and they are rendered; engine=design (the default with styleFrom) has Mellow's art director write the image prompt from the look. Variants are made in parallel for one reservation (10 credits each). Requires ai:generate and posts:write, maxCredits and an idempotencyKey. Never buys credits and never publishes: the result is a Studio project; poll studio_job, then studio_export and create_post. Faces put the creator in; styleFrom borrows a look.
studio_thumbnail_remix
Remake a thumbnail the person likes with the creator in it: the source's composition, framing, palette, lighting and type style are kept; every person in it becomes the creator (saved faces) or the described character; logos, watermarks and channel names are removed; its words become the person's own (in quotation marks in changes) or new words of the same length and tone. 10 credits per variant. Thumbnails are made the YGen way: with engine=direct (the default without a look) the person's words go straight to the image model — put words for the picture in quotation marks and they are rendered; engine=design (the default with styleFrom) has Mellow's art director write the image prompt from the look. Variants are made in parallel for one reservation (10 credits each). Requires ai:generate and posts:write, maxCredits and an idempotencyKey. Never buys credits and never publishes: the result is a Studio project; poll studio_job, then studio_export and create_post.
studio_thumbnail_edit
Change one thing in a project's current thumbnail and keep the rest (YGen's Refine): 10 credits, one image. referenceAssetId adds a person or an object to put in; faceIds put the creator in. The change is added to the thumbnail's history, so the original stays one save away. Thumbnails are made the YGen way: with engine=direct (the default without a look) the person's words go straight to the image model — put words for the picture in quotation marks and they are rendered; engine=design (the default with styleFrom) has Mellow's art director write the image prompt from the look. Variants are made in parallel for one reservation (10 credits each). Requires ai:generate and posts:write, maxCredits and an idempotencyKey. Never buys credits and never publishes: the result is a Studio project; poll studio_job, then studio_export and create_post.
studio_thumbnail_improve
Apply the latest review's edit commands to a project's current thumbnail (YGen's "Improve with recommendations"): 10 credits, one image. Review the thumbnail first with studio_thumbnail_review; a review that found nothing to change is answered with studio_review_nothing_to_improve. Thumbnails are made the YGen way: with engine=direct (the default without a look) the person's words go straight to the image model — put words for the picture in quotation marks and they are rendered; engine=design (the default with styleFrom) has Mellow's art director write the image prompt from the look. Variants are made in parallel for one reservation (10 credits each). Requires ai:generate and posts:write, maxCredits and an idempotencyKey. Never buys credits and never publishes: the result is a Studio project; poll studio_job, then studio_export and create_post.
studio_banner
Make 1–3 YouTube channel banners, 15 credits each: drawn at 2K and exported at exactly 2560×1440, with the channel name, the tagline, faces and key subjects inside the centre band every TV, computer and phone shows. Export only: the person uploads it in YouTube Studio. Requires ai:generate and posts:write; never buys credits.
studio_avatar
Make 1–3 channel avatars (profile pictures), 10 credits each: a 800×800 square that still reads inside a circle at 48 px — the creator's face, or an emblem or monogram from the name. Export only. Requires ai:generate and posts:write; never buys credits.
studio_thumbnail_review
Design review of one YouTube thumbnail or vertical cover, free (no credits; counted as AI writing under fair use). Name exactly one picture: assetId (an image of this profile), projectId (a Studio thumbnail's current image) or youtube (a video link; its thumbnail is kept as this profile's private image). A 24-item checklist for 16:9 or a 23-item one for 9:16 (format; otherwise read from the picture) returns overall_score out of 10 — the thumbnail's strength —, six category scores (null where there is no text or no face), strengths, exactly 0 or 2 improvements with matching edit_commands, three title ideas that complement the picture, and a one-line summary, in language. Below 8 the improvements apply in one edit with studio_thumbnail_improve (10 credits; improve.topic is what it sends); at 8 and above make a new version instead. The score is design feedback, not measured clicks or a CTR prediction: never present it as one. YouTube's own Test & Compare measures clicks. A stored review of the same image is returned as it is (cached: true) unless videoTitle is given.
studio_thumbnail_ideas
Three to five thumbnail ideas for a video, free (no credits; counted as AI writing under fair use). Each is a catchy title and a complete visual prompt — who is in it, emotion and pose, background, colours and light, any text — ready to pass as studio_generate's topic with kind=cover. Without a topic the ideas are general. Nothing is generated or saved.
whoami
The current profile's ID and name, and what this credential is allowed to do: its mode (autopilot publishes; review only prepares), its scopes, the channels it can reach, how many posts it has left today, and whether the account's subscription allows publishing at all. Call this before anything else — it answers the questions you would otherwise discover by being refused.
list_platforms
Every network Mellow publishes to and the rules it enforces: caption limits, media counts and kinds, required fields, available placements. With each: the video file the network's API takes (length, size, frame, type) and how often it takes a post, from the network's own pages. Read this instead of guessing a limit.
list_channels
The owner's connected accounts, with the channel IDs you name in a post. Pass refresh: true after a person has just connected something, to re-read from the provider rather than the local copy. needsReconnect: true means the network refused the account's sign-in on its last post: tell the person to sign in to it again. signIn.endsSoon: true means the sign-in is dated to end within a week (signIn.endsAt): tell them before it does. A Threads channel says chains: ready or needs_connection: a chain (options.threads.thread) is published only through the profile's own Threads connection, which a person makes once in Accounts.
connect_channel
Returns a link a PERSON must open to connect a network. You cannot complete this yourself: every network asks a human to sign in. Bluesky is connected on Mellow Hub's Channels page, where the person types the handle and an app password; never ask for a password in the chat. Telegram is connected inside Telegram: the link opens Mellow's bot, where the person presses Start and picks their channel. Give the link and the instruction to the person, then call list_channels with refresh once they say they are done. Each profile supports one Instagram. For another Instagram, the owner must create a new profile in Hub and authorize a separate credential there.
register_media
Checks that a public https URL can be fetched and reports what it is. Nothing is copied — the network fetches the URL when it publishes. If you hold bytes rather than a URL, call request_upload_url instead.
request_upload_url
A signed URL to PUT file bytes to, plus the media URL to use in a post afterwards. Use this for anything you hold as bytes, and for any video: the file goes straight to storage and never through Mellow.
validate_post
Checks a post against every channel it names and publishes NOTHING. Returns every problem at once, each naming the channel and the field. Call this before create_post every time — it costs nothing and it is the difference between fixing a post once and learning the rules by publishing badly.
preview_post
Renders what the post will look like on each network, without publishing. Use it when the question is how something will read rather than whether it is allowed; validate_post answers the second.
create_post
Publishes to every named channel, or schedules it with scheduledAt. THIS IS PUBLIC AND CANNOT BE UNDONE once a network has published. idempotencyKey is required: derive it from the content or the task, not at random, so a timeout you retry returns the original post instead of publishing a second one. Under a review-mode credential this prepares the post and stops for a person to approve.
get_post
The post and its per-channel outcome, with the public link where a network published. Read targets, not just status: partial means some channels succeeded and republishing everything would duplicate them.
list_posts
Recent posts, newest first, optionally filtered by status. Use it to find a post after a timeout.
reschedule_post
Moves an existing scheduled post to a future ISO 8601 time. Keeps its caption, media and destinations. Drafts and published posts cannot be rescheduled. Under a review-mode credential a scheduled post cannot be moved: its time was approved with it. Requires access to every destination and the owner's subscription allowance.
update_post
Changes a saved post in place, keeping its id: caption, media, channels, per-network settings and time. Send the whole post as for create_post — what is left out is removed. Works on drafts, posts awaiting approval and scheduled posts; a post a network has already published, one going out right now, or one handed over in parts is refused. draft: true takes a scheduled post back to a draft. Under a review-mode credential an edited post keeps waiting for approval, and a scheduled post cannot be changed. Run validate_post first. Moving a post without changing it is reschedule_post.
retry_post
Sends a post again to the networks that did not take it; where it is already out, nothing changes. Mellow Hub sends a busy network, an unprocessed file and a network's limit again by itself first, so use this for a channel that still reads failed in get_post. Without postId: every post of the profile with a channel that failed in the last seven days, oldest first, an account's posts ten minutes apart. channels narrows one post to some of its failed channel ids. Refused for a channel whose account's sign-in has run out (the person signs in again; the post is kept for three days and then goes out by itself) or whose account is no longer connected (a person chooses what to do). A review-mode credential cannot send again: that is the person's to press. An agent may send one network of one post again three times.
post_results
One post's results, one line per network: where it went, its status, views, likes and link. The question 'how did my post do?' is answered by this, not by get_metrics. postId is optional: without it, the most recent published post. A TikTok reads 'sent' until TikTok names the video. Hosts that draw MCP Apps show it as a card.
account_overview
The profile at a glance: its connected networks, posts published and scheduled, publications left this month, views over the last 30 days per network and the best post (with metrics:read), and the honours those numbers earned. The answer to 'how is my account doing?'. Hosts that draw MCP Apps show it as a card.
studio_templates
Creative Studio's ready setups: a slide the Studio made, its look, story, slide count, format and a brief with [slots] to fill. Show them when someone wants a carousel or cover and has no idea yet; choosing one in the card sends its brief to the chat. Generate with studio_quote, then studio_generate using the template's design, story, count and format. Free to call.
get_metrics
Reads recent published posts and network-reported metrics for the channels this credential can reach. Optional channelId narrows the result. Missing readings remain missing; reporting distinguishes ok, empty, unsupported and failed. Requires metrics:read.
cancel_post
Withdraws a post that has not gone out yet. A post a network has already published cannot be cancelled through any API — that has to be done in the network itself, by a person.
list_autoreplies
Reads the Instagram accounts connected for auto-replies, the rules that answer their comments and direct messages, and what the rules answered recently. A rule has keywords, public reply variants and, where the account allows messages, one private message. Set posts: true to also list an account's recent posts with the ids a rule can listen on. If no account is listed, a person connects one in Hub under Auto-replies; an agent cannot, because the consent is Instagram's. Requires posts:read.
create_autoreply
Creates a rule that answers Instagram comments or direct messages containing one of its keywords, with the words given here, in the account's name. source comment (the default): each matching comment gets one public reply, picked from replies, and — if the account can message — the one private message Instagram allows per comment. source message: each matching direct message gets one answer from replies, at most once per person an hour. Whole words match, in any case. Under an autopilot credential the rule is live at once and answers real people in public; under a review-mode credential it is saved off and a person turns it on in Hub. Read the account and its posts with list_autoreplies first. Requires posts:write and posts:publish.
update_autoreply
Changes a rule's keywords, replies, private message or post, or turns it on or off with enabled. Send only what changes. A review-mode credential may turn a rule off, and change one that is off; it may not turn one on or change one that is live — a person does that in Hub. Requires posts:write and posts:publish.
delete_autoreply
Deletes a rule. Comments and messages it already answered stay answered. Requires posts:write and posts:publish.
list_comments
Reads the connected Instagram account's recent comments (the last 7 days, newest first), each with its id, post, text, time, and whether it has been answered (by a rule, by an earlier reply, or by a reply on Instagram). `privateReplyOpenUntil` is when Instagram stops allowing a private reply to it (7 days). Set unansweredOnly to see what still waits for an answer. Needs the account connected for auto-replies in Hub. Requires posts:read.
reply_to_comment
Answers one comment in the account's name: a public reply (`text`), the one private message Instagram allows per comment within 7 days of it (`privateMessage`, where the account is connected with direct messages), or both. A comment is answered once: one a rule, the catch-up or an earlier reply has answered is refused (already_answered). It goes to a real person under the person's name, so it needs an autopilot credential (the person's delegation), counts against the profile's daily ceiling of answers, and is in the journal under this credential; a review-mode credential reads with list_comments and a person answers. Requires posts:write and posts:publish.
list_messages
Reads the connected Instagram account's recent direct conversations, newest first: who the other person is, the last message and who wrote it, and, when they wrote last, until when Instagram lets the account answer (24 hours after their message). Set waitingOnly to see only the conversations that wait for an answer. Needs the account connected with direct messages in Hub. Requires posts:read.
reply_to_message
Sends one direct message to a person who wrote to the account within the last 24 hours (Instagram's rule; checked first, nothing is sent otherwise). `recipientId` is the participantId from list_messages. It goes to a real person under the person's name, so it needs an autopilot credential, counts against the profile's daily ceiling of answers and is in the journal under this credential; a review-mode credential reads and a person answers. Requires posts:write and posts:publish.
mark_post_finished
Marks a post the person puts up themselves — a Reddit post Hub prepared, or an Instagram post finished in the Instagram app — as posted, with the post's own address as proof: `url`, an instagram.com post or reel, or a reddit.com thread. Hub cannot see those posts, so the address is what it keeps (and the journal names this credential). The channel then reads published. Needs an autopilot credential: a review-mode credential cannot say a post is out, a person marks it in Hub. Requires posts:write and posts:publish.
read_audit_log
Reads the journal of this credential's own actions, newest first: what it did, on which network and post, and how each ended (no captions, no media, no secrets). It does not show other credentials or the person's own actions: an agent checks what it did, the owner reads the rest in Hub under Agents & access. Requires posts:read.
catch_up_autoreplies
Reads the account's recent posts and their comments from Instagram and lists the ones from the last 7 days that an auto-reply rule that is on would answer and nobody has: comments that came before the rule was made, or while it was off. Instagram allows one private reply per comment within 7 days of it, so the oldest listed close their window first. By default it only PREVIEWS. With send: true it QUEUES them (up to a hundred): each commenter gets the rule's public reply and its private message, once, oldest first, a few every minute with pauses so it reads as answers and not a burst, whether or not anyone keeps a page open; `waiting` is what is still in the queue. Sending needs an autopilot credential (the person's delegation; a profile's answers are capped per day); a review-mode credential previews and a person sends from Hub under Auto-replies ("Reply to older comments"). Requires posts:read to preview, posts:write and posts:publish to send.
Resources mellow://guide/* — limits, errors and worked examples. Connect an agent
Publish one post to every network you are connected to — Instagram, TikTok, YouTube, X, LinkedIn, Threads, Bluesky, Pinterest, Facebook and Telegram — through one API call, with each network's own rules checked before anything goes out.
Base URL: https://www.mellow.world/api/hub/v1 MCP endpoint: https://www.mellow.world/mcp
whoami — what this credential may do, which channels it can reach, and how many posts are left today. Call it first; everything else depends on the answer.list_channels — the connected accounts. Each has an id beginning spc_; that is what you name in channels.register_media — if the post has media. Any public https URL works and nothing is copied: the network fetches it when it publishes. For bytes you hold, ask for an upload URL and send the file straight there.validate_post — free, publishes nothing, and returns every problem at once. Do this before create_post every time. It is the difference between fixing a post once and discovering the rules by breaking them publicly.create_post — publishes now, or schedules for later.get_post — the result per channel, with the public link.You cannot do this. Every network makes a person sign in, Bluesky asks for a handle and an app password typed into Mellow, and a Telegram channel's owner lets Mellow's bot into the channel inside Telegram itself. connect_channel returns a URL and a sentence explaining who has to open it — pass both on and wait. When the person is done, list_channels shows the new channel.
Studio creates AI carousels and video thumbnails. The Studio tabs are Carousels, Thumbnails and Gallery; the API still uses cover for a thumbnail. Its saved projects, reference images and jobs are private to the selected profile; the login account shares one credit balance across profiles. The current catalog is available at https://www.mellow.world/api/hub/v1/pricing and https://www.mellow.world/hub/pricing.
studio_list to read designs, job status and the wallet.studio_quote with kind carousel (and a count), outline, cover or illustration. A designed carousel costs 2 credits for its story plus 10 per slide — 32 for three. An outline costs 2; one cover or illustration costs 10. An outline creates editable text, not one generated image per slide.studio_generate requires ai:generate plus posts:write, a stable idempotencyKey, explicit maxCredits, and a request with kind, topic, format and style. Use the formats/styles returned by the quote. For an outline, count is 2–10. Reference asset IDs must belong to this profile.studio_job by jobId. Closing a tab does not cancel a saved job. Failed jobs return reserved credits once. Retry the same request with the same key after a lost response; do not create a second paid generation.studio_project, then use studio_save with the current revision. Editing text, ordering slides and changing style is free. A stale revision is refused. If AI finishes while a user edits, the saved job result remains available without replacing newer edits.studio_export renders ordered JPEGs at a saved revision, for free. Use the carousel URLs in validate_post. For a cover, attach thumbnailUrl to the VIDEO media item; keep the original video. Export never publishes.Panorama (design: "panorama") draws one continuous 3D scene across the whole carousel and sets every word in code over it, exactly as written: put exact copy in quotation marks in the topic, and a number appears only if the topic has it. It takes kind carousel, format 4:5, 3–5 slides and no reference images, at the same price; anything else is refused with studio_panorama_unsupported. Its slides keep a label, a heading, the heading's emphasis and typed blocks (note, pills, stat, board, steps, prompt, buttons) that studio_save edits for free; the art is one picture and is not redrawn slide by slide.
Thumbnails are made the way YGen makes them: the person's own words go straight to the image model inside YGen's template (engine: "direct", the default), so write the idea as they said it and put the words for the picture in quotation marks — they are rendered. With a look (styleFrom) Mellow's art director writes the image prompt instead (engine: "design").
studio_thumbnail — { topic, format, variants, faceIds?, styleFrom?, maxCredits, idempotencyKey }. 10 credits a version; variants up to 3 makes them at once for one reservation (30 for 3). The result lists every version in variants.studio_thumbnail_remix — a thumbnail the person likes (source: { youtube } or an imported assetId) remade with the creator in it: its composition, palette, light and type style stay; every person becomes the creator (saved faceIds) or a characterDescription; logos, watermarks and channel names go; its words become the person's own (quoted in changes) or new words of the same length and tone. 10 credits a version.studio_thumbnail_edit — { projectId, change }: one thing changes, the rest stays. 10 credits. referenceAssetId adds a person or object.studio_thumbnail_improve — { projectId }: applies the latest studio_thumbnail_review's commands to the current image, 10 credits. Review first; a review that found nothing to fix answers studio_review_nothing_to_improve.studio_banner — { channelName, tagline?, about?, styleFrom?, faceIds? }: a 2560×1440 YouTube channel banner with the name, the tagline and the faces inside the centre band every device shows. 15 credits.studio_avatar — { name?, faceId?, styleFrom?, background? }: a 800×800 square that reads inside a circle. 10 credits.studio_import brings a YouTube video's thumbnail, or a file put through request_upload_url, into Studio for free; studio_faces lists, adds and removes the creator's saved faces (up to 12).Every one of them is poll-and-export: studio_job until ready, then studio_export. Banners and avatars are files to upload in YouTube Studio; Hub does not set them on the channel. A thumbnail's history lists each image it has been, oldest first: saving slides[0].imageAssetId as one of them with studio_save goes back to it, for free.
A key or app that may spend AI credits also has a daily ceiling of them, chosen when it was made (200 offered). studio_quote and studio_list say what is left today (ceiling.leftToday); a generation past it is refused with 429 daily_credit_limit, nothing reserved, and only the owner can issue a key with a higher one. insufficient_credits (402) means the shared balance is short: credits are bought by the owner in the Hub, never by an agent.
Formats: 4:5, 1:1, 9:16, 16:9. Horizontal YouTube video is supported; square or vertical videos up to three minutes may be classified as Shorts by YouTube. The connected account's restrictions and per-network validation still apply.
Existing keys do not automatically gain AI permission: POST /assistant needs ai:generate. AI writing — captions, hashtags, titles, ideas, a review and assistant replies — is included in every plan and costs no credits; it is bounded by fair use, 36 requests an hour and 40 a day for one profile (15 more a day per further profile), answered with 429 and a retry time. An account without a plan gets 402 plan_required. Legacy active subscribers keep their existing assistant access. Included credits renew monthly; purchased credits do not expire. Buy credits or change a plan only through the owner's Hub UI, never through an agent.
A post has one caption, one media list, and a list of channels. Where a network genuinely differs, say so in options, keyed by platform:
{
"caption": "The same thought, everywhere.",
"media": ["https://cdn.example.com/clip.mp4"],
"channels": ["spc_instagram", "spc_youtube", "spc_bluesky"],
"options": {
"instagram": { "placement": "reels" },
"youtube": { "title": "The same thought", "privacyStatus": "public" }
},
"perChannel": {
"spc_bluesky": { "caption": "The same thought, in 300 characters." }
}
}
options applies to every channel of that network. perChannel applies to one channel and wins over options — it is how you give Bluesky a shorter caption without shortening the post everywhere.
What you do not fit, Hub fits for each channel when it checks and sends the post, and says so in validate_post's notes (adapted_*): a caption over the limit ends at its last whole sentence that fits, closing hashtags kept; a network that takes one file gets the first; a YouTube title comes from the caption's first line; a Pinterest video gets its first frame as cover. What would have to be invented — a video for YouTube, media for Pinterest — is still an issue.
The notes also say what may go wrong on an account before the post is sent to it: its sign-in has run out (channel_needs_reconnect) or is dated to end before the post is due (channel_sign_in_ends), one of its posts is waiting for the network's limit right now (network_limit_waiting, with until), or some of its posts had to wait for that limit in the last seven days (network_limit_recent). None of them stops the post, and Hub sends again by itself what a network refuses for any of them. Tell the person the post may go out later than planned, or move it, before you publish.
And they say what a video file is against what its network takes: Hub reads an MP4's or MOV's length, frame and weight from the file's header, without downloading it, and notes media_outside_limit when one is outside a limit the network's API publishes, or media_limit_depends when it depends on the account. Hub does not change a file: give the channel one that fits.
create_post requires an idempotency key, and it is not decoration. If your request times out you do not know whether it published; retrying with the same key returns the original post instead of making a second one. Use a key derived from the content or the task, not a random value per attempt. Reusing a key for *different* content is refused, because that is a bug worth seeing.
Give scheduledAt an ISO 8601 timestamp to publish later; omit it to publish now. Cancelling works while a post is still scheduled. Once a network has published there is no unpublishing it through any API — Mellow will say so rather than pretend.
Each channel succeeds or fails on its own. A post to five networks where YouTube rejects the title and the other four publish comes back as partial, with the failure named on the YouTube channel and public links on the rest. Read targets, not just status.
A key is a delegation with edges: the channels it may touch, whether it publishes on its own (autopilot) or only prepares a post for a person to approve (review), and how many of its posts may go out on one day. whoami reports all of them.
A post counts on the UTC day it goes out: its scheduledAt, or the moment it is created when it goes out at once. So a month of two posts a day fits a limit of two, planned in one sitting. A cancelled or failed post keeps its place on its day; a refused request costs nothing. validate_post says when a day is already full, and moving a post into a full day is refused like creating one. Everything done with the key is recorded in a journal the owner reads, and revoking a key takes effect immediately.
Channel limits apply to input checks, previews and stored posts too. Reading, retrying, moving or cancelling a stored post requires every destination in that post to be inside the grant. Restricted lists omit posts spanning other channels; the owner can still see them in Hub.
mellow://guide/platforms — every network's limits and required fields.mellow://guide/errors — what each refusal means and what to do about it.mellow://guide/recipes — worked examples for the common jobs.These are the rules Mellow checks before it sends anything. A post that passes validate_post has already satisfied everything on this page. Of the file itself Mellow reads a video's length, frame and weight from its header and says so in a note when one is outside a limit the network's API publishes (media_outside_limit); codecs and the network's own processing remain the network's judgement, which no API can answer in advance.
Each network below also says the video file its API takes and how often it takes a post, from the network's own pages, with the page and the day it was read. Where a network publishes no figure the line says so; none is borrowed. When a network refuses a post for its limit, Mellow Hub does this by itself: waits for the network’s limit to start over and sends it then, up to three times. The post shows until when it waits. For this account's own record, read the notes: network_limit_waiting and network_limit_recent say what its queue has met.
instagram)Connecting. A professional (Business or Creator) Instagram account. A personal account cannot publish through any API.
Needed to start the connection:
connection_type — Instagram login is the direct route and the default. Facebook login is for accounts reached through a Page. One of: instagram, facebook.Caption. Up to 2200 characters.
Media. At least 1, at most 10; image or video. Stories take exactly one item. Reels take one video.
Placement. timeline, reels, stories.
Video file. Through its API (Instagram Reels): 3 seconds to 15 minutes · up to 300 MB · 0.01:1 to 10:1 · up to 1920 pixels wide · MP4 or MOV. Read 2026-10-07 on Meta for Developers: Instagram Graph API, IG User media (reel specifications).
How often. Instagram takes 100 API-published posts from an account within a 24-hour moving period; a carousel counts as one. Read 2026-10-13 on Meta for Developers: Instagram Platform, Content Publishing.
Trial reels. trialReelType makes a reel a trial: Instagram shows it first to people who do not follow the account. manual keeps it with them until the owner shares it with their followers from the Instagram app; performance lets Instagram share it with the followers by itself if it does well within 72 hours. It applies only to one video posted as a reel (placement reels, or timeline, where a single video goes out as a reel). A story, a carousel or a picture with a trial is refused (trial_needs_reel) — a picture wherever Mellow can tell it is one — because the trial would be dropped and the post would reach the followers as an ordinary one. Instagram gives trial reels only to accounts with enough followers. Where it gives none — Hub's own bar is 200 followers, read where Hub can read the count, and otherwise Instagram's refusal is the answer — or the day's trials are used up, a trial reel is NEVER turned into an ordinary one by Hub on its own: the target fails, saying so, and nothing is posted. Only ordinaryIfTrialRefused: true (off unless set) lets it go out as an ordinary reel to the account's followers instead, and its settings then carry trialReelDeclined: true.
Finished in the app. Instagram's API publishes a file with the sound it already has: a sound from Instagram's library, or another creator's original audio (the sound of a trend), can only be chosen in the Instagram app. finishInApp: true leaves the post for the person to finish there: Hub never sends it to Instagram; at the post's time it sends them, in a message they read on their phone (a chat with Mellow where the account has one, otherwise email), the video or pictures, the caption to copy and soundUrl — the sound's page, https://www.instagram.com/reels/audio/… or a reel that uses it, which the phone opens in the Instagram app. The channel then reads publishing until the person says it is out (the button under the message, the post's link sent back, or Mellow Hub), then published. Other networks of the same post go out as usual. Hub cannot see the post in the app, so it is never marked out by itself. soundUrl without finishInApp is only noted: the reel goes out with the sound in its file.
Supports. schedule, carousel, thumbnail, collaborators, mediaTags, metrics.
tiktok)Connecting. A personal or creator TikTok account.
Caption. Up to 2200 characters.
Title. Optional, up to 90 characters. Used as the headline on photo posts.
Media. At least 1, at most 35; image or video. One video, or up to 35 images as a photo post. Videos and images cannot be mixed.
Video file. Through its API (TikTok): up to 3 minutes, or 10 minutes for some accounts · up to 4 GB · 360 to 4096 pixels each way · MP4, WebM or MOV. Every creator can post 3 minutes through TikTok’s API; some can post 5 or 10 minutes. Read 2026-10-07 on TikTok for Developers: Content Posting API, media transfer guide.
How often. TikTok limits the posts made to a creator account through its API in a 24-hour window. The limit varies among creators, typically around 15 a day, and is shared across every app that posts for the account. Read 2026-10-13 on TikTok for Developers: Content Sharing Guidelines.
After sending. TikTok reviews every video before anyone else can see it, usually within minutes, and does not tell Mellow when it is done, so a TikTok reads as sent rather than live and links to the profile. An account whose region is Russia cannot publish through an app: TikTok blocks the video as created in Russia, while the same account's posts from a phone abroad go out. Some accounts can change the region (Settings and privacy → Account → User information → Account region), and many registered in Russia have no such item; for those, set isDraft so the video lands in the TikTok inbox and is posted from the phone. A song baked into the file that you don't hold the rights to can get a video muted; in a draft, a sound from TikTok's library can be added instead.
Promotion. A post that promotes a product, business or service has to say so, and TikTok labels it: discloseYourBrand when it promotes your own ("Promotional content"), discloseBrandedContent when another brand pays or gifts you for it ("Paid partnership", which cannot be private). Both may be set. Sent with neither, a promotional video is flagged by TikTok itself, and its owner is asked in the app to disclose it within 24 hours or its reach in For You may be limited.
Supports. schedule, draft, carousel, metrics.
tiktok_business)Connecting. A TikTok Business account. Use it when you need business analytics; otherwise the ordinary TikTok connection is simpler.
Caption. Up to 2200 characters.
Title. Optional, up to 90 characters.
Media. At least 1, at most 35; image or video. One video, or up to 35 images as a photo post.
How often. TikTok limits the posts made to a creator account through its API in a 24-hour window. The limit varies among creators, typically around 15 a day, and is shared across every app that posts for the account. Read 2026-10-13 on TikTok for Developers: Content Sharing Guidelines.
After sending. TikTok reviews every video before anyone else can see it, usually within minutes, and does not tell Mellow when it is done, so a TikTok reads as sent rather than live and links to the profile. An account whose region is Russia cannot publish through an app: TikTok blocks the video as created in Russia, while the same account's posts from a phone abroad go out. Some accounts can change the region (Settings and privacy → Account → User information → Account region), and many registered in Russia have no such item; for those, set isDraft so the video lands in the TikTok inbox and is posted from the phone. A song baked into the file that you don't hold the rights to can get a video muted; in a draft, a sound from TikTok's library can be added instead. A Business account may use only TikTok's Commercial Music Library, so any other song is outside its rules.
Promotion. A post that promotes a product, business or service has to say so, and TikTok labels it: discloseYourBrand when it promotes your own ("Promotional content"), discloseBrandedContent when another brand pays or gifts you for it ("Paid partnership", which cannot be private). Both may be set. Sent with neither, a promotional video is flagged by TikTok itself, and its owner is asked in the app to disclose it within 24 hours or its reach in For You may be limited.
Supports. schedule, draft, carousel, thumbnail, metrics.
youtube)Connecting. A Google account with a YouTube channel. Uploads count against the channel's daily API quota.
Caption. Up to 5000 characters. Becomes the video description when no explicit description is given.
Title. Required, up to 100 characters. YouTube refuses an upload without a title.
Media. At least 1, at most 1; video. Exactly one video, including landscape. YouTube classifies eligible square or vertical videos up to three minutes as Shorts; there is no separate Shorts endpoint.
Video file. Through its API (YouTube Shorts): length not published · up to 256 GB. Read 2026-10-07 on YouTube Data API: Videos: insert.
How often. YouTube gives an API project 100 video uploads a day by default, shared by everybody who uploads through that project; the day starts over at midnight Pacific Time. Read 2026-10-13 on YouTube Data API: Quota calculator.
Required options. title.
Supports. schedule, thumbnail, metrics.
x)Connecting. Hub posts through its provider's X app, so you need no X developer account or API credits of your own.
Needed to start the connection:
connection_type — OAuth 2.0 is the default. OAuth 1.0a exists for apps still on the older credentials. One of: oauth2, oauth1.Caption. Up to 280 characters. 280 is the limit for a standard account, counted the way X counts: a link is 23 however long it is, and an emoji or a Chinese, Japanese or Korean character is 2. A premium account may write far more, but Mellow cannot see the account's tier, so anything longer is reported rather than silently sent.
Media. Optional, at most 4; image or video. Up to four images, or one video. Text on its own is fine.
Video file. Through its API (X): 0.5 seconds to 20 minutes, or 125 minutes for some accounts · up to 8 GB, or 16 GB for some accounts · 1:3 to 3:1. Without Premium, X’s API takes 20 minutes; with Premium, 125 minutes. A scheduler cannot see which an account has. Read 2026-10-07 on X Developer Platform: media upload best practices.
How often. X gives an unverified account 50 original posts and 200 replies a day, split into half-hour limits. Read 2026-10-13 on X Help Center: About X limits.
Supports. schedule, carousel, poll, metrics.
linkedin)Connecting. Posts as your personal profile, or as a company page you administer.
Needed to start the connection:
connection_type — A personal profile posts as you. A company page posts as the page and needs you to be one of its admins. One of: organization, personal.Caption. Up to 3000 characters, and required. LinkedIn publishes nothing without commentary.
Media. Optional, at most 20; image or video. Up to twenty images, or one video.
Video file. Through its API (LinkedIn): 3 seconds to 30 minutes · up to 500 MB · at least 75 KB · MP4. Read 2026-10-07 on LinkedIn API documentation on Microsoft Learn: Videos API.
How often. LinkedIn does not publish its limits: its documentation says so, and that they are counted over 24 hours for an app and for each member, and start over at midnight UTC. Read 2026-10-13 on LinkedIn API documentation on Microsoft Learn: Rate limiting.
Supports. schedule, carousel, metrics.
threads)Connecting. The Threads account attached to your Instagram login.
Caption. Up to 500 characters. Counted the way Threads counts: an emoji is its size in UTF-8, so 👇 is 4.
Media. Optional, at most 20; image or video. Text on its own is fine. Up to twenty items in a carousel.
Placement. timeline, reels.
Video file. Through its API (Threads): up to 5 minutes · up to 1 GB · 0.01:1 to 10:1 · up to 1920 pixels wide · MOV or MP4. Read 2026-10-07 on Meta for Developers: Threads API overview, media specifications.
How often. Threads takes 250 API-published posts from a profile within a 24-hour moving period, a carousel counting as one, and 1,000 replies. Read 2026-10-13 on Meta for Developers: Threads API overview, rate limiting.
Chains. A chain is a post and the posts that follow it in the same thread, each a reply to the one before: put them in options.threads.thread (or perChannel.<id>.thread) as a list of strings or { text, media } objects, in order. The post's own caption and media are the first of the chain; thread is what follows, up to 24 posts, each up to 500 characters (an emoji counts as its size in UTF-8) with at most one picture or video of its own. The first post must stand alone. A chain is published through the profile's own Threads sign-in through Mellow, beside the provider's channel — a person makes it once in Accounts ("Enable chains"); list_channels says chains: ready or needs_connection on each Threads channel, and a chain for a channel that is not ready is refused when the post is made (threads_chain_needs_connection), before anything goes out. A chain is one publication in the plan, goes out on Hub's own queue at the post's time (not the provider's), and is journaled. Each part is published in order; targets[].thread says how many posts the chain has and how many are on Threads. If one part fails the rest wait: the channel fails naming the part, what is out stays out, and retry_post continues from that part and never posts the first again. A chain that has begun cannot be edited, moved or cancelled. A post with no thread is an ordinary Threads post. Threads allows 250 posts and 1,000 replies per profile in 24 hours.
Supports. schedule, carousel, metrics.
bluesky)Connecting. Hub connects Bluesky with your handle and an app password rather than a sign-in screen, so an agent cannot complete this step alone.
Needed to start the connection:
handle — Your full Bluesky handle, for example name.bsky.social.app_password — Create one in Bluesky under Settings → App Passwords. Never your account password — an app password can be revoked on its own.Caption. Up to 300 characters, and required. Bluesky counts graphemes, the characters as you see them: an emoji counts once, however it is built.
Media. Optional, at most 4; image or video. Up to four images, or one video.
Video file. Through its API (Bluesky): length not published · size not published. Read 2026-10-07 on Bluesky documentation: Uploading video.
How often. Bluesky counts points for an account: 5,000 an hour and 35,000 a day, three for each record created, which is at most 1,666 records an hour and 11,666 a day. Read 2026-10-13 on Bluesky documentation: Rate limits.
Supports. schedule, carousel, metrics.
pinterest)Connecting. A Pinterest business account with at least one board to pin to.
Caption. Up to 500 characters. Becomes the pin description.
Title. Optional, up to 100 characters.
Media. At least 1, at most 1; image or video. One image or one video per pin. A video needs a cover: give the media item a thumbnailUrl.
Video file. Through its API (Pinterest): 4 seconds to 5 minutes · size not published · MP4, MOV or M4V. Read 2026-10-07 on Pinterest Help: Review Pin specs; Pinterest Developers: Create boards and Pins (video Pins).
How often. Pinterest publishes no number of Pins a day. For an app with Standard access it takes 100 requests a minute from a user for creating, editing or deleting boards and Pins. Read 2026-10-13 on Pinterest Developers: Rate limits.
Supports. schedule, metrics.
facebook)Connecting. A Facebook Page you administer. Personal timelines cannot be published to through the API.
Caption. Up to 63206 characters.
Media. Optional, at most 10; image or video. Stories take exactly one item. Reels take one video.
Placement. timeline, reels, stories.
Video file. Through its API (Facebook Reels): 3 to 90 seconds · size not published · at least 540 × 960. Read 2026-10-07 on Meta for Developers: Reels Publishing API, video specifications.
How often. Facebook’s Reels API takes 30 API-published reels within a 24-hour moving period. That page gives no figure for a Page’s other posts. Read 2026-10-13 on Meta for Developers: Reels Publishing API.
Supports. schedule, carousel, thumbnail, collaborators, mediaTags, metrics.
telegram)Connecting. A Telegram channel you administer. You add Mellow's bot to it with one right, to post messages; Mellow never sees your Telegram account.
Caption. Up to 4096 characters. Up to 1,024 characters sit under the media as its caption; a longer text follows the media as a message of its own. The text is read for a few marks and sent with Telegram's styles: bold, __italic__ or _italic_, ~~struck~~, ||hidden||, ` code , words, and a line that begins > as a quote. The marks are not counted in the limit, and \` before one keeps it as typed. Only Telegram reads them: the other networks of a post are sent the same text as typed, so give a styled text to the Telegram channel as its own caption.
Media. Optional, at most 10; image or video. Text on its own is fine. Up to ten items as an album. A video of up to 50 MB and a picture of up to 10 MB.
Video file. Through its API (Telegram): length not published · up to 50 MB · MP4; another format may arrive as a file. Read 2026-10-13 on Telegram Bot API: sendVideo.
How often. Telegram publishes no number of posts a day for a channel. It asks a bot to send no more than one message a second in one chat, and answers with an error to a bot that keeps going past that. Read 2026-10-13 on Telegram Bots FAQ: My bot is hitting limits.
Supports. schedule, carousel.
Every error carries a code, a sentence, and retryable. Trust retryable: if it is false, the same request will fail the same way for ever, and the thing to change is the request.
A rejected post also carries issues, one per problem, each naming the channel and the field. Fix them together and try once, rather than one at a time.
An issue marked "missing": true is about something not there yet (media, text, a title, a board) rather than something wrong. A draft (draft: true) is saved with those and is asked for them when it is published or approved; anything else refuses a draft too.
| Code | Meaning | What to do |
|---|---|---|
authentication_required | No credential, or one Mellow does not recognise. | Present the key or token. |
insufficient_scope | The credential lacks a permission this call needs. | The owner grants it when they create the key. |
channel_not_connected | That channel ID is not one of this owner's. | Call list_channels; IDs are stable but connections come and go. |
channel_out_of_scope | The credential does not cover every requested channel. | Use the channels it was given. A stored post spanning other channels needs a grant covering the whole post. |
caption_too_long | A channel's own perChannel caption exceeds its limit after fitting. Hub shortens an over-long caption on its own (note adapted_caption). | Give the channel a shorter caption with perChannel, or leave it to Hub. |
title_required | YouTube will not accept an upload without a title, and the caption has no line to take one from. | Set options.youtube.title. |
option_required | Something the network insists on is missing. | The message names it. |
media_kinds_mixed | Images and video in one post. | Split the post, or give the channel its own media. |
media_required | The network publishes nothing without media. | Add media, or drop that channel. |
branded_content_private | TikTok does not let a paid partnership be private. | Make it public, or drop discloseBrandedContent. |
trial_needs_reel | trialReelType is set on an Instagram post that is not one video posted as a reel — a story, a picture or a carousel. The trial would be dropped on the way and the post shown to the followers as an ordinary one. | Send one video with placement reels (or timeline), or drop trialReelType. |
schedule_in_past | scheduledAt has already passed. | Omit it to publish now. |
daily_limit_reached | This key already has its limit of posts going out on that UTC day. | Choose another day — for a post going out now, the next UTC day — or the owner raises the limit. |
idempotency_key_reused | That key already published something else. | Use a new key. This is a bug in the caller. |
validate_post and create_post return notes beside issues. A note stops nothing; it is what you tell the person, or act on, before the post goes.
| Code | Meaning | What to do |
|---|---|---|
channel_needs_reconnect | That account's sign-in has run out. The post is accepted, fails there, and is kept for three days: it goes out by itself once a person signs in again. | Tell the person now, or leave the channel out. |
channel_sign_in_ends | That account's sign-in still works and is dated to end within a week, before this post is due; until is the day. Whether it is renewed before then is not known. | Ask the person to sign in to it again before that day. If they do not, the post is kept for three days and goes out when they do. |
network_limit_waiting | One of that account's posts is waiting for the network's limit; until says when Hub sends it again. A post sent before then may be refused the same way, and Hub would send it again by itself. | Schedule the post after until if the hour matters, or say that it may go out later than asked. |
network_limit_recent | Some of that account's posts had to wait for the network's limit in the last seven days; the message gives how many and when last. Hub does not know the limit itself. | Tell the person the post may go out later than planned, by hours or by a day. |
media_outside_limit | A video's length, frame, weight or type, read from the file's header, is outside a limit that network's API publishes; the message gives both figures, the page and the day it was read. The post is taken all the same. | Give that channel a file that fits with perChannel, or leave the channel out; say so to the person if neither is yours to decide. |
media_limit_depends | The video is within what some accounts get on that network and over what every account gets (TikTok's ten minutes, X Premium). Hub cannot see which the account has. | Ask the person, or send it and read get_post. |
adapted_* | Hub fitted the post to a network: a caption shortened, a file left out. | Read what was changed; override with perChannel if it matters. adapted_caption carries measured and limit, counted the way that network counts: to say everything instead of losing the end, write the caption again within limit and send it as that channel's perChannel.caption. |
| Code | Meaning | What to do |
|---|---|---|
provider_error | The publishing provider refused or failed. | Read retryable. |
provider_result_failed | The network itself rejected this channel's post. | The channel's errorMessage carries what the network said. |
account_disconnected | The account had been disconnected before the post's time. | Tell the person to connect it again: Hub then sends the post by itself, within three days. whoami lists such posts ahead of time as queueWithoutAccount. |
result_never_confirmed | The network never reported an outcome. | Check the account directly before republishing — it may have gone out. |
already_published | Cancelling something already public. | Nothing here can unpublish it; delete it in the network. |
A partial post is not a failed post. status: "partial" means some channels published. Creating the post again duplicates those. For the channels whose target says failed, call retry_post: it sends the same post to them alone.
A channel that goes back to scheduled after sending is Hub sending it again. A network that was busy, could not process the file, or gave no reason is tried three more times within the hour; a network's limit is waited out. The target carries waiting (why, and until when). Do not send it yourself; wait for it to settle. A sign-in that ran out is different: the target reads failed with kept, and it goes out when a person signs in again within three days. retry_post cannot mend that one; say so to the person.
A timeout is not a refusal. If create_post times out, the post may exist. Retry with the same idempotency key — that is exactly what it is for — or call list_posts and look.
{
"caption": "Three minutes on why we rebuilt the editor.",
"media": ["https://cdn.example.com/editor.mp4"],
"channels": ["spc_ig", "spc_tiktok", "spc_youtube", "spc_threads"],
"options": {
"instagram": { "placement": "reels", "shareToFeed": true },
"youtube": { "title": "Why we rebuilt the editor", "privacyStatus": "public" },
"tiktok": { "privacyStatus": "public", "allowComment": true }
}
}
A vertical video under three minutes becomes a Short on YouTube by itself. There is no Shorts setting to send.
Bluesky allows 300 characters and X allows 280; LinkedIn allows 3000 and rewards using them. Write the long version once and override the short ones:
{
"caption": "The long version, written for LinkedIn…",
"channels": ["spc_li", "spc_bsky", "spc_x"],
"perChannel": {
"spc_bsky": { "caption": "The short version." },
"spc_x": { "caption": "The short version." }
}
}
Make one create_post per slot with scheduledAt, and give each a stable idempotency key — week-32-tue-morning rather than a random value — so re-running the plan does not double-post.
Under a review key, create_post prepares the post and stops. Tell the person it is waiting; they approve it in Mellow. whoami says which mode the key is in, so check before promising to publish.
get_post → status "partial"
→ targets[2].status "failed", errorMessage "…"
Mellow Hub has already sent it again by itself where that helps: a busy network, a file a network could not process and a network that gave no reason get three more tries within the hour; a network's limit (429) is waited out; a post whose account's sign-in ran out is kept for three days and goes out when the person signs in again. While that is happening the channel reads scheduled with waiting (why, and until when); a kept one reads failed with kept.
For a channel that still reads failed, call retry_post with the post's id: it sends the post again to the failed channels alone. Do not create a second post for it, and do not resend the channels that published. If the message names something in the post itself, the post is out where it went and cannot be changed there: tell the person what the network said.
retry_post without an id sends again everything that failed in the last seven days. It is refused for an account whose sign-in ran out or that is no longer connected: only a person mends those, so say so plainly.