octoque
API reference · v1

Octoque API reference

Everything an API key can do: upload a video or photo, make one post for many accounts, schedule it at golden hour, and read what happened.

Updated · OpenAPI file

The short answer

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.

Terminal
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:

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-Id header 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_required there, 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.

ScopeLets the keyExample use
post.readRead accounts, posts, files, queue times, history and resultsA dashboard of what went live
post.writeUpload files, create, edit, duplicate and delete posts (drafts)An assistant that prepares drafts for you to check
post.publishSchedule, queue, post now, unschedule and retry; change queue timesA script that posts the moment your edit is exported
account.manageConnect and disconnect social accountsRarely needed: connecting needs the platform's sign-in page in a browser
A few actions need a role permission as well: deleting a post that is already live needs post.delete_published (managers and up).

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.

Answer · 422
{
  "error": {
    "code": "caption_too_long",
    "message": "X allows 280 characters; this has 312. Shorten it in the X tab.",
    "field": "targets[1].caption"
  }
}
StatusMeaningCommon codes
401No key, or the key is wrong or revokedbad_api_key
402Your plan doesn't include this, or this month's allowance is usedplan_limit
403The key lacks the scope, the role lacks the permission, or it's an account-level actionscope_missing, forbidden, session_required
404Not in this workspacepost_not_found, account_not_found, media_not_found
409The post isn't in a state for that actionnothing_to_schedule, already_live, queue_full
413 / 415The body or file is too big, or the file type isn't supportedtoo_large, file_too_large, unsupported_media
422An input breaks a rulecaption_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 413 before 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 429 and be listed here and in the changelog.
  • Lists: GET /v1/posts returns at most 200 posts per call; use status, q, from and to to 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).

Limits the API checks, per platform
PlatformCaption (characters)Longest video Octoque sends
Instagram2,2003:00
TikTok2,2003:00, and no longer than the creator's own TikTok limit
YouTube5,0003:00
LinkedIn3,00010:00
X2802:20
Facebook63,2064:00
Threads5005:00
Pinterest800No Octoque cap
Bluesky300No Octoque cap
Reddit40,000No Octoque cap
Google Business Profile1,500Photos only
Instagram, TikTok and Pinterest need a photo or video; YouTube needs a video. TikTok posts also need a privacy choice and follow TikTok's sharing rules, on every way in. Pinterest needs a board (target option board_id), and Reddit a community and title (subreddit, title) before a post can be scheduled.

The post object

Every post endpoint answers with the same shape. The post's status sums up its targets; each target has its own.

FieldWhat it is
statusdraft, scheduled, publishing, published (all live), partial (some live, some failed or cancelled), failed or cancelled
approvalnull, or pending, approved, rejected in workspaces that use approvals
targets[].statusdraft, scheduled, publishing, published, failed, cancelled, or removed (it was live, then deleted on the platform)
targets[].scheduled_atWhen it goes (or went) out, in UTC
targets[].urlThe live post on the platform, once published
targets[].error_code / error_messageWhy it didn't post: a stable code and a plain sentence you can show
targets[].trimmedtrue when a trimmed copy of the video went to this platform
targets[].account_idThe 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).

Request
curl "https://api.octoque.com/v1/accounts" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 31 lines)
Answer · 200
{
  "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.

  • account_idpath · stringrequiredA TikTok account's id.
  • mediaquery · stringvideo (default) or image.
Request
curl "https://api.octoque.com/v1/accounts/b81e4d2a9c6f4b3e8d7a1c0f2e3d4b5a/tiktok?media=video" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 26 lines)
Answer · 200
{
  "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.

  • account_idpath · stringrequiredThe account's id.
  • audience_regionsbody · string[]requiredUp to three region names.
Request
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"
    ]
  }'
Answer · 200
{
  "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.

  • fileform · filerequiredThe video or photo.
Request
curl -X POST "https://api.octoque.com/v1/media" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY" \
  -F "file=@lassi.mp4"
Answer · 201
{
  "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: No file field.

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.

Request
curl "https://api.octoque.com/v1/media" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Answer · 200
{
  "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.

  • media_idpath · stringrequiredThe file's id.
Request
curl "https://api.octoque.com/v1/media/e2b4c6d8f0a14b3c9d7e5f1a3b5c7d9e" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Answer · 200
{
  "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.

  • media_idpath · stringrequiredThe file's id.
Request
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.

  • 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'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-Keyheader · stringOptional. Makes the request safe to repeat.
Request
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)
Answer · 201
{
  "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: An account_id isn'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).

  • 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.
Request
curl "https://api.octoque.com/v1/posts?status=scheduled&limit=20" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 71 lines)
Answer · 200
{
  "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.

  • post_idpath · stringrequiredThe post's id.
Request
curl "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 67 lines)
Answer · 200
{
  "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).

  • 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.
Request
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)
Answer · 200
{
  "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 target id isn'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.

  • post_idpath · stringrequiredThe post's id.
  • target_idpath · stringrequiredThe live target's id.
Request
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)
Answer · 200
{
  "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.

  • post_idpath · stringrequiredThe post's id.
Request
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.

  • post_idpath · stringrequiredThe post's id.
  • atbody · date-timeOptional. One time for every target, ISO 8601 with a time zone.
Request
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)
Answer · 200
{
  "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 a privacy_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.

  • post_idpath · stringrequiredThe post's id.
Request
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/queue" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 67 lines)
Answer · 200
{
  "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.

  • post_idpath · stringrequiredThe post's id.
Request
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/publish-now" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 67 lines)
Answer · 200
{
  "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.

  • post_idpath · stringrequiredThe post's id.
Request
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/cancel" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 67 lines)
Answer · 200
{
  "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).

  • post_idpath · stringrequiredThe post's id.
Request
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/retry" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 67 lines)
Answer · 200
{
  "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.

  • post_idpath · stringrequiredThe post to copy.
Request
curl -X POST "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/duplicate" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (201, 67 lines)
Answer · 201
{
  "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.

  • post_idpath · stringrequiredThe post's id.
Request
curl "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/history" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 26 lines)
Answer · 200
{
  "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.

  • platformsquery · stringComma-separated: instagram, tiktok, youtube, linkedin, x, facebook or threads. Default: instagram,tiktok,youtube,linkedin,x.
Request
curl "https://api.octoque.com/v1/golden-hour?platforms=instagram,tiktok,youtube" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 46 lines)
Answer · 200
{
  "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.

Request
curl "https://api.octoque.com/v1/queue-slots" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 39 lines)
Answer · 200
{
  "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.

  • weekdaysbody · integer[]requiredDays, 0 = Monday to 6 = Sunday.
  • timebody · stringrequiredHH:MM, 24-hour.
  • labelbody · stringA name you'll recognise.
Request
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"
  }'
Answer · 201
{
  "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.

  • slot_idpath · stringrequiredThe queue time's id.
Request
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.

  • post_idpath · stringrequiredThe post's id.
Request
curl "https://api.octoque.com/v1/posts/9f2c4e1ab7d04c5e8a3f6b2d1e0c7a95/metrics" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 26 lines)
Answer · 200
{
  "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.

  • daysquery · integer7 to 90. Default 28.
Request
curl "https://api.octoque.com/v1/analytics/summary?days=7" \
  -H "Authorization: Bearer $OCTOQUE_API_KEY"
Show the answer (200, 88 lines)
Answer · 200
{
  "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.

Request
curl "https://api.octoque.com/v1/health"
Answer · 200
{
  "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.

  1. OpenAPI Specification v3.1.0
  2. TikTok for Developers: Content Sharing Guidelines (updated 4 August 2026). Why TikTok posts need a privacy choice