Read and edit
One call reads any post, one call edits it, whatever its format.
GET /posts/{id} reads any format and PATCH /posts/{id} edits it. You do not need to know the format beforehand: the answer tells you, in format, and puts what belongs to that format in content.
format | What content carries | What you can change |
|---|---|---|
carousel | slides: each slide's id, layout and text fields | The caption, plus the slide endpoints |
caption_reel | The three text blocks, font, alignment, colors, sizes, clip and track | The caption and reel |
animated_audio | script, hook, speed and the illustrated scenes | The caption and narration |
narrated_photos | script, hook, speed and the photo scenes | The caption and narration |
premium_carousel | slides: six AI-drawn pages | The caption, plus POST /slides/{id}/reimagine |
infographic | slides: one AI-drawn piece | The caption, plus POST /slides/{id}/reimagine |
twitter_repost | hook, author, sourceKind, sourceUrl, sourceHandle, durationSeconds and videoUrl | The caption, plus PATCH /posts/{id}/repost for the hook and the header |
react_video | speech, speechState, speechError, speechRegenLeft, personaKind, the same source fields as the repost, speechDurationSeconds and videoUrl | The caption, plus PATCH /posts/{id}/react to redo the speech |
motion | origin, idea, script, stage, error, alterationUsed, alterationRequest, canUndo, activeVersion and videoUrl | The caption, plus ONE change with POST /posts/{id}/motion/alteration; after it, POST /posts/{id}/motion/undo switches between the original and the changed version, as many times as needed |
content comes back null while the post is still generating. That is a real state, not an error: the post exists and its content does not exist yet. Read status.
The fields of the video formats
The examples on this page are trimmed to what teaches the shape. A video format carries more, and these are the ones worth knowing before you build. The complete response of every format is in the Reference.
| Where | Field | What it is |
|---|---|---|
| Every format | mediaUrls[].thumbnail | A still frame for a video item. Absent on images. |
caption_reel | videoUrl, coverUrl | The rendered MP4 and its cover. This is how you download the reel. |
caption_reel | mediaOutOfDate | true when the text or look changed after the last render: the MP4 on videoUrl is behind. Publishing re-renders first. |
caption_reel | clipSource, clipUrl, clipId | Where the background video came from, and which library item it is. clipId is the same name POST /posts/{id}/clip takes. Note that the swap has no way back. |
caption_reel | trackId, startSeconds | The music in use and the second it starts from, under the same names POST /posts/{id}/track takes. Read one, send the other back. |
caption_reel | boxColor, inkColor, blockBoxColors, blockInkColors, sizes | The look of the three text boxes, per block. |
animated_audio, narrated_photos | durationSeconds, language | How long the narration is, and the language it was written in. |
narrated_photos | photoStyle, scenesVersion | The image treatment, and the version you send back to avoid overwriting a concurrent edit. |
| Both narrated formats | updatedAt | When the content row last changed. |
twitter_repost | sourceKind, sourceUrl, sourceHandle | Where the video came from: instagram with the post's link and its owner, or upload when it was sent as a file in the app. |
twitter_repost | videoUrl, durationSeconds | The rendered MP4 (the finished reel, with the header and the hook over the video) and how long the video is. mediaUrls carries the same file and is the one to publish from: videoUrl is a mirror and can lag right after the video is remade. The source video itself is not exposed. |
react_video | speech, speechState, speechError | What the person says, and whether a new speech is ready, still generating or failed (with the whole reason in speechError). |
react_video | speechRegenLeft | How many times the speech can still be redone with PATCH /posts/{id}/react. Up to 2. The number can drop when a redo that failed had already been paid. |
react_video | personaKind | person when the project's avatar reacts, house when it is a Posttar presenter. |
react_video | sourceKind, sourceUrl, sourceHandle, durationSeconds, speechDurationSeconds, videoUrl | Where the video came from (the same fields as the repost), how long it and the speech are, and the rendered MP4. The source video itself is not exposed. |
An animated_audio scene has no id; a narrated_photos scene does. The two shapes are genuinely different, and PATCH replaces the whole list either way, so nothing addresses a scene by id.
Read a post you just created
The same two calls work for every format. Nothing here branches on what you made.
- 1
Read it.
formattells you what it is.curl -H "Authorization: Bearer $POSTTAR_KEY" "https://api.posttar.com/v1/posts/b713e349-..."{ "id": "b713e349-...", "format": "caption_reel", "status": "draft", "projectId": "c85848ba-...", "textContent": "Your niche is not the topic you like...", "mediaUrls": [{ "url": "https://.../out.mp4", "type": "video" }], "content": { "blocks": ["Your niche is not the topic you like", "it is the problem you can solve again", "Answer the 3 questions in the caption"], "frames": [0, 60, 150], "font": "Inter", "alignment": "center", "boxStyle": "rounded" } }
Editing
caption works on every format. reel only on caption_reel, narration only on the two narrated ones. Sending the wrong one is refused with the field's name in the message, never ignored: ignoring it would let you believe you had saved.
Change the caption and the reel's hook in one call.
curl -X PATCH -H "Authorization: Bearer $POSTTAR_KEY" -H "Content-Type: application/json" \
-d '{"caption":"the new caption",
"reel":{"block1":"A sharper hook"}}' \
"https://api.posttar.com/v1/posts/b713e349-..."Change a narrated script. It does NOT re-record the audio: the video keeps the voice that is already there, and the post is flagged as having stale media.
curl -X PATCH -H "Authorization: Bearer $POSTTAR_KEY" -H "Content-Type: application/json" \
-d '{"narration":{"script":"[calm] Look at this. [break] Three things change."}}' \
"https://api.posttar.com/v1/posts/8c64bee5-..."A scene is { start, end, type, fields }, and each type only accepts the fields it draws. Read the current ones in content.scenes and send the list back complete: it replaces, it does not merge. The Reference lists all thirteen types.
The reel's clip and track
The background clip and the music are their own catalogs, so they have their own endpoints: GET /posts/{id}/clips and GET /posts/{id}/tracks list what this post can use, and POST /posts/{id}/clip and POST /posts/{id}/track pick one. They only apply to caption_reel.
startSeconds is optional, and trackId: null mutes the reel.
curl -X POST -H "Authorization: Bearer $POSTTAR_KEY" -H "Content-Type: application/json" \
-d '{"trackId":"94917ea8-...","startSeconds":19}' \
"https://api.posttar.com/v1/posts/b713e349-.../track"