Publishing

Drafts and approvals

Save posts as drafts, hold them for review with requiresApproval, and approve or reject them with one call before anything goes live.

Not every post should publish the moment it is written. A draft is saved and goes nowhere until you schedule it. A post that requires approval has a time but waits in pending_approval until someone with the right access approves it. Both are ordinary posts, so they show up in GET /v1/posts and can be edited like any other.

#Save a draft

Send isDraft: true, or simply leave out every scheduling field. platforms is optional for drafts, so you can save the text and media before anyone has chosen the accounts.

curl -X POST https://api.pozy.ai/v1/posts \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Draft: holiday opening hours. Confirm with the store team.",
    "isDraft": true,
    "tags": ["holiday", "needs-review"]
  }'

isDraft: true wins over publishNow, scheduledFor and queuedFromProfile, so a draft can never publish by accident. Drafts skip most platform checks, which is why an incomplete post saves without errors. The checks run when you schedule it.

List drafts with GET /v1/posts?status=draft, optionally filtered by profileId, tags or search.

#Turn a draft into a scheduled post

Update the post with isDraft: false and one of scheduledFor, publishNow or queuedFromProfile. Add platforms if the draft had none.

curl -X PUT https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88 \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "isDraft": false,
    "content": "Holiday hours: open 10:00 to 16:00 on 24 and 31 December.",
    "platforms": [
      { "platform": "facebook", "accountId": "6710c3e2a9f14b0d8e5c7a25" },
      { "platform": "googlebusiness", "accountId": "6710c3e2a9f14b0d8e5c7a26" }
    ],
    "scheduledFor": "2026-12-20T09:00:00",
    "timezone": "Europe/Madrid"
  }'
Note

If you send a time without isDraft: false, the update succeeds but the post stays a draft. This is deliberate: an editor changing the suggested time of a draft should not publish it.

Scheduling runs the full platform validation (media rules, required fields, text limits). A post that fails it returns 400 and stays a draft. Run validation first if you want to show problems before the person presses Schedule.

#Hold a post for approval

Add requiresApproval: true and a time. The post is saved as pending_approval and will not publish, even when its time comes, until it is approved.

Request body
{
  "content": "Flash sale: 30% off annual plans until Sunday.",
  "platforms": [
    { "platform": "instagram", "accountId": "6710c3e2a9f14b0d8e5c7a22" },
    { "platform": "linkedin", "accountId": "6710c3e2a9f14b0d8e5c7a21" }
  ],
  "mediaItems": [{ "type": "image", "url": "https://pozy.ai/media/temp/1730289600_z1x5_sale.jpg" }],
  "scheduledFor": "2026-11-20T10:00:00",
  "timezone": "Europe/Madrid",
  "requiresApproval": true
}

A common setup: writers and AI agents create posts with keys that always set requiresApproval, and a person reviews the list each morning with GET /v1/posts?status=pending_approval.

#Approve or reject

POST /v1/posts/{postId}/review takes one field, decision, which is approve or reject:

curl -X POST https://api.pozy.ai/v1/posts/6721a8c04e9b2f1d7c3a5e88/review \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "decision": "approve" }'
Decision Result
approve The post becomes scheduled for its scheduledFor and post.scheduled fires. If that time has already passed, it publishes within a couple of minutes.
reject The post goes back to draft. Edit it and send it for approval again, or delete it.

Reviewing a post that is not pending_approval returns 409. Approval does not fire post.scheduled at creation time, only when the post is approved.

#Who can create, approve and publish

Caller Create drafts and posts Approve or reject Notes
Workspace owner, admin or member Yes Yes From the dashboard or the MCP server.
Workspace viewer No No Read-only.
Read-write API key Yes Yes Restrict it to some profiles with a profile-scoped key.
Read-only API key No No Writes return 403 with code: "read_only_key".

To keep approval with people only, give automated writers a key that is scoped to the right profiles and always send requiresApproval: true from your own code. Keys cannot be forced to send it, so treat it as a rule in your integration.

#Platform drafts are different

Two platforms have a draft of their own, separate from Pozy drafts:

  • TikTok: tiktokSettings.draft: true uploads the video or photos to the creator's TikTok inbox, where they finish and post it in the app.
  • Facebook: facebookSettings.draft: true creates an unpublished Page post.

For Pozy these are published posts: the upload succeeded. See TikTok and Facebook.

#Endpoints

Endpoint What it does
POST /v1/posts Create post
PUT /v1/posts/{postId} Update post
POST /v1/posts/{postId}/review Approve or reject a post
GET /v1/posts List posts
DELETE /v1/posts/{postId} Delete post

#Webhook events

Event When it fires
post.scheduled Post scheduled.