Posts
18 endpoints for posts, with parameters and a real response example.
/postsList posts
Lists the workspace's posts: status, scheduled date, and the first words of the caption. Use it to find which post to act on next, since every other post endpoint needs its id. Filter by status, period, or project to narrow the search; without filters, returns the most recent.
| Parameter | In | Type | Description |
|---|---|---|---|
status | query | string | Comma-separated list of statuses to filter by. |
from | query | string | ISO date. Filters by scheduled date. |
to | query | string | ISO date. Filters by scheduled date. |
projectId | query | string | |
limit | query | integer | Default 25, max 100. |
cursor | query | string | Opaque cursor from a previous response's next field. |
Response
{
"posts": [
{
"id": "8c64bee5-f756-47b7-a64a-01f5db597202",
"status": "draft",
"scheduledFor": null,
"textContent": "Seu nicho pode estar amplo demais sem você perceber. Quando a mensagem tenta alcançar todo mundo, ela deixa de ser memorável para qualquer pessoa.\nQual desses sinais aparece mai...",
"projectId": "c85848ba-2881-4a2e-9bdd-841b26d07359",
"contentFormat": "animated_audio",
"theme": "Tres sinais de que o seu nicho esta amplo demais"
},
{
"id": "a6eed866-eed5-4f60-b3a5-1aaba4bee2eb",
"status": "draft",
"scheduledFor": null,
"textContent": "Your first SaaS customers probably aren’t waiting for an ad. They’re already dealing with a painful problem you can solve.\n\nStart with direct conversations and a simple offer. W...",
"projectId": "c85848ba-2881-4a2e-9bdd-841b26d07359",
"contentFormat": "animated_audio",
"theme": "How to land your first 10 SaaS customers without spending on ads"
}
],
"next": "eyJjaGF2ZSI6IjIwMjYtMDktMTNUMDU6NTg6MzYuNDUyNTI4KzAwOjAwIiwiaWQiOiJhNmVlZDg2Ni1lZWQ1LTRmNjAtYjNhNS0xYWFiYTRiZWUyZWIifQ"
}/posts202Create a post, in any of the six formats
Creates a post from a theme and starts generating it. The format parameter picks which of the six formats to make, and defaults to carrossel. Every format costs 1 credit and takes on the order of a minute (the carousel: median 43s, p99 87s, measured in production). Fire-and-forget: responds 202 with state: "generating"; poll GET /posts/{id} for the outcome. The four formats in preview are refused with 403 unless the workspace has them enabled, and nothing is charged.
Answers 202. The work finishes in the background; poll GET /posts/:id for the outcome.
| Parameter | In | Type | Description |
|---|---|---|---|
projectIdrequired | body | string | |
theme | body | string | What the post is about, in the client's words. |
format | body | "carousel" | "caption_reel" | "animated_audio" | "narrated_photos" | "premium_carousel" | "infographic" | Which format to generate. Defaults to carrossel. Formats in preview (audio_animado, narrated_photos, carrossel_profissional, infografico) are refused with 403 unless the workspace has them enabled. |
link | body | string | A URL to read before writing. When present, theme becomes the instruction for what to do with it. Only the carrossel format reads a link; any other format is refused. |
/posts/{id}Get a post, whatever its format
Returns one post in full, in any of the six formats. The envelope is always the same, format says which format it is, and content carries what belongs to that format: slides for the three carousel-shaped formats, the text blocks and look for caption_reel, the script and scenes for the two narrated ones. content is null while the post is still generating, which is a real state and not an error: read status to know.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
Response
{
"id": "e7869afa-d470-4e9b-a4c9-4c1936604a4b",
"format": "carousel",
"status": "draft",
"projectId": "c85848ba-2881-4a2e-9bdd-841b26d07359",
"workspaceId": "2bd5c04d-1dd4-456e-8704-9d7b84703fd0",
"scheduledFor": null,
"textContent": null,
"mediaUrls": [
{
"url": "https://.../post-images/ai-edits/e7869afa-d470-4e9b-a4c9-4c1936604a4b/b14c1fbe-b6f0-4ae0-bfd0-b1aaaf67a52b.webp",
"type": "image"
}
],
"content": {
"slides": [
{
"id": "1663f551-6958-41f6-bedb-e4294a9ff9a9",
"order": 0,
"variant": null,
"fields": [
{
"name": "profissional",
"value": {
"blocos": [
{
"peso": "etiqueta",
"texto": "04 · USO"
},
{
"peso": "forte",
"texto": "Metricaas: mede se a galera realmente usa"
}
],
"destaque": ""
}
}
],
"titleFont": null,
"bodyFont": null,
"colors": {
"background": "#fff1e2",
"text": "#1D2939",
"brand": "#ff6e05"
}
}
]
}
}/posts/{id}Update a post, whatever its format
Changes the caption and, on the formats that have one, the content inside the video: reel on caption_reel, narration on animated_audio and narrated_photos. Send only what changes; the caption is replaced in full and never merged. Sending reel on a post that is not a reel (or narration on one that is not narrated) is refused with the field name, never ignored. Only works before the post publishes.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
caption | body | stringmax 2200 chars | The Instagram caption, replaced in full. Up to 2200 characters, the same ceiling Instagram has. |
reel | body | object | Only on the caption_reel format: the three text blocks and the look of the video. |
narration | body | object | Only on animated_audio and narrated_photos: the spoken script and what is drawn over it. Changing script does NOT re-record the audio. |
/posts/{id}Delete a post
Permanently deletes the post. Irreversible.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
/posts/{id}/mediaReplace a post's media
Replaces a single-image post's media with the given list. Does not apply to a carousel (its image is generated from its slides) or to a reel (its background video is replaced via POST /posts/{id}/clip). An empty list removes the media. Only works before the post publishes.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
mediarequired | body | object[]max 10 items | The full media list, at most 10 items (the Instagram carousel limit). An empty list removes the media. |
/posts/{id}/scheduleSchedule a post
Schedules the post to publish on its own at a future date and time, or changes the date of a post already scheduled. Only works on a draft, a previously failed post, or one already scheduled: a post in flight (publishing, queued, generating) or already published cannot be rescheduled this way.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
whenrequired | body | string | ISO 8601 with a timezone, in the future. Either Z or an offset like -03:00. |
/posts/{id}/unscheduleUnschedule a post
Takes the post out of the schedule queue and returns it to draft, without deleting anything. Only works on a scheduled post.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
/posts/{id}/archiveArchive a post
Removes the post from the Posttar calendar without deleting it; reactivate brings it back. Does NOT remove anything from Instagram: an already published post stays published there.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
/posts/{id}/reactivateReactivate a post
Takes the post out of the archive and returns it to draft, ready to edit and schedule again. Only works on an archived post.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
/posts/{id}/publish202Publish a post now
Publishes the post to Instagram right away. Fire-and-forget: responds 202 with the post in publishing state (median 38s, p99 61s, measured in production); poll GET /posts/{id} for the outcome. Irreversible.
Answers 202. The work finishes in the background; poll GET /posts/:id for the outcome.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
/posts/{id}/slidesAdd a slide
Appends a new slide to the end of the carousel, inheriting the last slide's layout with placeholder text. Edit that text afterwards with PATCH /slides/{id}. Carousel only.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
layoutId | body | string | Without it, inherits the layout of the post's last slide. |
/posts/{id}/slides/orderReorder slides
Changes the order of the carousel's slides. Send the complete list of slide ids in the new order; a missing or repeated id is rejected, because the order cannot have a gap.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
orderrequired | body | string[]max 50 items | The complete list of slide ids, in the new order. |
/posts/{id}/edit-budgetGet a post's image-edit budget
Returns how many AI image edits (POST /slides/{id}/reimagine) this post has used and how many remain, so a client can check before spending one (about $0.015 each, capped at 2 on the standard plan) instead of risking a call just to find the budget empty.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
Response
{
"used": 1,
"cap": 2,
"remaining": 1
}/posts/{id}/clipsList a reel's available clips
Lists the background clips available to this reel from the project's video library: id and description of each, before choosing one with POST /posts/{id}/clip.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
Response
{
"clips": []
}/posts/{id}/clipSet a reel's background clip
Replaces the reel's background video with a clip from the project's video library. clipId must come from GET /posts/{id}/clips.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
clipIdrequired | body | string |
/posts/{id}/tracksList a reel's available tracks
Lists the music tracks this reel can use: name, description, duration, which one is currently in use, and a link to listen to each, before choosing one with POST /posts/{id}/track.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
Response
{
"tracks": [
{
"id": "94917ea8-17e6-47de-a2df-c79146cb5771",
"name": "Bad Bunny - MONACO (Instrumental) - TYPE",
"description": null,
"durationSeconds": 267.377778,
"suggestedStartSeconds": 19,
"url": "https://.../audio-tracks/posttar/bad-bunny-monaco-instrumental-type.mp3",
"inUse": false
},
{
"id": "b6bb3c6d-9324-4df2-aced-70a6aead9a55",
"name": "INSONAMIA - Ronald Figo",
"description": null,
"durationSeconds": 181.36815,
"suggestedStartSeconds": 15,
"url": "https://.../audio-tracks/posttar/insonamia-ronald-figo.mp3",
"inUse": false
}
],
"inUse": "fda25fc1-6f3f-4eb6-b7d5-c53501a8c077"
}/posts/{id}/trackSet a reel's track
Sets, changes, or removes the reel's music. trackId must come from GET /posts/{id}/tracks; null mutes the reel. startSeconds picks which second of the track the reel's 7 seconds start from.
| Parameter | In | Type | Description |
|---|---|---|---|
idrequired | path | string | Opaque id from a previous response. |
trackIdrequired | body | string | null | From GET /posts/:id/tracks. Null mutes the reel. |
startSeconds | body | number | What second of the track the reel's 7 seconds start from. |