Posts
Creating, scheduling, changing, and canceling posts.
Create a post
POST /v1/posts
Authorization: Bearer tb_live_xxx
Idempotency-Key: 6f1c2b7e-0d8a-4f7e-9a51-2c1f7b0e9d34
Content-Type: application/json
{
"content": "Weekend promo 🎉",
"media_ids": ["0b9d..."],
"targets": [{ "account_id": "a1.." }, { "account_id": "b2.." }],
"scheduled_at": "2026-10-15T09:00:00+07:00"
}| Field | Description |
|---|---|
content | The post text |
media_ids | Media ids from an upload, in display order |
media_urls | Optional. Public URLs of photos or videos; Tebar downloads them first (same rules as POST /v1/media/from-url) and adds them after media_ids. Up to 20 with media_ids. A failed download makes no post (400 media_download_failed) |
targets | Target accounts (account_id from GET /v1/accounts) |
scheduled_at | Optional. Without it, the post is published right away |
201 response:
{
"id": "p1..",
"status": "scheduled",
"scheduled_at": "2026-10-15T02:00:00Z",
"targets": [
{
"id": "t1..",
"account_id": "a1..",
"platform": "instagram",
"status": "pending",
"permalink": null
},
{
"id": "t2..",
"account_id": "b2..",
"platform": "threads",
"status": "pending",
"permalink": null
}
]
}Publishing runs in the background. Check GET /v1/posts/{id}: each target becomes published with a permalink, or failed with an error_code.
A single video on Instagram publishes as a Reel automatically. Two or more media items become a carousel (Instagram up to 10, Threads up to 20).
A version per account
Each target can have its own text and/or media (media_ids and/or media_urls). Fields not sent follow the shared version. content: "" means deliberately without text.
{
"content": "What's your favorite coffee?",
"targets": [
{ "account_id": "th..", "options": { "poll": { "options": ["Black", "Latte"] } } },
{ "account_id": "ig..", "content": "New on the menu this week ☕", "media_ids": ["m1.."] }
]
}Threads threads
content is the first post. Each item of options.thread goes out as the next reply, in order (up to 10 follow-up parts). A part is text, or { "text", "media_ids" } / { "text", "media_url" } with 1 photo or video (media_url is downloaded by Tebar like media_urls). If publishing fails partway, a retry continues from the next part without reposting the ones already out. Needs the threads_manage_replies permission (see the table below).
{
"content": "5 tips for iced latte at home 🧵",
"targets": [
{
"account_id": "th..",
"options": {
"thread": [
"1. Start with a strong espresso.",
{ "text": "2. Cold milk, not hot.", "media_ids": ["m1.."] },
{ "media_url": "https://example.com/latte.mp4" }
]
}
}
],
"scheduled_at": "2026-10-31T19:30:00+07:00"
}Options per platform
Sent in targets[].options. Unknown keys are refused (400 invalid_options).
| Platform | Option | Rules |
|---|---|---|
| Threads | thread: (string | { text?, media_ids? })[] | Needs the threads_manage_replies permission (accounts connected before Oct 24, 2026: reconnect); without it 400 option_permission_missing. Thread: 1–10 follow-up parts. Each part is text (≤ 500 characters) or { "text": "…", "media_ids": ["…"] } with 1 photo or video. Errors in a specific part include details.thread_part (2 = the first part after the main post) |
| Threads | poll: { options: string[] } | 2–4 options, 1–25 characters. Only posts without media |
| Threads | link_attachment: url | Link card. Only posts without media |
| Threads | text_attachment: { text, link_url? } | Long text ≤ 10,000 characters. Only posts without media |
| Threads | topic_tag: string | 1–50 characters, without . and & |
| Threads | reply_control | everyone, accounts_you_follow, mentioned_only, followers_only, parent_post_author_only. Anything but everyone (Threads' default, not sent) needs threads_manage_replies |
format: "feed" | "story" | Story: exactly 1 media item, no caption, videos 3–60 seconds and ≤ 100 MB | |
share_to_feed: boolean | Reels only (default true) | |
cover_media_id / thumb_offset_ms | Reel cover: an image id, or a video frame in milliseconds | |
| TikTok | privacy_level | Business accounts (video_public_only in GET /v1/accounts/{id}/tiktok/creator-info): optional; videos are always PUBLIC_TO_EVERYONE (anything else is 400 tiktok_privacy_unavailable), photos without a privacy go out public. Other accounts: required for direct posts, one of the privacy_level_options, chosen by the user (without it 400 tiktok_privacy_required) |
| TikTok | post_mode: "direct" | "draft" | draft: sent to the TikTok app's inbox to be finished there |
| TikTok | allow_comment, allow_duet, allow_stitch | Business accounts: allowed by default, false turns off. Other accounts: default false. Duet and Stitch are video only. Anything the creator turned off in TikTok stays off |
| TikTok | commercial: { your_brand, branded_content } | Commercial content disclosure (at least one true) |
| TikTok | video_cover_timestamp_ms, is_aigc | The video's cover frame in milliseconds; mark AI-generated content. Business accounts also take cover_media_id: a JPG/PNG image id (360-1920 px, short side up to 1080 px, 20 MB) as the cover |
| TikTok | photo_title, auto_add_music | Photos only. A TikTok post holds 1 video or 1–35 photos (400 invalid_media_mix) |
| YouTube | title, made_for_kids | Both required. title 1-100 characters without < or >; always ask the user for made_for_kids. The post text is the description (up to 5,000, no < or >) |
| YouTube | privacy: "public" | "unlisted" | "private", tags, category_id | Default public. tags up to 500 characters in total |
| YouTube | contains_synthetic_media, notify_subscribers | Mark realistic AI or altered content; notify_subscribers: false skips notifying subscribers |
| YouTube | cover_media_id | Id of a JPG or PNG from the media library as the thumbnail, set once the video is up. Not for Shorts. The channel must be phone-verified (youtube.com/verify); when YouTube refuses, the video stays up with its automatic thumbnail |
visibility: "PUBLIC" | "CONNECTIONS" | PUBLIC (default): everyone on LinkedIn. CONNECTIONS: connections only | |
| Telegram | silent, protect_content | No notification sound; the post cannot be forwarded or saved. Default false |
| Telegram | no_link_preview | Links in the text without a preview card. Only posts without media |
board_id, title, link | board_id required, from GET /v1/accounts/{id}/pinterest/boards (no board: 400 pinterest_board_required). title up to 100 characters, link the destination URL. The post text is the description (up to 800). Exactly 1 photo | |
| Discord | silent, no_link_preview | No push notification to members; links in the text without a preview card. Default false. Mentions such as @everyone are always sent without pinging anyone |
link: url | Article card. Only posts without media |
Threads allows 5 unique links per post (400 too_many_links).
Managing posts
| Request | What it does |
|---|---|
PATCH /v1/posts/{id} | Change content, media_ids, scheduled_at, or each account’s version and options (targets[]) of a post not published yet |
DELETE /v1/posts/{id} | Cancel a scheduled post |
POST /v1/posts/{id}/retry | Retry the failed accounts. Never reposts the ones already published |
POST /v1/posts/{id}/remove | Remove from Tebar's history. The post on Instagram/Threads/TikTok is not deleted |
A post that has started publishing cannot be changed (409 post_not_editable). To publish a scheduled post now, send PATCH with scheduled_at set to the current time.
To change one account's version or options in a scheduled post, send targets with accounts already in the post. A field sent replaces that account's (options as a whole, so send again the other options you want to keep); content or media_ids set to null make the account follow the shared version again. Accounts cannot be added or removed (400 account_not_in_post).
{
"targets": [
{ "account_id": "th..", "options": { "thread": ["The new part 2"], "topic_tag": "coffee" } },
{ "account_id": "ig..", "content": null, "media_ids": null }
]
}