Octoque API reference
Updated · OpenAPI file
Send requests to https://api.octoque.com/v1/… with Authorization: Bearer and an API key. Upload the file with POST /v1/media, create a draft with POST /v1/posts, then send it with /schedule, /queue or /publish-now. Each key has scopes (post.read, post.write, post.publish) and works on paid plans and the free trial.
Quick start
Four requests take a video from your computer to a scheduled post. Replace the ids in angle brackets with the ones the earlier answers gave you.
export OCTOQUE_API_KEY="oq_live_••••" # from You → Developers & AI
# 1. Find your accounts
curl "https://api.octoque.com/v1/accounts" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"
# 2. Upload the video
curl -X POST "https://api.octoque.com/v1/media" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-F "file=@lassi.mp4"
# 3. Make a draft for two accounts, each with its own caption
curl -X POST "https://api.octoque.com/v1/posts" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Content-Type: application/json" -d '{
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": ["<media id>"],
"targets": [
{"account_id": "<instagram account id>"},
{"account_id": "<youtube account id>", "options": {"title": "Three-minute mango lassi"}}
]
}'
# 4. Schedule it (or /queue, or /publish-now)
curl -X POST "https://api.octoque.com/v1/posts/<post id>/schedule" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Content-Type: application/json" -d '{"at": "2026-10-15T19:00:00+05:30"}'To post at each platform's golden hour instead of one fixed time, read the times from Golden hour, set each target's scheduled_at with Edit a post, then call Schedule with no body. That is exactly what the MCP server does when you ask your assistant to post "at golden hour".
Base URL and format
- Base URL:
https://api.octoque.com. Every path starts with/v1. - JSON in, JSON out, UTF-8. Uploads are
multipart/form-data. - Times are ISO 8601. Send them with a time zone offset (
2026-10-15T19:00:00+05:30). Post times come back in UTC; golden-hour and queue times come back in the audience's zone. - Ids are 32-character hex strings.
- Lists come wrapped as
{"data": [...]}.
Authentication
Make a key in the app under You → Developers & AI (workspace owners and admins can do this). The key starts with oq_live_ and is shown once: Octoque stores only a hash of it. Send it on every request:
curl "https://api.octoque.com/v1/posts" -H "Authorization: Bearer $OCTOQUE_API_KEY"- One workspace. A key belongs to the workspace it was made in and acts as the person who made it. The
X-Workspace-Idheader the app uses is ignored for keys. - Both checks apply. A request needs the scope on the key and the permission in that person's role. A key can't be given more than its maker has.
- No account settings. Signing in, passwords, API keys, team, billing, data export and deleting the account need a real sign-in. A key gets
403 session_requiredthere, so a leaked key can't lock you out or make more keys. - Revoke any time on the same page. Anything using the key stops at once. The page also shows when each key was last used.
Scopes
Pick these when you make the key. New keys start with the first three.
| Scope | Lets the key | Example use |
|---|---|---|
post.read | Read accounts, posts, files, queue times, history and results | A dashboard of what went live |
post.write | Upload files, create, edit, duplicate and delete posts (drafts) | An assistant that prepares drafts for you to check |
post.publish | Schedule, queue, post now, unschedule and retry; change queue times | A script that posts the moment your edit is exported |
account.manage | Connect and disconnect social accounts | Rarely needed: connecting needs the platform's sign-in page in a browser |
For an AI assistant you don't fully trust yet, give the key post.read and post.write only. It can then prepare drafts but never send anything.
Errors
Errors use HTTP status codes and one JSON shape. message is plain English you can show to people; code is stable for your code to check; field appears when one input is the problem.
{
"error": {
"code": "caption_too_long",
"message": "X allows 280 characters; this has 312. Shorten it in the X tab.",
"field": "targets[1].caption"
}
}| Status | Meaning | Common codes |
|---|---|---|
| 401 | No key, or the key is wrong or revoked | bad_api_key |
| 402 | Your plan doesn't include this, or this month's allowance is used | plan_limit |
| 403 | The key lacks the scope, the role lacks the permission, or it's an account-level action | scope_missing, forbidden, session_required |
| 404 | Not in this workspace | post_not_found, account_not_found, media_not_found |
| 409 | The post isn't in a state for that action | nothing_to_schedule, already_live, queue_full |
| 413 / 415 | The body or file is too big, or the file type isn't supported | too_large, file_too_large, unsupported_media |
| 422 | An input breaks a rule | caption_too_long, media_required, tiktok_rules |
One exception: when the JSON body itself doesn't match the expected shape (a missing required field, a wrong type), the 422 answer is {"detail": [...]} with one entry per problem, each with loc and msg.
Limits
- Request size: 1 MB for JSON, 1 GB per uploaded file. Bigger requests get
413before anything is read. - Plans: API keys work on Starter, Creator and Studio and during the 14-day free trial, not on Free (pricing). The trial includes 30 posts in total and 10 X posts. The monthly X post allowance is 30 on Starter, 150 on Creator and 500 on Studio; an X post with a link counts as 10.
- Request rate: there is no per-key request quota on these endpoints today. If one is added it will answer
429and be listed here and in the changelog. - Lists:
GET /v1/postsreturns at most 200 posts per call; usestatus,q,fromandtoto narrow it.
Captions are checked against each platform's limit, and videos against the length Octoque sends to each platform. A video that is too long fails for that platform unless you ask Octoque to trim it (target option trim: start or end).
| Platform | Caption (characters) | Longest video Octoque sends |
|---|---|---|
| 2,200 | 3:00 | |
| TikTok | 2,200 | 3:00, and no longer than the creator's own TikTok limit |
| YouTube | 5,000 | 3:00 |
| 3,000 | 10:00 | |
| X | 280 | 2:20 |
| 63,206 | 4:00 | |
| Threads | 500 | 5:00 |
| 800 | No Octoque cap | |
| Bluesky | 300 | No Octoque cap |
| 40,000 | No Octoque cap | |
| Google Business Profile | 1,500 | Photos only |
The post object
Every post endpoint answers with the same shape. The post's status sums up its targets; each target has its own.
| Field | What it is |
|---|---|
status | draft, scheduled, publishing, published (all live), partial (some live, some failed or cancelled), failed or cancelled |
approval | null, or pending, approved, rejected in workspaces that use approvals |
targets[].status | draft, scheduled, publishing, published, failed, cancelled, or removed (it was live, then deleted on the platform) |
targets[].scheduled_at | When it goes (or went) out, in UTC |
targets[].url | The live post on the platform, once published |
targets[].error_code / error_message | Why it didn't post: a stable code and a plain sentence you can show |
targets[].trimmed | true when a trimmed copy of the video went to this platform |
targets[].account_id | The account; null once that account was disconnected (handle keeps the name it had) |
Accounts
The social accounts connected to the key's workspace. Connecting a new account needs the platform's own sign-in page, so you do that in the app.
List connected accounts
GET/v1/accountsScope: post.read
Every account in the workspace, oldest first. Use the id values as account_id when you create a post. health is ok, warn or broken (broken means it needs reconnecting in the app).
curl "https://api.octoque.com/v1/accounts" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 31 lines)Hide the answer
{
"data": [
{
"id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"test": false,
"health": "ok",
"audience_regions": [
"India"
]
},
{
"id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"test": false,
"health": "ok",
"audience_regions": []
},
{
"id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"test": false,
"health": "ok",
"audience_regions": []
}
],
"test_accounts": false
}Read a TikTok creator's options
GET/v1/accounts/{account_id}/tiktokScope: post.write
What this TikTok account allows right now, read fresh from TikTok: who can see posts, which interactions the creator allows, the longest video and whether it can post. Call it before you send to TikTok and use these values in the target's options.
| Parameter | In | Type | What it is |
|---|---|---|---|
account_idrequired | path | string | A TikTok account's id. |
media | query | string | video (default) or image. |
account_idpath · stringrequiredA TikTok account's id.mediaquery · stringvideo(default) orimage.
curl "https://api.octoque.com/v1/accounts/b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a/tiktok?media=video" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 26 lines)Hide the answer
{
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"handle": "@mayacooks",
"nickname": "Maya Cooks",
"can_post": true,
"privacy_levels": [
{
"value": "PUBLIC_TO_EVERYONE",
"label": "Everyone"
},
{
"value": "MUTUAL_FOLLOW_FRIENDS",
"label": "Friends"
},
{
"value": "SELF_ONLY",
"label": "Only me"
}
],
"max_video_seconds": 600,
"interactions": {
"comment": true,
"duet": true,
"stitch": true
}
}409 tiktok_unsupported: TikTok can't be posted to through this account yet.502 tiktok_unreachable: TikTok didn't answer. Try again in a minute.
Set an account's audience
PATCH/v1/accounts/{account_id}Scope: post.write
Where this account's audience lives, up to three regions (extra ones are dropped). Region names: United States, Canada, UK, Europe, Middle East, India, Southeast Asia, Australia, Latin America, Africa.
| Parameter | In | Type | What it is |
|---|---|---|---|
account_idrequired | path | string | The account's id. |
audience_regionsrequired | body | string[] | Up to three region names. |
account_idpath · stringrequiredThe account's id.audience_regionsbody · string[]requiredUp to three region names.
curl -X PATCH "https://api.octoque.com/v1/accounts/a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"audience_regions": [
"India",
"Middle East"
]
}'{
"id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"test": false,
"health": "ok",
"audience_regions": [
"India",
"Middle East"
]
}Media
Upload the video or photo first, then pass its `id` in `media_ids` when you create the post. Files are checked by their bytes, not their name.
Upload a video or photo
POST/v1/mediaScope: post.write
One file per request as multipart/form-data, in a field called file. MP4 or MOV video, or JPG, PNG or WebP photo, up to 1 GB. The answer says how long the video is and which platforms it's too long for (too_long_for, platform: maximum seconds); you can let Octoque trim it per platform with the target option trim.
| Parameter | In | Type | What it is |
|---|---|---|---|
filerequired | form | file | The video or photo. |
fileform · filerequiredThe video or photo.
curl -X POST "https://api.octoque.com/v1/media" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-F "file=@lassi.mp4"{
"id": "e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e",
"kind": "video",
"filename": "lassi.mp4",
"size_bytes": 18402213,
"duration_s": 48.2,
"width": 1080,
"height": 1920,
"too_long_for": {},
"url": "/media/4f6a8c0e2b3d4f5a7c9e1b3d5f7a9c0e/0a2c4e6f8b1d4a3c5e7f9b0d2a4c6e8f.mp4",
"file_removed": false,
"created_at": "2026-10-14T09:11:02.118734+00:00"
}415 unsupported_media: Not an MP4, MOV, JPG, PNG or WebP file.413 file_too_large: Bigger than 1 GB.422 file_missing: Nofilefield.
List uploaded files
GET/v1/mediaScope: post.read
The workspace's 200 newest files you can still post, newest first, in the same shape as an upload.
curl "https://api.octoque.com/v1/media" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"{
"data": [
{
"id": "e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e",
"kind": "video",
"filename": "lassi.mp4",
"size_bytes": 18402213,
"duration_s": 48.2,
"width": 1080,
"height": 1920,
"too_long_for": {},
"url": "/media/4f6a8c0e2b3d4f5a7c9e1b3d5f7a9c0e/0a2c4e6f8b1d4a3c5e7f9b0d2a4c6e8f.mp4",
"file_removed": false,
"created_at": "2026-10-14T09:11:02.118734+00:00"
}
]
}Get a file
GET/v1/media/{media_id}Scope: post.read
One file, in the same shape as an upload. A video leaves Octoque 90 days after every post using it is done: then file_removed is true, url is null, and the post keeps its history. Sending a post whose video was removed answers 409 file_removed.
| Parameter | In | Type | What it is |
|---|---|---|---|
media_idrequired | path | string | The file's id. |
media_idpath · stringrequiredThe file's id.
curl "https://api.octoque.com/v1/media/e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"{
"id": "e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e",
"kind": "video",
"filename": "lassi.mp4",
"size_bytes": 18402213,
"duration_s": 48.2,
"width": 1080,
"height": 1920,
"too_long_for": {},
"url": null,
"file_removed": true,
"created_at": "2026-10-14T09:11:02.118734+00:00"
}404 media_not_found: No file with that id in this workspace.
Delete a file
DELETE/v1/media/{media_id}Scope: post.write
Deletes the file. Answers 204 with no body.
| Parameter | In | Type | What it is |
|---|---|---|---|
media_idrequired | path | string | The file's id. |
media_idpath · stringrequiredThe file's id.
curl -X DELETE "https://api.octoque.com/v1/media/e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Answer: 204 with no body.
Posts
A post is one caption and one file sent to one or more accounts. Each account is a target with its own caption, options, time and status. You create a post as a draft, then schedule it, queue it or post it now.
Create a post
POST/v1/postsScope: post.write
Makes a draft. Nothing is posted until you schedule it, queue it or post it now. Captions are checked against each platform's limit (for example 2,200 characters on Instagram and TikTok, 280 on X). Send an Idempotency-Key header (up to 80 characters) so a retried request returns the post it already made, with status 200 instead of 201.
| Parameter | In | Type | What it is |
|---|---|---|---|
caption | body | string | The caption every platform gets unless a target overrides it. |
media_ids | body | string[] | Uploaded file ids. Instagram and TikTok need a photo or video; YouTube needs a video. |
targetsrequired | body | object[] | At least one. Each: account_id (required), caption_override, options, scheduled_at (ISO 8601 with a time zone). Each account once per post. |
targets[].options | body | object | YouTube: title. TikTok: privacy_level (one of the creator's privacy_levels), allow_comment, allow_duet, allow_stitch, disclose_commercial, your_brand, branded_content. Any platform with a long video: trim: start or end (which part to keep). |
Idempotency-Key | header | string | Optional. Makes the request safe to repeat. |
captionbody · stringThe caption every platform gets unless a target overrides it.media_idsbody · string[]Uploaded file ids. Instagram and TikTok need a photo or video; YouTube needs a video.targetsbody · object[]requiredAt least one. Each:account_id(required),caption_override,options,scheduled_at(ISO 8601 with a time zone). Each account once per post.targets[].optionsbody · objectYouTube:title. TikTok:privacy_level(one of the creator'sprivacy_levels),allow_comment,allow_duet,allow_stitch,disclose_commercial,your_brand,branded_content. Any platform with a long video:trim:startorend(which part to keep).Idempotency-Keyheader · stringOptional. Makes the request safe to repeat.
curl -X POST "https://api.octoque.com/v1/posts" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Idempotency-Key: lassi-2026-10-14" \
-H "Content-Type: application/json" \
-d '{
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"targets": [
{
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70"
},
{
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true
}
},
{
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"options": {
"title": "Three-minute mango lassi"
}
}
]
}'Show the answer (201, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "draft",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "draft",
"caption_override": null,
"options": {},
"scheduled_at": null,
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "draft",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": null,
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "draft",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": null,
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}422 caption_too_long: A caption is over that platform's limit.422 account_not_found: Anaccount_idisn't in this workspace.422 tiktok_rules: TikTok options break TikTok's rules (for example branded content set to private).402 plan_limit: Over the plan's posts or X posts for the month.
List posts
GET/v1/postsScope: post.read
Newest first. Filter by status, caption text, or a time window (keeps posts with a target scheduled inside it).
| Parameter | In | Type | What it is |
|---|---|---|---|
status | query | string | Comma-separated: draft, scheduled, publishing, published, partial, failed, cancelled. |
q | query | string | Text the caption contains. |
from | query | date-time | Start of a time window. |
to | query | date-time | End of a time window (not included). |
limit | query | integer | Default 50, at most 200. |
statusquery · stringComma-separated:draft,scheduled,publishing,published,partial,failed,cancelled.qquery · stringText the caption contains.fromquery · date-timeStart of a time window.toquery · date-timeEnd of a time window (not included).limitquery · integerDefault 50, at most 200.
curl "https://api.octoque.com/v1/posts?status=scheduled&limit=20" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 71 lines)Hide the answer
{
"data": [
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T12:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}
]
}Get a post
GET/v1/posts/{post_id}Scope: post.read
One post with every target's status, time, live link (url) and, if something went wrong, error_code and a plain error_message you can show to people.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "partial",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "published",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": "https://www.instagram.com/reel/…",
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": "2026-10-15T13:31:12.204551+00:00"
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "published",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": "https://www.tiktok.com/@mayacooks/video/…",
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": "2026-10-15T14:31:40.882310+00:00"
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "failed",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T12:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}404 post_not_found: No such post in this workspace.
Edit a post
PATCH/v1/posts/{post_id}Scope: post.write
Change the shared caption, a target's caption, options or time, and add or take out platforms. Targets already posting or live are left alone. Changing a scheduled target's time moves it; a platform added to a scheduled post is scheduled too (its golden hour if no time).
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
caption | body | string | New shared caption. Refused once any platform is live. |
targets | body | object[] | Each: id (the target's id, required), caption_override (empty string clears it), options, scheduled_at. |
add | body | object[] | New platforms, shaped like a target when creating a post: account_id, caption_override, options, scheduled_at. |
remove | body | string[] | Target ids to take out. Never ones already posting or live; at least one platform must stay. |
post_idpath · stringrequiredThe post's id.captionbody · stringNew shared caption. Refused once any platform is live.targetsbody · object[]Each:id(the target's id, required),caption_override(empty string clears it),options,scheduled_at.addbody · object[]New platforms, shaped like a target when creating a post:account_id,caption_override,options,scheduled_at.removebody · string[]Target ids to take out. Never ones already posting or live; at least one platform must stay.
curl -X PATCH "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"scheduled_at": "2026-10-15T20:00:00+05:30"
}
]
}'Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T12:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 already_live: You changed the shared caption after some platforms went live, or tried to remove a live one.422 target_not_found: A targetidisn't part of this post.422 duplicate_account: An added account is already in the post.422 no_platforms: That would leave the post with no platforms.
Delete a live post on its platform
POST/v1/posts/{post_id}/targets/{target_id}/unpublishScope: post.delete_published
Deletes one live platform's post on the platform itself, for good (on YouTube with its views and comments). The target becomes removed and stays in the history. Works where can_remove is true: YouTube, Facebook, LinkedIn, X, Threads, Pinterest and Bluesky; Instagram and TikTok don't let apps delete posts.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
target_idrequired | path | string | The live target's id. |
post_idpath · stringrequiredThe post's id.target_idpath · stringrequiredThe live target's id.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/targets/1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c/unpublish" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T12:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 not_live: It isn't live there.409 cant_remove: The platform doesn't let apps delete posts. Delete it in its app.502 remove_failed: The platform didn't delete it just now. Try again in a minute.
Delete a post
DELETE/v1/posts/{post_id}Scope: post.write
Deletes the post from Octoque (not from the platforms). If any platform is live, the key also needs post.delete_published. Answers 204.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl -X DELETE "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Answer: 204 with no body.
Schedule a post
POST/v1/posts/{post_id}/scheduleScope: post.publish
Schedules every draft or unscheduled target. Send at to use one time for all of them, or leave the body out to use each target's own scheduled_at. A target without a future time goes at its platform's next golden hour. To post right away, use Publish now.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
at | body | date-time | Optional. One time for every target, ISO 8601 with a time zone. |
post_idpath · stringrequiredThe post's id.atbody · date-timeOptional. One time for every target, ISO 8601 with a time zone.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/schedule" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"at": "2026-10-15T19:00:00+05:30"
}'Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 nothing_to_schedule: Every target is already scheduled or posted.422 media_required: A platform needs a photo or video and the post has none.422 tiktok_rules: TikTok needs aprivacy_level, or the creator's settings don't allow a choice.
Add a post to the queue
POST/v1/posts/{post_id}/queueScope: post.publish
Schedules the draft targets for the workspace's next free queue time (see Queue times). No body.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/queue" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T12:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 queue_full: No free queue time in the next 60 days.
Post now
POST/v1/posts/{post_id}/publish-nowScope: post.publish
Sends every target that isn't live or posting yet, straight away. Targets move to publishing, then published or failed. Some platforms take a few minutes to process video, so poll Get a post.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/publish-now" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-14T09:15:03.120044+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "scheduled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-14T09:15:03.120044+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-14T09:15:03.120044+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 nothing_to_publish: Everything is already live or posting.
Unschedule a post
POST/v1/posts/{post_id}/cancelScope: post.publish
Every scheduled target becomes cancelled; live ones are not touched. You can schedule it again later.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/cancel" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "cancelled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "cancelled",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "cancelled",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "cancelled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T12:30:00+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 nothing_to_cancel: Nothing is waiting to go out.
Retry failed platforms
POST/v1/posts/{post_id}/retryScope: post.publish
Sends the failed targets again, now. Fix the cause first (the target's error_message says what it was).
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/retry" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 67 lines)Hide the answer
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "scheduled",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "published",
"caption_override": null,
"options": {},
"scheduled_at": "2026-10-15T13:30:00+00:00",
"url": "https://www.instagram.com/reel/…",
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": "2026-10-15T13:31:12.204551+00:00"
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "published",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": "2026-10-15T14:30:00+00:00",
"url": "https://www.tiktok.com/@mayacooks/video/…",
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": "2026-10-15T14:31:40.882310+00:00"
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "scheduled",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": "2026-10-15T15:02:10.554120+00:00",
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}409 nothing_to_retry: Nothing failed.409 account_removed: The account was disconnected.
Duplicate a post
POST/v1/posts/{post_id}/duplicateScope: post.write
A new draft with the same caption, file, accounts and options, and no times. Handy for reposting a video that did well.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post to copy. |
post_idpath · stringrequiredThe post to copy.
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/duplicate" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (201, 67 lines)Hide the answer
{
"id": "5c7e9a1b3d4f4c6e8a0b2d4f6a8c0e1b",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"media_ids": [
"e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e"
],
"status": "draft",
"approval": null,
"created_at": "2026-10-14T09:12:44.512301+00:00",
"targets": [
{
"id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"account_id": "a3f9c2e14b7d4e0f9c1a2b3c4d5e6f70",
"platform": "instagram",
"handle": "@mayacooks",
"status": "draft",
"caption_override": null,
"options": {},
"scheduled_at": null,
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "2e4a6c8e0a1c4e3a9b7d5f3c1e0a8b6d",
"account_id": "b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a",
"platform": "tiktok",
"handle": "@mayacooks",
"status": "draft",
"caption_override": null,
"options": {
"privacy_level": "PUBLIC_TO_EVERYONE",
"allow_comment": true,
"allow_duet": false,
"allow_stitch": false,
"disclose_commercial": false,
"your_brand": false,
"branded_content": false
},
"scheduled_at": null,
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
},
{
"id": "3f5b7d9f1b2d4f4b0c8e6a4d2f1b9c7e",
"account_id": "c5d7e9f1a2b34c6d8e0f1a2b3c4d5e6f",
"platform": "youtube",
"handle": "Maya Cooks",
"status": "draft",
"caption_override": null,
"options": {
"title": "Three-minute mango lassi"
},
"scheduled_at": null,
"url": null,
"error_code": null,
"error_message": null,
"trimmed": false,
"published_at": null
}
]
}A post's history
GET/v1/posts/{post_id}/historyScope: post.read
Who did what and when (created, scheduled, edited, retried…), and every attempt to post each target.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/history" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 26 lines)Hide the answer
{
"events": [
{
"action": "post.created",
"by": "Maya",
"at": "2026-10-14T09:12:44.530112+00:00",
"detail": {
"targets": 3
}
},
{
"action": "post.scheduled",
"by": "Maya",
"at": "2026-10-14T09:13:05.007431+00:00",
"detail": {}
}
],
"attempts": [
{
"target_id": "1d3f5a7c9e0b4d2f8a6c4e2b0d9f7a5c",
"ok": true,
"status": "published",
"at": "2026-10-15T13:30:02.311902+00:00"
}
]
}Golden hour and queue
Golden hour is the next good time to post on each platform, in your audience's time zone. Queue times are the workspace's regular posting rhythm.
Next golden hour per platform
GET/v1/golden-hourAny key
The next golden-hour time for each platform you ask for, in the audience's time zone when the workspace has audience regions, otherwise in the key owner's. These are starting points per platform (how they work: /golden-hour). activity is a 24-value relative activity curve by hour.
| Parameter | In | Type | What it is |
|---|---|---|---|
platforms | query | string | Comma-separated: instagram, tiktok, youtube, linkedin, x, facebook or threads. Default: instagram,tiktok,youtube,linkedin,x. |
platformsquery · stringComma-separated:instagram,tiktok,youtube,linkedin,x,facebookorthreads. Default: instagram,tiktok,youtube,linkedin,x.
curl "https://api.octoque.com/v1/golden-hour?platforms=instagram,tiktok,youtube" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 46 lines)Hide the answer
{
"platforms": {
"instagram": {
"at": "2026-10-15T19:00:00+05:30",
"hour": 19
},
"tiktok": {
"at": "2026-10-15T20:00:00+05:30",
"hour": 20
},
"youtube": {
"at": "2026-10-15T18:00:00+05:30",
"hour": 18
}
},
"activity": [
2,
1,
1,
1,
1,
2,
4,
8,
14,
18,
16,
14,
17,
15,
12,
11,
13,
19,
27,
34,
31,
22,
12,
6
],
"audience_regions": [
"India"
],
"timezone": "Asia/Kolkata"
}List queue times
GET/v1/queue-slotsScope: post.read
The workspace's queue times and the next free one. A new workspace starts with weekday mornings at 09:00, every day at 19:00 and Saturday at 10:00. weekdays counts from 0 = Monday; times are in the workspace's time zone.
curl "https://api.octoque.com/v1/queue-slots" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 39 lines)Hide the answer
{
"data": [
{
"id": "6b8d0f2a4c5e4b7d9f1a3c5e7b9d1f3a",
"weekdays": [
0,
1,
2,
3,
4
],
"time": "09:00",
"label": "Weekday mornings"
},
{
"id": "7a9c1e3f5b6d4a8c2e0f9b7d5c3a1e8f",
"weekdays": [
5
],
"time": "10:00",
"label": "Saturday"
},
{
"id": "8c0e2a4b6d7f4c9e1a3b5d7f9c1e3a5b",
"weekdays": [
0,
1,
2,
3,
4,
5,
6
],
"time": "19:00",
"label": "Golden hour"
}
],
"next_free": "2026-10-14T19:00:00+05:30"
}Add a queue time
POST/v1/queue-slotsScope: post.publish
Adds a regular posting time.
| Parameter | In | Type | What it is |
|---|---|---|---|
weekdaysrequired | body | integer[] | Days, 0 = Monday to 6 = Sunday. |
timerequired | body | string | HH:MM, 24-hour. |
label | body | string | A name you'll recognise. |
weekdaysbody · integer[]requiredDays, 0 = Monday to 6 = Sunday.timebody · stringrequiredHH:MM, 24-hour.labelbody · stringA name you'll recognise.
curl -X POST "https://api.octoque.com/v1/queue-slots" \
-H "Authorization: Bearer $OCTOQUE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"weekdays": [
6
],
"time": "11:30",
"label": "Sunday brunch"
}'{
"id": "9d1f3b5c7e8a4d0f2b4c6e8a0d2f4b6c",
"weekdays": [
6
],
"time": "11:30",
"label": "Sunday brunch"
}Remove a queue time
DELETE/v1/queue-slots/{slot_id}Scope: post.publish
Removes it. Posts already scheduled keep their times. Answers 204.
| Parameter | In | Type | What it is |
|---|---|---|---|
slot_idrequired | path | string | The queue time's id. |
slot_idpath · stringrequiredThe queue time's id.
curl -X DELETE "https://api.octoque.com/v1/queue-slots/7a9c1e3f5b6d4a8c2e0f9b7d5c3a1e8f" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Answer: 204 with no body.
Results
Numbers the platforms report for live posts. A post shows nothing for a platform until that platform has reported.
A post's results
GET/v1/posts/{post_id}/metricsScope: post.read
Views, likes, comments, shares and new followers per platform, plus totals. A platform that hasn't reported yet (or a post deleted on the platform) shows an empty object.
| Parameter | In | Type | What it is |
|---|---|---|---|
post_idrequired | path | string | The post's id. |
post_idpath · stringrequiredThe post's id.
curl "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/metrics" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 26 lines)Hide the answer
{
"total": {
"views": 5120,
"likes": 409,
"comments": 61,
"shares": 102,
"followers": 20
},
"platforms": {
"instagram": {
"views": 3010,
"likes": 240,
"comments": 36,
"shares": 60,
"followers": 12
},
"tiktok": {
"views": 2110,
"likes": 169,
"comments": 25,
"shares": 42,
"followers": 8
},
"youtube": {}
}
}Results summary
GET/v1/analytics/summaryScope: post.read
Totals for posts that went live in the last days days: views per day, per platform, and the top five posts.
| Parameter | In | Type | What it is |
|---|---|---|---|
days | query | integer | 7 to 90. Default 28. |
daysquery · integer7 to 90. Default 28.
curl "https://api.octoque.com/v1/analytics/summary?days=7" \
-H "Authorization: Bearer $OCTOQUE_API_KEY"Show the answer (200, 88 lines)Hide the answer
{
"days": 7,
"totals": {
"views": 5120,
"likes": 409,
"comments": 61,
"shares": 102,
"followers": 20
},
"posts_published": 1,
"series": [
{
"date": "2026-10-09",
"views": 0
},
{
"date": "2026-10-10",
"views": 0
},
{
"date": "2026-10-11",
"views": 0
},
{
"date": "2026-10-12",
"views": 0
},
{
"date": "2026-10-13",
"views": 0
},
{
"date": "2026-10-14",
"views": 0
},
{
"date": "2026-10-15",
"views": 5120
}
],
"platforms": [
{
"platform": "instagram",
"views": 3010
},
{
"platform": "tiktok",
"views": 2110
}
],
"top_posts": [
{
"id": "9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95",
"caption": "Three-minute mango lassi. Save it for Sunday.",
"views": 5120,
"platforms": [
"instagram",
"tiktok"
]
}
],
"activity_by_hour": [
2,
1,
1,
1,
1,
2,
4,
8,
14,
18,
16,
14,
17,
15,
12,
11,
13,
19,
27,
34,
31,
22,
12,
6
]
}Health
For uptime checks.
Health check
GET/v1/healthNo key
Answers {"ok": true} when the API is up. No key needed.
curl "https://api.octoque.com/v1/health"{
"ok": true
}OpenAPI file
The same endpoints as an OpenAPI 3.1 file, for Postman, Insomnia, code generators or an AI agent: /docs/api/openapi.json. It lists only what a key can call.
Questions people ask
Is there an official SDK?
Not yet. The API is plain JSON over HTTPS, so any HTTP client works, and the OpenAPI file can generate a typed client in most languages.
Can I post to a platform without a video?
LinkedIn, X, Facebook, Threads, Bluesky, Reddit and Google Business Profile take text-only posts. Instagram, TikTok and Pinterest need a photo or video, and YouTube needs a video; the API answers 422 media_required otherwise.
How do I know when a post went live?
Poll Get a post. Each target moves from scheduled to publishing to published (with its url) or failed (with a plain error_message). Outgoing webhooks aren't available yet.
Can a key connect a new Instagram or TikTok account?
Connecting means signing in on the platform's own page, so do it in the app. Once connected, the account shows up in List accounts.
Why did TikTok refuse my post?
TikTok requires the creator to choose who can see each post, with no default. Read the allowed values from the creator's options and send one as privacy_level. Branded content can't be private.
Do API posts count towards my plan?
Yes, the same as posts made in the app, including the monthly X allowance.
Keep reading
Sources
All links checked on 14 October 2026.
- OpenAPI Specification v3.1.0
- TikTok for Developers: Content Sharing Guidelines (updated 4 August 2026). Why TikTok posts need a privacy choice