API
Read and write your Postopus ideas, posts and inspiration over HTTP with a personal access token, schedule or publish posts, and have Tako draft in your voice.
The Postopus API is a JSON API over HTTPS. It does the same things as the connector, with the same rules: your role, the workspace's paid plan, approvals and the AI allowance.
Base URL:
https://api.postopus.com
Authenticate#
Every request sends a personal access token in the Authorization header:
curl https://api.postopus.com/v1/me \
-H "Authorization: Bearer tako_YOUR_TOKEN"
The examples below read the token from the POSTOPUS_TOKEN environment variable.
Create a token#
- In Postopus, open the menu under your name and choose Settings, then Developer.
- Choose Create token.
- Enter a Token name, turn on the scopes the token needs under Scopes, and choose Create token. Only the scopes your role can grant are listed.
- Copy the token and choose Done. This is the only time Postopus shows it.
A token:
- starts with
tako_; - belongs to you and to the workspace you are in when you create it;
- has the name and the scopes you chose;
- can never have more scopes than your current role in the workspace allows, checked on every request;
- stops working when you revoke it, when you leave the workspace, or while the workspace has no paid plan.
The API needs a paid plan: Inkling, Deep Diver or Kraken. The free trial on its own does not include it. If you pick a plan while trial days are left, it works from then on. Without a paid plan, Settings > Developer shows "The API needs a paid plan" and a Go to Billing button instead of Create token.
Revoke a token#
The API tokens list in Settings > Developer shows tokens with their scopes, when each was last used, when it was created and its status. Owners and admins see every token in the workspace, with a Created by column, and can revoke any of them. Members and viewers see and revoke only the tokens they created. Choose Revoke on a token, then Revoke again to confirm. Any app using it loses access right away. You can revoke tokens with or without a paid plan.
Scopes#
| Scope | Lets the token |
|---|---|
ideas:read |
Read ideas and categories |
ideas:write |
Create, edit and delete ideas |
posts:read |
Read posts and connected social accounts |
posts:write |
Create, edit and delete posts |
publish:schedule |
Schedule and reschedule posts |
publish:now |
Publish posts right away, and delete posts from LinkedIn and X |
inspiration:read |
Read saved inspiration |
inspiration:write |
Save inspiration |
voice:read |
List voices |
drafting:use |
Draft with Tako in a voice |
context:write |
Send facts and samples of your own writing to Postopus, where they wait for your review |
Owners, admins and members can give a token any of these. A viewer's token can only have ideas:read, posts:read, inspiration:read and voice:read.
Responses#
A success returns { "data": ... }. Lists also return "meta": { "count": n }. An error returns { "error": { "code": "...", "message": "..." } }. Branch on code; the message may change.
Lists return 50 items by default; ideas, posts and inspiration come newest first. Pass limit (1 to 200) for more or fewer.
Who you are#
GET /v1/me, any scope. Returns your name, email and the token's workspace.
curl https://api.postopus.com/v1/me \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
Ideas#
GET /v1/ideas (ideas:read). Optional status: raw, developing, drafted or archived.
curl "https://api.postopus.com/v1/ideas?status=raw" \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
GET /v1/ideas/{id} (ideas:read). One idea.
curl https://api.postopus.com/v1/ideas/IDEA_ID \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
POST /v1/ideas (ideas:write). Body: content (required), sourceUrl, categoryId.
curl -X POST https://api.postopus.com/v1/ideas \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Why we stopped using hashtags"}'
PATCH /v1/ideas/{id} (ideas:write). Any of content, sourceUrl, categoryId, status.
curl -X PATCH https://api.postopus.com/v1/ideas/IDEA_ID \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "archived"}'
DELETE /v1/ideas/{id} (ideas:write). Deletes the idea for good.
curl -X DELETE https://api.postopus.com/v1/ideas/IDEA_ID \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
Categories#
GET /v1/categories (ideas:read). Active categories; add includeArchived=true for archived ones too.
curl https://api.postopus.com/v1/categories \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
Posts#
GET /v1/posts (posts:read). Optional status: draft, scheduled, publishing, processing_media, published, failed or partially_failed.
curl "https://api.postopus.com/v1/posts?status=scheduled" \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
GET /v1/posts/{id} (posts:read). One post, with targetAccountIds, scheduledTimezone and its publications: one per account, each with id, accountId, platform, kind (post, or repost for an automatic repost), status, scheduledFor, publishedAt, platformPostId and url, the link to the live post on X or LinkedIn once it is published.
curl https://api.postopus.com/v1/posts/POST_ID \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
POST /v1/posts (posts:write). Creates a draft. Body: content (required), firstComment, categoryId, targetAccountIds. If your posts need approval, the draft is created pending review.
curl -X POST https://api.postopus.com/v1/posts \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "We shipped threads today.", "targetAccountIds": ["ACCOUNT_ID"]}'
PATCH /v1/posts/{id} (posts:write). Any of content, firstComment, categoryId, targetAccountIds. Changing the text, first comment or accounts of an approval-gated post sends it back to review.
curl -X PATCH https://api.postopus.com/v1/posts/POST_ID \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"firstComment": "Details on our blog."}'
Delete a post#
DELETE /v1/posts/{id}?alsoDeleteFromPlatforms=false (posts:write). The alsoDeleteFromPlatforms parameter is required and makes the same choice as the delete dialog in the app:
falsedeletes the post from Postopus only. Anything already published stays live on LinkedIn and X.truealso deletes each published copy on LinkedIn and X, which cannot be undone. This also needspublish:now.
Either way the post leaves Postopus with its publications, so a scheduled post no longer goes out. The post's author can delete it, and so can a workspace owner or admin; anyone else gets POST_DELETE_NOT_ALLOWED. A post that is publishing at that moment is refused with POST_PUBLISHING.
The response has the post's id, "deleted": true and publications, one per account: publicationId, platform, url (the live post, if it went out), platformDeleted, and a warning when LinkedIn or X did not delete it. A failed platform delete does not stop the delete in Postopus: the post stays live at its url and you can remove it there.
curl -X DELETE "https://api.postopus.com/v1/posts/POST_ID?alsoDeleteFromPlatforms=true" \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
Schedule a post#
POST /v1/posts/{id}/schedule (publish:schedule). Only a draft or a failed post can be scheduled. Body:
scheduledFor(required): an ISO 8601 time in the future, on the minute (seconds set to 0), such as2030-01-15T09:00:00Z. ReplaceFUTURE_TIMEandNEW_FUTURE_TIMEin the examples with one;accountIds(required): one or more active accounts of the workspace;scheduledTimezone: an IANA timezone such asEurope/Lisbon.
Postopus publishes the post at that time. A post that needs approval and is not approved yet waits for an owner or admin to approve it. A post that is already scheduled is refused with POST_ALREADY_SCHEDULED, and one that is publishing or published with POST_ALREADY_PUBLISHED.
curl -X POST https://api.postopus.com/v1/posts/POST_ID/schedule \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"scheduledFor": "FUTURE_TIME", "accountIds": ["ACCOUNT_ID"], "scheduledTimezone": "Europe/Lisbon"}'
To move a scheduled post to a new time, send "reschedule": true with the new scheduledFor (and optionally scheduledTimezone) and no accountIds. Only the time changes; the post keeps its accounts. A post that is not scheduled is refused with POST_NOT_SCHEDULED.
curl -X POST https://api.postopus.com/v1/posts/POST_ID/schedule \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"scheduledFor": "NEW_FUTURE_TIME", "reschedule": true}'
Publish a post now#
POST /v1/posts/{id}/publish (publish:now). Publishes a draft or failed post right away, to its target accounts or to the accountIds you send. This posts publicly on your LinkedIn and X accounts, through the same publishing as Publish Now in the app, first comment included.
Before anything is posted:
- a post that needs approval and is not approved is refused with
APPROVAL_REQUIRED; - a scheduled post is refused with
POST_ALREADY_SCHEDULED, and a post that is publishing or published withPOST_ALREADY_PUBLISHED; - the post is claimed, so two requests at the same moment cannot both publish it.
A successful response has the post and one result per account: accountId, success, and either the platformPostId with url, the link to the live post on X or LinkedIn, or an error. When publishing fails, the request returns PUBLISH_FAILED instead.
curl -X POST https://api.postopus.com/v1/posts/POST_ID/publish \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
Social accounts#
GET /v1/social-accounts (posts:read). The LinkedIn and X accounts connected to the workspace, active ones first, with the ids you pass as accountIds and targetAccountIds. Optional platform, such as linkedin or x. Tokens and secrets are never returned.
curl "https://api.postopus.com/v1/social-accounts?platform=linkedin" \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
Inspiration#
GET /v1/inspiration (inspiration:read). Optional platform.
curl https://api.postopus.com/v1/inspiration \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
POST /v1/inspiration (inspiration:write). Body: content (required), note, platform, sourceUrl, authorHandle, mediaUrls, categoryId. If you already saved the same sourceUrl, you get the saved item back with "meta": { "deduplicated": true } and status 200 instead of 201.
curl -X POST https://api.postopus.com/v1/inspiration \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"content": "Great hook about pricing", "platform": "x", "sourceUrl": "https://x.com/example/status/1"}'
Voices#
GET /v1/voices (voice:read). The team voice (id team) and each person in the workspace whose voice Tako has learned.
curl https://api.postopus.com/v1/voices \
-H "Authorization: Bearer $POSTOPUS_TOKEN"
Draft with Tako#
POST /v1/draft (drafting:use). Body:
action(required):draft_ideaorthread(input is an idea),hooks(input is a topic),rewriteorremix(input is your text);input(required): the idea, topic or text;voiceId:teamfor the team voice; leave it out for your own voice.
It returns the text Tako wrote. It does not create a post or publish anything, and it counts against your workspace's monthly AI allowance.
curl -X POST https://api.postopus.com/v1/draft \
-H "Authorization: Bearer $POSTOPUS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"action": "draft_idea", "input": "Lessons from our first 100 customers"}'
Errors#
| HTTP | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR |
The request was not valid: a missing field, bad JSON, a time in the past. |
| 401 | MISSING_AUTHORIZATION_HEADER |
No Authorization: Bearer header. |
| 401 | INVALID_TOKEN |
The token is not valid. |
| 401 | TOKEN_REVOKED |
The token was revoked. |
| 401 | TOKEN_EXPIRED |
The token expired. |
| 402 | SUBSCRIPTION_REQUIRED |
The workspace has no paid plan, or you scheduled or published in a workspace your plan does not cover. |
| 403 | INSUFFICIENT_SCOPE |
The token lacks the scope for this endpoint. |
| 403 | NOT_TEAM_MEMBER |
You are no longer a member of the workspace. |
| 403 | APPROVAL_REQUIRED |
The post needs approval before it can be published. |
| 403 | POST_DELETE_NOT_ALLOWED |
Only the post's author or a workspace owner or admin can delete the post. |
| 404 | NOT_FOUND |
No such item in this workspace, or no such route. |
| 405 | METHOD_NOT_ALLOWED |
The route does not take this method. |
| 409 | POST_ALREADY_SCHEDULED |
The post is already scheduled. Send reschedule: true to move it, or unschedule it in Postopus first. |
| 409 | POST_ALREADY_PUBLISHED |
The post is publishing or already published. |
| 409 | POST_NOT_SCHEDULED |
You asked to reschedule a post that is not scheduled. |
| 409 | POST_PUBLISHING |
The post is publishing right now, so it cannot be deleted yet. |
| 429 | RATE_LIMITED |
Too many requests. See below. |
| 429 | AI_QUOTA_EXCEEDED |
The workspace has used this month's AI allowance. |
| 500 | SERVER_ERROR |
Something went wrong on our side. Try again. |
| 502 | PUBLISH_FAILED |
Publishing failed on at least one account. |
Rate limits#
Each token can make 120 requests a minute. Every response says where you stand:
X-RateLimit-Limit: 120;X-RateLimit-Remaining: requests left in this minute;X-RateLimit-Reset: when the window resets, in Unix seconds.
Over the limit you get 429 RATE_LIMITED with a Retry-After header, in seconds.