Content API

REST endpoints for the Content module — content items, categories, publishing integrations.

Endpoints

MethodPathPurpose
GET/api/contentList content items. Filters: status, content_type, category_id.
POST/api/contentCreate. Emits content.post.created.
GET/PATCH/DELETE/api/content/{id}CRUD.
POST/api/content/{id}/publishPublish to a connected platform via a publishing_integration. Emits content.post.published on success.
GET/api/content/scheduling-queueList scheduled items (status='scheduled' with a future publish_date).
GET/api/content/categoriesList categories.
POST/api/content/categoriesCreate.

Key entity shapes

Content item

{
  "id": "uuid",
  "title": "string",
  "slug": "string",
  "content_type": "article | blog_post | social_post | email | landing_page | ad_copy | video_script",
  "status": "draft | review | approved | scheduled | published | archived",
  "body": "string?",
  "excerpt": "string?",
  "publish_date": "iso-8601?",
  "platforms": ["wordpress", "medium", "..."],
  "tags": ["string"],
  "seo_title": "string?",
  "seo_description": "string?",
  "metadata": {}
}

Permissions

Seeded slugs: content.posts.read|create|update|delete|publish, content.approvals.read|update. There are no separate seeded slugs for content.items.* or content.categories.* — the endpoint table refers to "content items" but the underlying table

  • permission namespace is content_posts.

Events

  • content.post.created|updated|published|deleted
  • content.approval.updated

Scheduled publishing

Items with status='scheduled' and publish_date <= now() are picked up by the content-scheduler cron (*/5 * * * *) which calls the same publishing pipeline as the manual publish route. Status flips scheduled → publishing → published via compare-and-set so two ticks can't double-publish.

OpenAPI

Full schema at /api/openapi.json.