Skip to content
UGC API

Create a post

A post is one piece of content sent to one or more accounts. Each account and placement gets its own result. This page covers POST /v1/posts and the endpoints to read and cancel posts.

Updated

POST /v1/posts

FieldTypeDescription
accountsstring[], requiredAccount IDs from GET /v1/accounts. Can mix platforms.
formatstring, requiredvideo, slideshow or image.
mediastring[], requiredPublic URLs. One for video and image, 2 or more in order for slideshow.
captionstringCaption with hashtags. Used as the description on YouTube.
scheduled_atISO 8601 stringWhen to publish, like 2026-11-01T17:00:00Z. Omit to publish now.
external_idstringYour ID for this post. Returned in results and webhooks.
optionsobjectPer-platform options: instagram, tiktok, youtube, facebook. See formats and options.
bash
curl https://ugcapi.dev/v1/posts \
  -H "Authorization: Bearer ugc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "accounts": ["acc_tt_01", "acc_ig_01"],
    "format": "video",
    "media": ["https://cdn.example.com/clip.mp4"],
    "caption": "Day 1 of the test #ugc",
    "scheduled_at": "2026-11-01T17:00:00Z",
    "external_id": "deliverable-981",
    "options": {
      "instagram": { "grid": true, "story": true },
      "tiktok": { "draft": false, "ai_generated": false }
    }
  }'

Response

json
{
  "id": "post_abc",
  "status": "scheduled",
  "format": "video",
  "scheduled_at": "2026-11-01T17:00:00Z",
  "external_id": "deliverable-981",
  "results": [
    { "account_id": "acc_tt_01", "platform": "tiktok", "placement": "video", "status": "scheduled", "url": null, "error": null },
    { "account_id": "acc_ig_01", "platform": "instagram", "placement": "reel", "status": "scheduled", "url": null, "error": null },
    { "account_id": "acc_ig_01", "platform": "instagram", "placement": "story", "status": "scheduled", "url": null, "error": null }
  ]
}

Each result is one post credit. Result status is scheduled, publishing, published or failed. A published result has a public url. A failed one has an error object with code and message. See pricing and credits.

Read a post

javascript
const res = await fetch("https://ugcapi.dev/v1/posts/post_abc", {
  headers: { "Authorization": "Bearer " + process.env.UGCAPI_KEY },
});
const post = await res.json();
for (const r of post.results) console.log(r.platform, r.placement, r.status, r.url);

List posts

GET /v1/posts returns posts newest first. Query parameters: status, account_id, external_id, limit and cursor. The response has data and next_cursor. Pass next_cursor as cursor to get the next page; it is null on the last page.

bash
curl "https://ugcapi.dev/v1/posts?status=failed&limit=50" -H "Authorization: Bearer ugc_live_..."

Cancel a scheduled post

bash
curl -X DELETE https://ugcapi.dev/v1/posts/post_abc -H "Authorization: Bearer ugc_live_..."

You can cancel a post while its results are still scheduled. Results that already published can't be removed through the API. Delete them on the platform.

Validation

We validate the request before accepting it. A missing field or unknown option returns 400 invalid_request. An account ID that isn't yours returns 404 account_not_found. Not enough credits for all results returns 402 insufficient_credits. See errors. To schedule many posts over many accounts, use campaigns instead of a loop.

FAQ

How many accounts can one post target?

As many as you have connected. Each account and placement is a separate result and credit.

What time zone does scheduled_at use?

It is an ISO 8601 timestamp. Include Z for UTC or an explicit offset.

Can I edit a scheduled post?

Cancel it with DELETE /v1/posts/:id and create a new one.

Related