Breaking changes will be marked when they occur; minor versions stay backward-compatible when possible.
October 2026 (Meta sign-ins that ended)2026-10-28
An Instagram, Facebook or Threads connection whose sign-in Meta ended reads reconnect_required, and posts to it are refused with 401
- *A connection whose sign-in Meta ended (Graph code 190 or 102, for example after a password change) kept status connected and health ready in GET /api/v2/accounts and status200_list_accounts while every post to it failed. When Meta refuses the sign-in on a post, a read or a renewal, we ask Meta once more with the same sign-in (a read of the account), and when it refuses again the connection reads status expired and health reconnect_required. When Meta renews a sign-in and then refuses both the new and the old one, the same. A rate limit, a temporary error, a refusal the second read does not repeat, or a refusal while our safety limits are reached leaves the connection as it is. An Instagram renewal Meta refuses for a reason that is not about the account's sign-in (for example code 100, about our app's access) no longer turns the connection expired: it stays connected, and a post that needs the renewal is 401 TOKEN_REFRESH_FAILED with "Instagram token refresh failed: ..." (it was 401 RECONNECT_REQUIRED "Instagram can no longer refresh this token (...). Please reconnect your Instagram account.", and the connection turned expired); status200_publish_post and status200_retry_post answer it temporarily_unavailable, naming Instagram (they answered reconnect_required)
- ~GET /api/v2/accounts/{profile_id}/options and status200_get_posting_options answer such an Instagram or Facebook connection reconnect_required, as before, with the note "<network> is connected to this profile, but the saved sign-in is no longer usable, so its options could not be read. ..." instead of "<network> is no longer accepting the saved sign-in for this account, so its options could not be read."
- ~POST /api/v2/posts and the older URL refuse a post to an Instagram, Facebook or Threads connection with status expired before anything is sent, and a dry run reports the same: 401 RECONNECT_REQUIRED (Instagram) or reconnect_required (Facebook, Threads), with error.platform and a message that says to reconnect on the Connections page: why, for a connection Meta signed out, and otherwise "This Instagram connection has expired. Nothing was posted. Reconnect Instagram on the Connections page, then send the post again." It was 400 api_error "<network> is not connected for this profile. Go to Connections and connect <network> first."; a network that is not connected at all keeps that answer. Nothing is counted toward the allowance. Before refusing a connection Meta signed out, a publish asks Meta once more (at most every 10 minutes per connection) and publishes when Meta accepts the sign-in again; a dry run asks the same read-only question when a publish would, writes nothing, and reports the connection usable when Meta accepts
- ~Of the posts refused this way, the first one after Meta ended a sign-in is listed by GET /api/v2/posts as a failed post with that message, unless another post already says why: one per sign-in Meta ended (when that row cannot be written, the next refused post writes it). It keeps no request, so retry-post answers it 409 no_request (409 retry_not_available for a Threads post), and status200_retry_post answers the same code with retry "never"; both leave it as it is
- ~The post on which Meta's refusal was confirmed fails with the same code and message instead of Meta's own error (on Instagram it was 400 with Instagram's own error, such as CONTAINER_ERROR; on Facebook 401 reconnect_required with other words; on Threads a 500), and GET /api/v2/posts shows that message in error_message. A Facebook refusal worded like a dead sign-in is 401 reconnect_required only once the connection is marked this way; otherwise it is 500 FUNCTION_ERROR with Facebook's own words. It used to be 401 reconnect_required "Facebook did not accept the saved sign-in. Reconnect Facebook on the Connections page and try again." status200_publish_post answers that 500 with code FUNCTION_ERROR and "Try again in a minute. If it keeps failing, contact support ...", and status200_retry_post with invalid_request ("Fix the request and send it again."); both used to answer reconnect_required
- ~A Threads post whose sign-in could not be renewed just then (Meta answered the renewal, but it could not be finished or confirmed) is 401 TOKEN_REFRESH_FAILED with error.platform threads and "Threads could not renew the sign-in just now, so nothing was posted. Try again in a few minutes.", or "Threads refused the sign-in (...), so nothing was posted. If it keeps failing, reconnect Threads on the Connections page." when Meta refused it but the connection could not be marked just then; the connection is left as it is. It was a 500 without a code (platform_error on /api/v2/posts), and the connection was marked expired. status200_publish_post answers it temporarily_unavailable, naming Threads ("Try again in a few minutes. If it keeps failing, ask the person to reconnect Threads on the Connections page ..."). A renewal that Meta does not answer at all is still a 500 without a code
- ~An Instagram post whose renewal Meta refused with code 190 or 102, when our check could not tell or the connection could not be marked just then, is 401 TOKEN_REFRESH_FAILED with "Instagram could not renew the sign-in just now, so nothing was posted. Try again in a few minutes." or "Instagram refused the sign-in (...), so nothing was posted. If it keeps failing, reconnect Instagram on the Connections page."; the connection is left as it is, and status200_publish_post and status200_retry_post answer it temporarily_unavailable, naming Instagram. It was 401 RECONNECT_REQUIRED "Instagram can no longer refresh this token (...). Please reconnect your Instagram account." (reconnect_required in both tools), and the connection turned expired
October 2026 (n8n node on n8n Cloud)2026-10-26
The n8n node can be added on n8n Cloud
- +n8n verified the n8n node @status200uploads/n8n-nodes-status200uploads (version 0.1.3) on 26 October 2026, so it is in the nodes panel of n8n Cloud: an owner or admin searches for Status 200 Uploads and clicks Install (if it is not listed, the owner turns on Verified community nodes under Instance settings in the n8n Cloud console). On self-hosted n8n it installs as before, under Settings, Community Nodes. Our own live test of the node ran on self-hosted n8n (29 September 2026); we have not run it on n8n Cloud ourselves yet. The HTTP Request node still does the same on any n8n, as the n8n guide describes
October 2026 (connector reconnect answers)2026-10-26
The AI connector answers a network's refusal of the saved sign-in as reconnect_required, naming the network
- ~When a network refuses the saved sign-in of a connection (RECONNECT_REQUIRED of Instagram; reconnect_required of Facebook, LinkedIn, Skool and Threads; NO_TOKEN; REFRESH_TOKEN_EXPIRED; pinterest_auth_failed; also inside the 400 of status200_retry_post), status200_publish_post and status200_retry_post answer code reconnect_required with a next_step that names the network (the one in the refusal, else the one the post was for) and the Connections page (and, when the network wants a security check or a Page role first, says that first). status200_publish_post used to answer it as the app's own sign-in to Status 200 Uploads ("Connect the app to Status 200 Uploads again, then try once more."), and status200_retry_post, which gets it inside retry-post's 400, as invalid_request ("Fix the request and send it again."). These answers keep no retry rule, as before, except one: the refusal that names its network in error.platform (Instagram's, Facebook's or Threads' refusal of a connection that needs reconnecting, which every post meets until the person reconnects) gets retry "never", and its next_step says that every post to that network is refused until then. X's x_rejected keeps the answer it had
- ~TOKEN_REFRESH_FAILED (Instagram, TikTok: a renewal of the sign-in that did not work) is answered as temporarily_unavailable, "Try again in a few minutes. If it keeps failing, ask the person to reconnect <network> on the Connections page ...". When TikTok's own words in it say the sign-in can no longer be renewed (for example invalid_grant, or a refresh token that is invalid, expired or revoked: the words for which our renewals mark the connection expired), it is reconnect_required with the next_step to reconnect TikTok, without a retry rule. status200_publish_post used to answer every TOKEN_REFRESH_FAILED as reconnect_required ("Connect the app to Status 200 Uploads again, then try once more."), and status200_retry_post as invalid_request ("Fix the request and send it again.")
- ~status200_validate_post is marked open-world (openWorldHint true), and its description says what a check does for an Instagram, Facebook or Threads connection that needs reconnecting: it may ask the network once, read-only, whether it accepts the saved sign-in again, exactly when publishing would ask it, and writes nothing
- ~status200_schedule_post's refusal of a connection that is not ready (health not ready in status200_list_accounts) carries retry "never" too
- *status200_retry_post of a post whose original request was not stored (History offers no Retry for it either) answers code no_request with retry "never" ("The original request was not stored for this post, so it cannot be replayed.") and leaves the post exactly as it is. It used to try, then mark the post failed again with words such as "Cannot retry: missing profile information from original post", which replaced the post's own error
- *status200_retry_post of a Threads or Pinterest post, or of an X or LinkedIn post that is not a large video sent in the background (History offers no Retry for them either), answers code retry_not_available with retry "never" ("Retry is not available for this platform yet. Create the post again from the Schedule page.") and leaves the post exactly as it is. It used to mark the post failed again with "Unsupported platform: threads" (or pinterest, x, linkedin), which replaced the post's own error, and to answer invalid_request ("Fix the request and send it again.")
October 2026 (Instagram posts and the allowance)2026-10-19
An Instagram post that went out keeps counting toward the allowance
- *An Instagram post that was published counts toward the plan's post allowance from then on, whatever a later answer about the same post says. Sending Instagram's publish step again for a post that is already live (Instagram answers that with an error), or a later status check that reads an error for it, used to give its place in the allowance back, so the allowance counted one post fewer. The same holds when the post was published through another profile connected to the same Instagram account, and when Instagram's status check finds a post published after its publish step answered with an error. A post that failed still gives its place back, and a post that failed and then went out on a second try still counts once
October 2026 (scheduled posts that were not sent)2026-10-19
A network of a scheduled post that was never sent reads as failed, with words that say so
- *A network of a scheduled post that our scheduler stopped before sending used to read as status timeout (outcome unknown: do not send it again) with "No answer came back from <network> after this post was sent. ...". It now reads as failed with "This post was not published on <network>: our scheduler stopped before publishing it, so nothing went out. You can retry it." (on X, LinkedIn, Pinterest and Threads: "Create the post again from the Schedule page to send it."). Nothing of it was published, so sending it again is safe, and status200_retry_post accepts it where retry exists
- *A retry of a network of a scheduled Facebook post (History's Retry, status200_retry_post) failed with "photo_url is required" whatever had gone wrong. It now sends the post again as it was scheduled, with the same type, files and caption
- *A scheduled post is no longer stopped about three minutes after it started to go out: on 14 October that stopped a scheduled Instagram Reel before it was published
- ~publish_id of a scheduled Instagram post (GET /api/v2/posts, GET /api/v2/posts/{id} and its results, status200_get_post) now carries Instagram's container id while the post is processing or timeout, from the moment the container exists, as a post sent at once always did (until now a scheduled one had it only when the answer to its publishing was lost); at success it is the media id. So a scheduled Instagram post cut off while it was being published is settled by that container: success with its link when Instagram published it, or failed, not published, with retry allowed, once Instagram reports the container expired (after about a day)
October 2026 (scheduled posts and the daily allowance)2026-10-13
A network of a scheduled post that did not fit the day moves to the next day instead of failing
- *When the daily allowance filled up while a scheduled post was going out (another post sent at that moment), the networks that did not fit were failed. They now move to the same time on the next UTC day as a scheduled post of their own, which GET /api/v2/posts lists as waiting, with its note. They leave the post that went out: its platforms and results hold only the networks that went out, so GET /api/v2/posts/{id} reads it as success when they did (not partly_failed), and each of those networks carries a notice moved_to_next_day with the scheduled_post_id of the post the others moved to and their platforms. Do not send the moved networks again: that post sends them. When nothing of the post had gone out yet, the post itself moves, as a post over the allowance always did
- *Two scheduled posts of one account due at the same time that would go over the allowance together are decided one after another: the one that does not fit moves whole to the next day (a daily allowance) or is not sent (the Free month), instead of both going out side by side and a network of the second being refused
- +notices (GET /api/v2/posts, GET /api/v2/posts/{id} and each result of a scheduled post) can hold a new code on any network, moved_to_next_day, with two new fields, scheduled_post_id and platforms; until now they held only what we changed to get a TikTok photo post out. The AI connector's status200_get_post and status200_list_posts carry it as a warning with the same fields, and status200_retry_post refuses a post that moved (queued_for_next_day, retry not_a_failure)
October 2026 (share links on every paid plan)2026-10-12
Share links in POST /api/v2/media are on for every paid plan
- ~Share links in POST /api/v2/media (and the older api-media-upload) have been on for every account since 9 October 2026. On the paid plans, from Beginner, a Google Drive link (tested on 9 October 2026) of a file shared with "Anyone with the link" is turned into the address of the file itself and imported. Dropbox, OneDrive and SharePoint links are accepted but not tested yet. With a Free key, a link that already downloads the file (such as a drive.usercontent.google.com one) is imported as before, and a link that needs converting is 403 plan_limit_reached
- *Nothing changes for a request today: share links were switched on for every account on 9 October 2026, and until now the docs, llms.txt and the OpenAPI file said they were rolling out, switched on account by account (as the entry of 9 October below does)
October 2026 (media addresses)2026-10-12
A media address that is not a web address is refused at once with 400, instead of being sent to the network
- ~POST /api/v2/posts (and the older api-posts) checks the media addresses of a post before anything is sent: every item of post.content.mediaUrls is checked (when the post has no mediaID or mediaIds), even one the network would not use, and so is a Reel's post.instagram.coverUrl. One that is not a full web address starting with https:// or http:// (a file name joined in front of the address, a file path, an empty value, a value that is not text) is refused with 400 bad_request, error.field naming it (for example post.content.mediaUrls[0]), and a message that says what is wrong, for example: "post.content.mediaUrls[0] is not a web address, so nothing was sent. Send the full address of the file, starting with https://. Here an address starts later in the text ("photo-01https://..."): something may have been joined in front of it." Before, such a post was sent to the network, which refused it, and it was recorded in History as a failed post
- ~Nothing is sent, scheduled, queued or recorded for such a request, a post with post.scheduledFor included, and a dry run answers outcome refuse with the same reason. An address with spaces or other unusual characters that a URL parser reads is sent exactly as before
- ~A Reel's post.instagram.coverUrl sent now is read as a scheduled Reel's always was: the spaces around it are removed before it is checked and sent, and a coverUrl that is blank (only spaces) means no cover. Before, a Reel sent now gave Instagram the cover exactly as it came, spaces included
October 2026 (media library and share links)2026-10-09
GET /api/v2/media/files lists your media library; share links in POST /api/v2/media are rolling out
- +GET https://status200uploads.com/api/v2/media/files lists the files of your media library, newest first, on every plan: what you uploaded in the dashboard, imported from a URL or sent through an upload link. Parameters: name_contains (every word in the name, 1 to 120 characters), type (image or video), since (a date and time with a time zone, read 2 minutes earlier to allow for clocks), limit (1 to 100, default 20), cursor and include_unconfirmed. Each file has file_id, file_name, type, kind, size, status, usable, source, uploaded_at, expires_at, confirm_before_posting and error, never its address. A read like the others: 60 a minute per account, not counted in the key's request count, Cache-Control: private, no-store. One request reads at most 500 files: follow next_url until it is null
- +Share links in POST /api/v2/media (and the older api-media-upload) are rolling out, switched on account by account, for some accounts first; until they are on for an account, every link is imported exactly as before. Where they are on, a Google Drive link (tested on 9 October 2026) of a file shared with "Anyone with the link" is imported on the paid plans, under the name the provider gives the file. Dropbox, OneDrive and SharePoint links are accepted but not tested yet. A link that cannot give one file is 400 with code link_not_public, link_is_folder, link_not_found, link_temporarily_blocked, link_not_a_file, link_not_supported or share_links_paused, plus next_step and provider. A Free key's link that needs converting is 403 plan_limit_reached (a link that already downloads the file, such as a drive.usercontent.google.com one, is imported as before), and a plan that cannot be read is 503 uploads_busy with Retry-After 60
- +The AI connector has a 17th tool for signed-in apps, status200_list_media: the same list for an AI app, 10 files a page (at most 50), so a file uploaded in the dashboard is posted by its file_id
- ~The JSON 404 of a path that is no endpoint under /api/v2 lists GET /api/v2/media/files too
October 2026 (notices when a post is read)2026-10-09
GET /api/v2/posts and GET /api/v2/posts/{id} say what we changed to get each TikTok photo post out
- +Every post in GET /api/v2/posts and GET /api/v2/posts/{id}, and every network's entry in a scheduled post's results, has notices: what we changed to get a TikTok photo post out (a photo sent as a smaller or JPEG copy, a title or description shortened), as it was said when TikTok took the post: code, message and, for a photo, photo (for a smaller copy also photos, size and copy_size). [] when there is none and on the other networks, where what we changed (a YouTube title or description we shortened, for example) is still said only in the warnings of the answer that sent or scheduled the post. A TikTok photo sent as a smaller copy (resized_for_tiktok) by a scheduled post, or by a post answered 202 still_publishing, used to be told only in History. Details: https://status200uploads.com/docs/api#tiktok-photos
- +The AI connector's status200_get_post and status200_list_posts carry them as warnings (code and message) on each post and each result, with tell_the_person
- ~A notices field at the top of a POST /api/v2/posts body is not one the API reads (the answer says so: unknown_field), and it is no longer kept with the post either, so a post's notices are only ever what we changed
- ~The copy we store for TikTok in your media library is named after the original file ("IMG_0042 (smaller copy for TikTok).jpg"), no longer after its file id; GET /api/v2/media/files still leaves these copies out
- ~A TikTok post refused with picture_size_check_failed: its error_message no longer says the photo may be too small, and says to save the photo as a JPEG of 1080 × 1350 or 1080 × 1920 pixels and post it again (the code stays in brackets)
October 2026 (AI connector on paid plans)2026-10-08Breaking
The MCP server refuses the API key of a Free account; the REST API is unchanged
- ~The AI connector (the MCP server, https://mcp.status200uploads.com/mcp) is included in every paid plan, from Beginner, whether an app signs in or sends an rl_ API key (Authorization: Bearer or X-API-Key). For the key of a Free account the session still opens and lists its 5 tools, and every tool call answers plan_limit_reached with retry "never" and upgrade_url. The REST API (/api/v2/* and the older api-posts) and its keys are unchanged on every plan
- ~POST /api/v2/media/uploads and POST /api/v2/media/uploads/{file_id}/token can answer 503 upload_links_paused for one account only: uploading from a computer is switched off for that account. The message then says "switched off for this account", retry is "never", there is no Retry-After and asking again does not help: upload the file in the dashboard (Media), or write to info@status200uploads.com. Finishing (/complete) and cancelling an upload are not affected, and neither is posting
Migration Guide
On Free, call the REST API with your API key (https://status200uploads.com/docs/api). To keep using the MCP server, choose a paid plan, from Beginner.
October 2026 (TikTok photo sizes)2026-10-08
TikTok photos larger than 1080 × 1920 are sent as a smaller copy, or refused before anything is sent
- ~TikTok photo posts: a JPEG larger than TikTok's size (1080 × 1920 pixels, 1920 × 1080 when wide) is sent to TikTok as a smaller JPEG copy inside that size (at least 90% of it), turned the way the photo is shown. TikTok used to accept such a post and fail it a few seconds later with picture_size_check_failed. The warnings in the answer say so (code resized_for_tiktok, with photo, photos, size and copy_size, and the message "Photo too large for TikTok: it is 2160 × 2700 pixels and TikTok takes up to 1080 × 1920, so we sent a smaller copy (1080 × 1350). Your original file is unchanged."), History shows it on the post, and your original file is not changed
- +422 photo_too_large_to_resize, with error.photo: a TikTok photo larger than that size that we cannot make smaller (a WebP; a JPEG over 5 MiB or about 13 MP; a progressive JPEG over 2 MiB or about 12 MP; fewer megapixels with more colour detail or under about 1.8 times the size of its copy; or a JPEG we cannot read: CMYK, 12-bit, arithmetic-coded, lossless, hierarchical or with unusual colour components). Nothing is sent and no post is recorded: send a JPEG of at most 1080 × 1920 pixels
- ~A TikTok post that TikTok refused with picture_size_check_failed has an error_message in plain English that says what to do next, with the code kept in brackets
- +The OpenAPI file describes the warning's photo, photos, from, size and copy_size, and error.photo. Every limit, every message and what to do: https://status200uploads.com/docs/api#tiktok-photos
October 2026 (upload links)2026-10-06
Upload a file from a computer through a one-time upload link
- +POST https://status200uploads.com/api/v2/media/uploads makes a one-time upload link for a file on a computer: send file_name, size_bytes and sha256 (and shell, powershell or sh, for a ready-made command that runs our uploader). The answer (201) has the file_id, a TUS 1.0.0 address on storage's own host with its signed token (about 2 hours, this file only) and resume_before. Send the file with the command or any TUS client, then POST /api/v2/media/uploads/{file_id}/complete: the file is checked (exact size, type, first bytes, SHA-256) and answered 200 ready (it is in the media library: post it with its file_id in content.mediaID) or 202 verifying (poll GET /api/v2/media?file_id=)
- +POST /api/v2/media/uploads/{file_id}/token gives an unfinished upload a fresh token (only the API key that made the link, at most 12 times, within 24 hours), and DELETE /api/v2/media/uploads/{file_id} cancels it. For an upload, GET /api/v2/media?file_id= answers uploading, verifying, ready or failed, without public_url until it is ready
- +The uploader (Windows PowerShell, sh and Node.js) is published at https://status200uploads.com/uploader/v1/ and a published version never changes. The command checks its SHA-256 before running it, and the API docs list the hashes of every version
- +Limits: videos (MP4, M4V, MOV, WebM) up to 5 GB, images (JPEG, PNG, WebP) up to 20 MB; per account 10 uploads open at once, 20 new links in 10 minutes and 100 a day, and 60 upload-link calls a minute. One daily budget per account and UTC day counts every upload link and the URL imports of connected AI apps: Beginner 2 GB, Apprentice 10 GB, Skilled 25 GB, Expert and Agency 100 GB
- +Paid plans only: Free is answered 403 plan_limit_reached before anything is reserved (upload the file in the dashboard, Media, which every plan can use)
- +New codes: invalid_request, unsupported_media_type, media_too_large, too_many_open_uploads, upload_already_received, upload_closed, renewals_exhausted, account_being_deleted, upload_links_paused, uploads_busy, upload_incomplete, upload_rejected, upload_failed, upload_expired and upload_being_checked, next to plan_limit_reached, import_budget_exhausted, rate_limited, media_not_found and server_error. These answers also carry next_step and, for most refusals, retry ("never" or "after_reset"); the OpenAPI file describes them, and its x-status200-retry table says which may be sent again
- +The x-status200-retry table has a by_operation list, read before by_code for that operation: an answer whose rule is not its code's. Its one entry: POST /api/v2/media/uploads/{file_id}/complete answering 503 upload_links_paused (checking files is paused, and the file that arrived is kept) is wait_and_resend, after Retry-After. A client that reads only by_code gives up there instead; nothing is sent twice either way
- +A budget refusal (429 import_budget_exhausted) carries held_bytes and held_until when unfinished upload links of the account hold part of the day's budget: how much they hold, and when it is free again if nobody continues them
- ~POST /api/v2/posts answers a mediaID that is an unfinished upload with 404 media_not_found and the request that finishes it (POST /api/v2/media/uploads/{file_id}/complete)
October 2026 (media types)2026-10-06Breaking
URL imports take the six media types the dashboard takes
- ~POST /api/v2/media (and the older api-media-upload) refuses with 415 a URL whose file is not JPEG, PNG, WebP, MP4, MOV, M4V (stored as MP4) or WebM. GIF, HEIC, SVG and other formats were stored before, and a post that used one could then fail
- ~A source that sends no type, or a generic one such as application/octet-stream, is judged by its first bytes: a JPEG, PNG, WebP, MP4, MOV or WebM file is imported as that type, anything else (a web page, for example) is refused with 415
Migration Guide
Convert GIF, HEIC, SVG and other formats to JPEG, PNG, WebP or MP4 before importing them.
September 2026 (Free plan)
Free: 30 posts a month from 18 October
- ~From 18 October 2026 00:00 UTC a Free account gets 429 monthly_limit_reached after 30 successful posts per calendar month (announced before as 60). The codes and fields do not change: error.limit is 30 and error.resets_at is the 1st of the next month
- ~Posts published from 1 October 2026 count toward October's 30, so from 18 October an account with 30 or more used gets monthly_limit_reached until 2026-11-01T00:00:00Z, with error.used above error.limit
- ~Until 18 October, error.limit is 60 for Free accounts created since 18 September 2026, and error.resets_at is the 1st of the next month
- ~On 17 October 2026 a request over the day's 5 posts of an older Free account (5 per profile per day) is answered 429 monthly_limit_reached, with error.resets_at 2026-11-01T00:00:00Z, instead of 202 queued_for_next_day when October's 30 are already used: the queued post would go out on the 18th and be refused
September 2026 (Python package and n8n node)
A package for Python and a community node for n8n
- +The Python package status200uploads is on PyPI: pip install status200uploads (Python 3.11 or newer). Its Status200 client publishes, checks, schedules and cancels posts, imports media, reads your profiles, posting options and posts, and can wait until a post is done. By default it sends an Idempotency-Key with every post and media import, and it sends a request again only when the x-status200-retry table of the OpenAPI file allows it. Source: https://github.com/iBoyDroid/status-200-uploads/tree/main/python
- +The n8n community node @status200uploads/n8n-nodes-status200uploads is on npm. On self-hosted n8n: Settings, Community Nodes, Install, then enter @status200uploads/n8n-nodes-status200uploads. It publishes, checks, schedules, reads and cancels posts, lists your profiles and their posting options, and imports media, with an automatic Idempotency-Key. n8n Cloud installs only community nodes that n8n has verified, and this one is not verified yet: on n8n Cloud, use the HTTP Request node as the n8n guide describes
- ~The "Using Python" and n8n guides show the package and the node. The requests example and the HTTP Request node steps stay, for use without them
September 2026 (OpenAPI description)
The whole API as an OpenAPI 3.1 file
- +https://status200uploads.com/openapi.yaml describes every endpoint of both URLs in OpenAPI 3.1: the requests, every answer with its fields, the error codes of each status, the Idempotency-Key and the x-status200-retry table of which answers may be sent again. Import it into Postman or Insomnia, or generate a client from it. It is written from the code and checked against the live answers of both URLs
- *A method /api/v2/posts does not answer (for example PUT) is still 405 method_not_allowed, and now carries a message too: every error of /api/v2/posts and of the reads has error.code and error.message (the media endpoint keeps its {"error": "message"} shape)
- */api/v2/posts reads the word Bearer in any capital letters ("Authorization: bearer rl_..."), as the older URL, /api/v2/media and the reads always did. It answered 401 before
- *The docs name every code the API answers with, among them pinterest_board_required, media_wrong_for_post_type, options_outside_post, no_container, the networks' own refusals (pinterest_rejected and x_rejected with the network's own status), the 401s of Instagram and TikTok that ask for a reconnect (RECONNECT_REQUIRED, REFRESH_TOKEN_EXPIRED, NO_TOKEN, and TOKEN_REFRESH_FAILED when a sign-in could not be renewed just now) and the media endpoint's 405 and import_budget_exhausted. They said queue_failed for a post that could not be queued for the next day: that answer has always been 500 api_error. The queued_for_next_day example shows its upgrade_url and status200, and monthly_limit_reached lists all its fields
- ~The differences of the older URL are listed in full (its api_error refusals of the request, the order of its checks, the answers only /api/v2 gives), and a media source is checked with two requests of 8 seconds each, so up to about 16 seconds
- +A "Using Python" guide. A Python package and an n8n node are coming soon; until then any HTTP library and n8n's HTTP Request node do the same
September 2026 (safe retries)
Send a request again safely with an Idempotency-Key
- +POST /api/v2/posts, POST /api/v2/media and the older api-posts and api-media-upload URLs take an optional Idempotency-Key header: 1 to 255 printable ASCII characters naming this one request. The same key with the same JSON body within 24 hours of the first request gets the first answer back, status and body byte for byte, with Idempotent-Replayed: true, and nothing is posted or imported a second time. A request without the header works exactly as before
- +Remembered: every 2xx (published, processing, still_publishing, scheduled, queued; for media a 200 or 202 with its file_id) and an answer whose outcome could not be confirmed, such as a 5xx platform_error after the post was handed to the network. Not remembered: refusals and failures the network reported with their own code, so a fixed request can be sent again with the same key. A key belongs to the API key that sent it; posts and media are kept apart; the two posts URLs share keys, and so do the two media URLs
- +New answers: 400 idempotency_key_invalid (empty, over 255 characters or not printable ASCII), 409 idempotency_in_progress (the first request with the key is still working; Retry-After 5 and retry_after_seconds), 409 idempotency_outcome_unknown (the first request never finished: check GET /api/v2/posts, then use a new key), 422 idempotency_key_reused (the key was used for a different body; first_used_at) and 503 idempotency_unavailable (the key could not be checked; nothing was sent; Retry-After 5). Nothing is sent with any of them
- +An answer sent again takes no 20-second wait, is logged and counted as a request, and never uses the post allowance. GET, DELETE and dry runs ignore the header. CORS allows the header and exposes Idempotent-Replayed and Retry-After
- ~The n8n guide: with the header, Retry On Fail (Max Tries 5, Wait Between Tries 5000 ms) never posts twice a post whose answer was lost, with a key built from the item and the network such as {{ $json.id }}-tiktok (an id that is never empty), never $now or a random value, and the same body on every try
September 2026 (reading through the API)
Read your profiles, posting options and posts, and follow a post with the id every answer now names
- +GET https://status200uploads.com/api/v2/accounts lists your profiles (profile_id, profile_name, handle) and the networks connected to each, with health (ready, reconnect_required or unknown), connected_at and updated_at
- +GET /api/v2/accounts/{profile_id}/options answers what the profile may do on each network, asked of the networks themselves: the TikTok privacy levels post.tiktok.privacyLevel accepts, Pinterest boards for post.pinterest.boardId, Skool groups (and one group's labels, ?skool_group_slug=), the Facebook Page, the Instagram publishing limit and YouTube's choices. One row per network with status ok, not_connected, reconnect_required, unavailable or no_options; always 200 (?platforms= to ask only some)
- +GET /api/v2/posts lists your posts and your scheduled posts that have not produced a post yet (waiting, cancelled, or failed before anything was sent), newest first by at (when a post was sent, when a scheduled post is due). Once a scheduled post has gone out, each network's post is listed instead, with its scheduled_post_id, so nothing is listed twice. limit (1-100, default 20), cursor, status, platform, kind and profile_id filter it; next_cursor and next_url give the next page, and a cursor that is not ours is refused with 400
- +GET /api/v2/posts/{id} reads one post (status, done, link, error, and figures for a successful post: null never means zero; done is true once it will not change by itself, a timeout included once nothing is checking it any more, so a polling loop always ends) or one scheduled post, before and after it goes out (outcome and each network's results)
- +Every POST answer that made a post or a scheduled post, at both URLs and whatever its status, has a new top-level field status200: {post_id, scheduled_post_id, status_url}. status_url is GET /api/v2/posts/{id}. data.post_id and the top-level post_id / scheduled_post_id are unchanged. It is not on a dry run or on a refusal answered before any post was recorded; any answer that left a post in History has it, a failed one included
- +Reads are limited to 60 a minute per account (all its API keys together), and posting options to 10 a minute per account, because each asks the networks themselves: 429 rate_limited with Retry-After, error.retry_after_seconds and error.limit. Reads are not counted in usage_count. Every read answers with Cache-Control: private, no-store
- ~The reads are on status200uploads.com/api/v2 only: GET on the older URL is still 405. CORS on /api/v2/posts now allows GET
- +The AI connector's status200_list_posts also lists posts waiting to go out, cancelled ones and ones that failed before anything was sent, and status200_get_post of a scheduled post shows each network's result once it has gone out
- *The note on a post with no figures in status200_get_post_performance says what is true: figures are collected every 6 hours during the first 7 days after publishing, on the networks that report them. Before, it said an hourly sweep collected them within a few hours
September 2026 (scheduling through the API)Breaking
Schedule a post with post.scheduledFor, and cancel it with DELETE
- ~A post.scheduledFor more than 60 seconds ahead now schedules the post: the answer is 202 with "code": "scheduled", scheduled_post_id and scheduled_at (data.status is "scheduled", and there is no "queued" field), and the post is published at that time, usually within a few minutes of it. Before, it was refused with 400 scheduling_not_available_yet. A past time, "now" or a time within the next 60 seconds still publishes at once
- ~A time must say its time zone: ISO 8601 ending in Z or an offset such as +02:00, a Unix time in seconds or milliseconds, or a date with the month as a word as e-mail and HTTP write it ("Wed, 30 Sep 2026 10:00:00 GMT", "... +0200", "... EDT"). A time without a zone ("2026-09-30T10:00:00", or a date alone) is refused with 400 scheduled_for_invalid and error.reason no_time_zone, also when it is in the past (before, a past one published at once). error.reason is unreadable for a value that is not a date and time (a date written with numbers only, such as 01/10/2026, included: it is January in one country and October in another; before, a past one published at once), and too_far_ahead for a time more than 365 days ahead
- +At most 500 posts can wait per account: the next is refused with 409 scheduled_queue_full. When the waiting posts cannot be counted, the answer is 503 schedule_check_unavailable with Retry-After 5, and nothing was scheduled
- +Scheduling works on every plan, Free included, and a scheduled post takes no 20-second wait. The plan gate is checked at once (Skool needs Beginner or higher, X the X add-on: 403 plan_required). The allowance and the X add-on's meter are checked when the post goes out: over a daily allowance it moves to the same time on the next day; on Free, a post over the month's 60 fails and shows on the Scheduled page and in the failure email
- +mediaUrls of a scheduled post, and a Reel's instagram.coverUrl, are fetched when it goes out, so they must still work then: the answer warns with media_url_not_kept, and an address that already answers "not found" is refused with 400 media_not_available (a cover that is gone by the time the Reel goes out leaves the Reel without its cover). An imported mediaID is kept until the post goes out, however far ahead. Skool's group and title are checked at once for a scheduled post, and skool_one_post_per_hour warns when two scheduled Skool posts of your account are less than an hour apart
- +posts_close_together warns when another post of your account on the same network is scheduled within 20 seconds: posts due together go out one after another with no gap, and a network can refuse posts that arrive that close together. Leave at least a minute between them
- +DELETE https://status200uploads.com/api/v2/posts/{id} (and DELETE https://app.status200uploads.com/functions/v1/api-posts/{id}) cancels a post that has not gone out, whoever scheduled it, with the scheduled_post_id of the 202: 200 with data.status "cancelled"; sent again, 200 with already_cancelled: true; 404 post_not_found; 400 bad_request for an id that is not a UUID; 409 not_cancellable once it is being published, published or failed (error.status says which); on /api/v2, 504 cancel_unconfirmed when the answer did not arrive in time (send it again). Each DELETE is logged and counted once in usage_count
- +A dry run with a time answers the outcome "schedule" (reason code scheduled, status 202) and schedules nothing
- +On /api/v2/posts a request with a time whose answer did not arrive in time is answered 202 schedule_unconfirmed: it may have been scheduled, so check the Scheduled page before sending it again
- ~The AI connector reads a time the same way: status200_schedule_post and status200_update_scheduled_post refuse a scheduled_at without a time zone (invalid_request, and the next step asks for the zone) instead of reading it in the server's own time zone, and a date written with numbers only (01/10/2026) as not a date
Migration Guide
Branch on code: "scheduled" means the post was scheduled for your time, "queued_for_next_day" (with "queued": true) that the daily allowance moved it. Never send a request again after a 202 scheduled: it would schedule the post a second time (a DELETE can always be sent again). Send times with a zone (Z or +hh:mm). For a post more than a few hours ahead, import the file (POST /api/v2/media) and send its mediaID rather than mediaUrls.
September 2026 (options of queued posts)
A post queued for the next day keeps its platform options
- *A pin queued for the next day keeps pinterest.altText and pinterest.dominantColor, as a pin published at once. Before, they were dropped
- ~A pin queued for the next day gets a description only from pinterest.description, as a pin published at once: content.text is its title. Before, content.text was also its description
- *A stored X post keeps x.whoCanReply and x.community (an X post is never queued for the next day: the X add-on has its own allowance, so this matters for scheduled posts)
- *A post queued for the next day keeps instagram.coverUrl, thumbOffset and collaborators (Reels) and locationId (feed images), and tiktok.isAiGenerated on a video, as a post published at once. Before, they were dropped when it went out
September 2026 (checking posts with no answer)
Posts we heard nothing back about are checked with the network
- +When a post was sent but no answer came back (the connection broke, or the network was slower than we can wait), we now ask the network ourselves whether the post exists. Facebook: if we find it on the Page, History shows success with its link; if it is not on the Page after a fair wait, History shows it failed and Retry is safe. Instagram: a post we find shows success. The check runs every 10 minutes and gives its answer within about an hour
- ~A Facebook or TikTok photo post sent through the API whose answer was lost is answered 202 still_publishing with its post_id instead of an error, and History shows "Not confirmed" while it is checked (this replaces "timeout, check before retrying")
- ~A post that may already be live and that the network gives us no way to check (X, LinkedIn, Skool, a TikTok post without a TikTok post number, an Instagram post not found yet) cannot be retried: Retry answers 409 outcome_unknown and History says to check the account first, so the same post is never published twice. If it is not there, publish it again as a new post
September 2026 (one engine)Breaking
One engine behind both API URLs
- ~A Facebook post with no media field is a text post on the older URL too: facebook.postType can be left out. On the older URL a media field sent empty ([] or null) without facebook.postType "text" is still refused with 400, so a failed media step never publishes the text alone
- *A Facebook text post without content.text is refused with 400 bad_request "A Facebook text post needs content.text" before anything is sent (the older URL answered 500 and showed a failed post)
- *On the older URL, a profile UUID with spaces around it is found (was 404), a media field sent as text where a list belongs (for example mediaUrls: "https://…") is answered 400 "post.content.<field> must be a list" (was 404 or 500), and an accountId that is not text, or is blank, is answered 400 "post.accountId is required" (was 500, and 404 for a blank one)
- ~TikTok and YouTube connections marked expired are tried and refreshed on the older URL, as /api/v2 already did. When the network no longer accepts the sign-in, the answer is the network's reconnect error (TikTok 401 REFRESH_TOKEN_EXPIRED or TOKEN_REFRESH_FAILED; YouTube "YouTube token expired. Please reconnect your account.") and History shows a failed post; before, the older URL answered 400 "not connected" without trying
- ~Every Facebook and TikTok post appears in History as processing as soon as it is sent, on both URLs. A post whose connection broke off mid-send shows "timeout, check before retrying" instead of not appearing, and a post our gateway lost the answer for (a 504, not a refusal from Facebook) stays processing until the outcome from Facebook is recorded, instead of showing failed
- ~On /api/v2/posts a network slower than the request can wait is answered 202 still_publishing a little earlier. The answer includes post_id whenever the post is already in History, and the request is counted once in usage_count
- ~A connection that breaks after the request was sent is answered 202 still_publishing instead of 502. 502 upstream_unavailable now always means nothing was sent
- *The API page shows your own IP address and client again for /api/v2/posts calls
- ~/api/v2/posts sends YouTube, Facebook and TikTok posts through the same engine as the older URL. Status codes and fields stay the same
- ~The 20-second wait is checked before the connection, as on the older URL: a request that is both too soon and for a network that is not connected gets 429 (was 400)
- ~A refusal because the Free month is used up no longer starts the 20-second wait
- ~Facebook on /api/v2/posts: an empty media list without facebook.postType is refused with 400, as on the older URL (it used to publish a text post)
- *A single .m4v video, or a video URL with #, is sent as a video post
- ~TikTok on /api/v2/posts: when TikTok does not confirm the upload, the answer is 400 (no_publish_id, or TikTok's error), and when our upload of a video stops it is 502 upload_worker_failed (it did not go through: send it again), as on the older URL. When our upload of a photo post stops after TikTok accepted it, the answer is 202 still_publishing (it may be live: do not send it again, History shows the result). Before, /api/v2 answered 2xx and History showed a failed post
- ~TikTok over the daily allowance whose host does not report the file size in time is refused with 400 tiktok_size_unknown instead of being queued
- +dryRun works on /api/v2/posts: send dryRun: true to check a post without sending it. The answer is 200 with dry_run: true and is not counted in usage_count. dryRun: false publishes as normal, and any other value is refused with 400. A check that gets no report in time is answered 503 dry_run_unavailable with Retry-After: send it again
Migration Guide
If your TikTok step treats any 2xx from /api/v2/posts as success, a 400 no_publish_id or 502 upload_worker_failed now means the upload did not go through: send it again. If your Facebook step sends an empty media list for text posts, leave the media fields out instead.
September 2026 (titles and descriptions)
YouTube and TikTok photo posts take a title and a description
- +YouTube videos and TikTok photo posts take a separate title and description, with the same rule in the dashboard, the API (both URLs, and posts queued for the next day) and the AI connector. YouTube: youtube.title (up to 100 characters) and youtube.description (up to 5,000 bytes). TikTok photo posts: the new tiktok.title (up to 90 characters) and tiktok.description (up to 4,000 characters)
- +What you leave out is filled from content.text (the caption). No title: the caption is the title. No description: the caption is the description when you sent a title (on TikTok, a title that is not the same as the caption). With neither, the caption is also the description when the title cannot hold all of it (on YouTube: more than one line, or over 100 characters; on TikTok: over 90 characters). When you send both fields, content.text is not used, and warnings says so with field_not_used
- ~A title or a description that is too long is shortened at the end of a word, never inside an emoji (a text with no space near the limit is cut where it fits), and < and > are removed from YouTube texts. The API refuses nothing for it: the post is sent, and the warnings in the answer say what was changed, with the codes title_shortened, description_shortened, characters_removed, text_partly_used and title_missing. The dashboard asks you to shorten a description that is too long before it posts
- *A TikTok photo post with a caption over 90 characters was refused by TikTok ("The request post info is empty or incorrect"), because the whole caption was sent as the photo title. This happened to 9 customer posts between July and August 2026. Now the title is shortened and the whole caption is the description
- *A YouTube description is measured in bytes, as YouTube measures it (a letter with an accent counts 2, an emoji 4). A description over 5,000 bytes, or with < or >, used to fail at YouTube after the answer said "processing". It is now shortened or cleaned and sent
- ~A TikTok video has one text, its caption, up to 2,200 characters: tiktok.title when sent, otherwise content.text. tiktok.description is not used on a video, and warnings says so
- *A post queued for the next day keeps its YouTube embeddable, license, publicStatsViewable, notifySubscribers and defaultLanguage options, and a scheduled TikTok photo post keeps its description and automatic music. Before, they were dropped
- ~The check that validate_post runs in the AI connector gives the same warning codes as a real post: for a YouTube title, caption_truncated is now title_shortened (Pinterest keeps caption_truncated), youtube_title_missing is now title_missing, and a YouTube text over 100 characters no longer gives caption_over_limit (it was a false warning). A TikTok photo text that is too long now gives title_shortened and description_shortened
September 2026 (fixes for API callers)Breaking
Profile names in any capital letters, a clear wait on every 429, YouTube titles, no early posts
- ~accountId finds a profile whatever the capital letters are, on both URLs: "@MyShop" finds "myshop". If two of your profiles differ only in capital letters, send the exact name or the profile UUID
- ~On the older URL (app.status200uploads.com/functions/v1/api-posts) an unknown profile is still answered 404 api_error, now with error.profiles listing your profiles, and the refusal no longer starts the 20-second wait
- +Every 429 carries retry_after_seconds in its body (error.retry_after_seconds on posts, retry_after_seconds on media imports), for tools such as n8n that read only the body. A throttled media import now also has a Retry-After header and "code": "rate_limited", on both URLs. The Retry-After header is sent only when the wait is an hour or less
- ~A post.scheduledFor more than 60 seconds in the future is refused with 400 and nothing is sent. Before, the field was ignored and the post went out at once, earlier than planned. A time in the past or within the next 60 seconds is still ignored. The time can be ISO 8601 with a time zone or a Unix time in seconds or milliseconds
- +A successful answer can carry a warnings array naming each field of the request that was not used and why (for example tiktok.privacyStatus instead of privacyLevel, an option block next to post instead of inside it, X madeWithAi and paidPartnership, LinkedIn carousel)
- +youtube.title sets the YouTube title, also for a post queued for the next day. When a title is sent and youtube.description is empty, content.text becomes the description. Without a title, the title still comes from content.text
- ~TikTok photo posts: PNG and GIF photos are sent to TikTok as JPEG copies so that the post can be published, because TikTok does not accept those formats; JPEG and WebP are sent as they are. HEIC, AVIF, BMP and TIFF photos are refused with 422 photo_format_not_supported before anything is sent. The warnings in the answer say when a photo was converted, and your original file is not changed
- ~The request count of an API key (usage_count, shown on the API page of the dashboard) now counts every request to the older URL, refused ones included, as /api/v2 already does. Before, it counted only posts that were sent or queued
Migration Guide
If you send post.scheduledFor with a future time, remove it to publish at once, or schedule the post in the dashboard. Scheduling through the API is planned.
September 2026 (large videos)
Videos up to 5 GB on X, LinkedIn, Facebook and Skool, 4 GB on TikTok
- ~Video limits: X, LinkedIn, Facebook and Skool 5 GB (5,368,709,120 bytes), TikTok 4 GB (4,000,000,000 bytes). YouTube stays at 5 GB, Instagram at 300 MB, Threads at 1 GB
- +A single video over 100 MB (X, Skool), 200 MB (LinkedIn) or 1 GB (Facebook) is sent in the background: 202 with data.status "processing", a job_id and a post_id; the result appears in History. Smaller videos answer as before
- +A TikTok video over 1 GB from our storage is fetched by TikTok itself; the answer is 200 "processing" with a publish_id, as for every TikTok post
September 2026 (pricing)Breaking
X add-on, Free monthly allowance, Skool from Beginner
- ~X posts need the X add-on: 403 plan_required with error.required "x_addon"
- +429 x_limit_reached / x_link_limit_reached when the X add-on's 200 posts or 20 link posts of the billing month are used, with resets_at
- ~Free over 60 successful posts per calendar month: 429 monthly_limit_reached with resets_at, not queued
- ~Skool from Beginner
- ~Skilled, Expert and Agency have no allowance; publish attempts capped at 500 per profile per UTC day
September 2026 (update)Breaking
Clearer errors, answers within 25 seconds, throttle on every network
- +A mediaID that does not exist on your account (never imported, deleted, or removed after 7 days) is answered at once with 404 media_not_found instead of 409 media_processing
- +POST /api/v2/media refuses a URL that does not return an image or a video with 415, and GET /api/v2/media answers 400 for a file_id that is not a UUID
- ~Every /api/v2/posts answer arrives within about 25 seconds: media still importing is waited for about 12 seconds (then 409 media_processing), and a network slower than that is answered 202 still_publishing (do not resend; the outcome appears in the post history)
- ~The 20-second throttle per network now also applies to TikTok, Facebook and YouTube, and a throttled post carries a Retry-After header
- ~An unknown profile is answered 403 account_not_found on every network, and every error from /api/v2/posts carries error.code
- ~A Facebook post without media no longer needs facebook.postType "text"
- ~X, Pinterest and Skool refusals come back as 4xx or 503 with their own codes (x_rejected, x_unavailable, pinterest_auth_failed, pinterest_sandbox_board, pinterest_rejected, skool_unavailable) instead of 500
- ~YouTube uploads answer 202 with a post_id, and the post history shows the upload's real outcome
- *TikTok photo posts over the size limit are refused with 413 MEDIA_TOO_LARGE before anything is sent
- *Unknown paths under /api/v2 answer a JSON 404 not_found
- !TikTok answers no longer include TikTok's temporary upload_url and upload_token
- +A mediaID whose import failed is answered 422 media_failed with the reason (was 500)
- ~Throttled posts carry error.code rate_limited, and Skool's own limits (one post per hour, 10 per day) answer 429 rate_limited with Retry-After instead of 500
- ~Facebook and LinkedIn answer 401 reconnect_required when they no longer accept the saved sign-in (also on image and video uploads), instead of 500
- ~403 plan_required answers include upgrade_url
September 2026
Large media imports, size limits up front, Threads
- +Media import accepts videos up to 5 GB. Large imports run in the background, report their progress on GET /api/v2/media?file_id=... and continue automatically after an interruption when the source server supports HTTP Range requests
- +Threads posting (platform "threads"): text only, one image or video, or a carousel of 2 to 20 items
- +accountId on /api/v2/posts accepts "@handle" or the profile name as well as the profile UUID, and /api/v2/posts accepts every network
- ~File size limits per network are checked before anything is sent: a file that is too large for the chosen network is refused with 413 MEDIA_TOO_LARGE
- ~A post whose media is still being imported is answered with 409 media_processing and a Retry-After header instead of a timeout
- ~The daily allowance counts successful posts only: a failed post no longer uses it
- ~A Pinterest post without a board id is refused with 400 before Pinterest is called
- *A single video sent to Instagram without a postType is published as a Reel
August 2026
Plan limits enforced on the server
- ~Plan limits are enforced on the server for every caller (dashboard, scheduler and API): a daily allowance per profile across all platforms, and X and Skool from the Apprentice plan
- ~A post over the daily allowance is queued for the next day (202 queued_for_next_day) instead of failing
July 2026
Skool
- +Skool community posts (platform "skool") with text, images and video
April 2026
X, LinkedIn and Pinterest
- +X (Twitter) posts with text, images and video, reply settings and Communities
- +LinkedIn posts with text, image or video
- +Pinterest image pins with board selection
March 2026
Instagram, Facebook and YouTube
- +Instagram (feed image, Reel, Story, carousel), Facebook (photo, video, Reel, text) and YouTube video posts
August 2025
Initial release
- +Create a post endpoint, starting with TikTok
- +Media import from a public URL: the returned file_id can be reused across posts
- +API keys with Bearer token authentication