Posttar API

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.

formatWhat content carriesWhat you can change
carouselslides: each slide's id, layout and text fieldsThe caption, plus the slide endpoints
caption_reelThe three text blocks, font, alignment, colors, sizes, clip and trackThe caption and reel
animated_audioscript, hook, speed and the illustrated scenesThe caption and narration
narrated_photosscript, hook, speed and the photo scenesThe caption and narration
premium_carouselslides: six AI-drawn pagesThe caption, plus POST /slides/{id}/reimagine
infographicslides: one AI-drawn pieceThe caption, plus POST /slides/{id}/reimagine
twitter_reposthook, author, sourceKind, sourceUrl, sourceHandle, durationSeconds and videoUrlThe caption, plus PATCH /posts/{id}/repost for the hook and the header
react_videospeech, speechState, speechError, speechRegenLeft, personaKind, the same source fields as the repost, speechDurationSeconds and videoUrlThe caption, plus PATCH /posts/{id}/react to redo the speech
motionorigin, idea, script, stage, error, alterationUsed, alterationRequest, canUndo, activeVersion and videoUrlThe 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.

WhereFieldWhat it is
Every formatmediaUrls[].thumbnailA still frame for a video item. Absent on images.
caption_reelvideoUrl, coverUrlThe rendered MP4 and its cover. This is how you download the reel.
caption_reelmediaOutOfDatetrue when the text or look changed after the last render: the MP4 on videoUrl is behind. Publishing re-renders first.
caption_reelclipSource, clipUrl, clipIdWhere 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_reeltrackId, startSecondsThe 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_reelboxColor, inkColor, blockBoxColors, blockInkColors, sizesThe look of the three text boxes, per block.
animated_audio, narrated_photosdurationSeconds, languageHow long the narration is, and the language it was written in.
narrated_photosphotoStyle, scenesVersionThe image treatment, and the version you send back to avoid overwriting a concurrent edit.
Both narrated formatsupdatedAtWhen the content row last changed.
twitter_repostsourceKind, sourceUrl, sourceHandleWhere 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_repostvideoUrl, durationSecondsThe 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_videospeech, speechState, speechErrorWhat the person says, and whether a new speech is ready, still generating or failed (with the whole reason in speechError).
react_videospeechRegenLeftHow 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_videopersonaKindperson when the project's avatar reacts, house when it is a Posttar presenter.
react_videosourceKind, sourceUrl, sourceHandle, durationSeconds, speechDurationSeconds, videoUrlWhere 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. 1

    Read it. format tells 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"