Posts endpoints
Create, list, update, and delete posts with platform/account overrides.
Posts use a three-layer override model: base caption/media →
platform_configurations → account_configurations. Status values are
draft, processing, scheduled, posted, and failed.
Endpoints
- GET
/api/v1/posts— List posts with platform/status filters. - POST
/api/v1/posts— Create a post (immediate, scheduled, or draft). - GET
/api/v1/posts/{id}— Fetch a single post. - PATCH
/api/v1/posts/{id}— Update any field or replace media/accounts. - DELETE
/api/v1/posts/{id}— Remove the post and attached media.
Shared payload fields
caption(string) — required on create; optional on update.social_accounts(string[]) — required on create; IDs returned from the Social Accounts API.scheduled_at(ISO string | null) — null = publish now; future timestamp = schedule; omit on PATCH to keep existing.is_draft(boolean | null) — true keeps it in draft; false + nullscheduled_atpublishes now.media(string[] | undefined) — IDs returned by Media API; replaces existing media when provided in PATCH.media_urls(string[] | undefined) — optional direct URLs; converted to media records on create/update. Replaces existing assets when provided.platform_configurations(object | null) — per-platform overrides; free-form JSON stored underapi.platform_configurations.account_configurations(object | null) — per-account overrides; free-form JSON stored underapi.account_configurations.processing_enabled(boolean | null) — defaults totrue; setfalseto skip internal video processing.
GET /api/v1/posts
Query filters:
offset,limit— see pagination rules.platform— array of platform IDs (twitter-x,instagram,linkedin,facebook-page,tiktok,youtube,bluesky,threads,pinterest).status— array ofposted|scheduled|processing|draft|failed.
Response:
{
"data": [
{
"id": "post-uuid",
"caption": "caption text",
"social_accounts": ["acc-1", "acc-2"],
"scheduled_at": "2025-12-01T10:00:00.000Z",
"is_draft": false,
"status": "scheduled",
"media": ["media-uuid"],
"platform_configurations": { /* platform overrides */ },
"account_configurations": { /* account overrides */ },
"processing_enabled": true
}
],
"meta": { "offset": 0, "limit": 10, "total": 12 }
}Example:
curl "https://<host>/api/v1/posts?status=scheduled&platform=linkedin" \
-H "Authorization: Bearer YOUR_SECRET_TOKEN"POST /api/v1/posts
Body (JSON):
{
"caption": "Launch post",
"social_accounts": ["acc-123"],
"scheduled_at": "2025-12-01T10:00:00Z",
"is_draft": false,
"media": ["media-uuid"],
"platform_configurations": {
"linkedin": { "caption": "LinkedIn copy" }
},
"account_configurations": null,
"processing_enabled": true
}Response body:
{ "data": { /* same shape as GET list item */ } }Errors: 400 for invalid account IDs or other business rules, 422 for schema
validation failures.
GET /api/v1/posts/{id}
Path: id (string). Returns the same DTO as the list endpoint.
PATCH /api/v1/posts/{id}
Any field is optional; omitting a field preserves its current value. Providing
media or media_urls replaces existing attachments. Changing social_accounts
recomputes the post targets (removed accounts are deleted; new ones inserted).
Status transitions:
- Set
is_draft=trueto move back to draft. - Set
scheduled_at=nullandis_draft=falseto publish immediately. - Provide a future
scheduled_atto queue for later.
DELETE /api/v1/posts/{id}
Deletes the post, detaches media assets, and deletes associated media records.
Returns { "success": true }.
Tips
- Always attach uploaded media IDs (
media) or URLs (media_urls) before publishing; pending media cannot be attached. statusin responses maps internal states:publishing/ready→processing,published→posted.- Use idempotency on your side (e.g., hash captions + accounts) to avoid duplicates when retrying after network errors.
