# Subscribr Customer API Reference Generated from `openapi/subscribr-v1.json`. Do not infer undocumented routes. - Base URL: `https://subscribr.com` - Authentication: `Authorization: Bearer ` - Contract: [OpenAPI 3.1.2](https://subscribr.com/openapi.json) - Generic `/api/v1/videos` is retired. YouTube research remains available through the Intel video operations. ## Channels ### `GET /api/v1/channels` **Operation ID:** `listChannels` **Purpose:** List Channels. **Abilities:** `channels:read` **Parameters** - `search` — query, optional - `per_page` — query, optional - `page` — query, optional **Response `200` example** ```json { "success": true, "data": [ { "id": 123, "yt_handle": "mkbhd", "details": { "title": "Marques Brownlee", "custom_url": "mkbhd", "channel_id": "UCBJycsmduvYEL83R_U4JriQ", "subscriber_count": 19000000, "video_count": 1650, "view_count": 4200000000, "description": "Channel description", "country": "US", "default_language": "en", "thumbnails": { "default": { "url": "https://i.ytimg.com/..." } } }, "scripts_count": 42 } ], "pagination": { "current_page": 1, "per_page": 20, "total": 1, "last_page": 1 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/channels/{channel}` **Operation ID:** `getChannel` **Purpose:** Get Channel. **Abilities:** `channels:read` **Parameters** - `channel` — path, required **Response `200` example** ```json { "success": true, "data": { "id": 123, "yt_handle": "mkbhd", "details": { "title": "Marques Brownlee", "custom_url": "mkbhd", "channel_id": "UCBJycsmduvYEL83R_U4JriQ", "subscriber_count": 19000000, "video_count": 1650, "view_count": 4200000000, "description": "Channel description", "default_language": "en", "country": "US", "thumbnails": { "default": { "url": "https://i.ytimg.com/..." } } }, "settings": { "language": "English", "audience": "Tech enthusiasts" }, "voice": { "id": 77, "name": "Default Voice", "instructions": "Voice instructions", "voice": "neutral" }, "scripts_count": 42, "scripts_idea_count": 4, "scripts_active_count": 38 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/channels/{channel}/competitors` **Operation ID:** `listChannelCompetitors` **Purpose:** List Channel Competitors. **Abilities:** `channels:read` **Parameters** - `channel` — path, required **Response `200` example** ```json { "success": true, "data": [] } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/competitors` **Operation ID:** `addChannelCompetitor` **Purpose:** Add Channel Competitor. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "identifier": "https://www.youtube.com/@competitor" } ``` **Response `201` example** ```json { "success": true, "data": { "channel_id": 1, "competitor": { "channel_id": "UC123", "handle": "competitor", "title": "Competitor" } } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `DELETE /api/v1/channels/{channel}/competitors/{competitor}` **Operation ID:** `deleteChannelCompetitor` **Purpose:** Delete Channel Competitor. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required - `competitor` — path, required **Response `200` example** ```json { "success": true, "message": "Competitor removed." } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Ideas ### `GET /api/v1/channels/{channel}/ideas` **Operation ID:** `listChannelIdeas` **Purpose:** List Channel Ideas. **Abilities:** `scripts:read` **Parameters** - `channel` — path, required - `status` — query, optional - `source_type` — query, optional - `search` — query, optional - `per_page` — query, optional - `page` — query, optional **Response `200` example** ```json { "success": true, "data": [ { "id": 456, "channel_id": 123, "title": "Why Apple's AI Changes Everything", "topic": "Analysis of Apple Intelligence", "angle": "Reveal the hidden implication...", "suggested_length": 1200, "suggested_template_id": 22, "status": "new", "script_id": null, "source_type": "user_added", "thumbnail_concept": "Split-screen before/after with bold headline", "outlier_score": null, "notes": null } ], "pagination": { "current_page": 1, "per_page": 20, "total": 1, "last_page": 1 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/ideas` **Operation ID:** `createChannelIdea` **Purpose:** Create Channel Idea. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "title": "Why Apple's AI Changes Everything", "topic": "Analysis of Apple Intelligence", "angle": "Reveal the hidden implication that most reviews miss.", "suggested_length": 1200, "suggested_template_id": 22, "thumbnail_concept": "Split-screen before/after with bold headline", "notes": "Focus on practical consequences." } ``` **Response `201` example** ```json { "success": true, "data": { "id": 456, "channel_id": 123, "title": "Why Apple's AI Changes Everything", "topic": "Analysis of Apple Intelligence", "angle": "Reveal the hidden implication that most reviews miss.", "suggested_length": 1200, "suggested_template_id": 22, "status": "new", "script_id": null, "source_type": "user_added", "thumbnail_concept": "Split-screen before/after with bold headline", "outlier_score": null, "notes": null } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/ideas/generate` **Operation ID:** `generateChannelIdeas` **Purpose:** Generate Channel Ideas. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "count": 10 } ``` **Response `202` example** ```json { "success": true, "message": "Idea generation started.", "data": { "channel_id": 123, "count": 10 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/ideas/generate-from-channel` **Operation ID:** `generateIdeasFromChannel` **Purpose:** Generate Ideas From Channel. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "channel_handle": "@mkbhd", "count": 10 } ``` **Response `202` example** ```json { "success": true, "message": "Idea generation from channel started.", "data": { "channel_id": 123, "source_channel_title": "Marques Brownlee", "count": 10 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/ideas/generate-from-video` **Operation ID:** `generateIdeasFromVideo` **Purpose:** Generate Ideas From Video. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ", "count": 10 } ``` **Response `202` example** ```json { "success": true, "message": "Idea generation from video started.", "data": { "channel_id": 123, "count": 10 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/ideas/{idea}` **Operation ID:** `getIdea` **Purpose:** Get Idea. **Abilities:** `scripts:read` **Parameters** - `idea` — path, required **Response `200` example** ```json { "success": true, "data": { "id": 456, "channel_id": 123, "title": "Why Apple's AI Changes Everything", "topic": "Analysis of Apple Intelligence", "angle": "Reveal the hidden implication...", "suggested_length": 1200, "suggested_template_id": 22, "status": "new", "script_id": null, "source_type": "user_added", "thumbnail_concept": "Split-screen before/after", "outlier_score": null, "notes": null } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/ideas/{idea}/change-topic` **Operation ID:** `changeIdeaTopic` **Purpose:** Change Idea Topic. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `idea` — path, required **Request example** ```json { "topic": "Instead of productivity apps, apply this to morning routines" } ``` **Response `202` example** ```json { "success": true, "message": "Topic change started.", "data": { "idea_id": 456 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/ideas/{idea}/write` **Operation ID:** `writeIdea` **Purpose:** Write Idea. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `idea` — path, required **Response `201` example** ```json { "success": true, "data": { "script_id": 789, "script_number": 12, "thread_id": 456, "canvas_url": "https://subscribr.ai/chat/my-channel-thread/canvas/789" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Intel ### `GET /api/v1/intel/bookmarks` **Operation ID:** `listIntelBookmarks` **Purpose:** List Intel Bookmarks. **Abilities:** `intel:read` **Parameters** - `page` — query, optional - `bookmark` — query, required **Response `200` example** ```json { "success": true, "data": [], "pagination": { "current_page": 1, "per_page": 50, "total": 0, "last_page": 1 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/intel/bookmarks` **Operation ID:** `createIntelBookmark` **Purpose:** Create Intel Bookmark. **Abilities:** `intel:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `page` — query, optional - `bookmark` — query, required **Request example** ```json { "type": "channel", "external_id": "UCBJycsmduvYEL83R_U4JriQ", "title": "Competitor: MKBHD", "url": "https://youtube.com/@mkbhd", "notes": "Strong format", "tags": [ "competitor" ] } ``` **Response `201` example** ```json { "success": true, "data": { "id": 1, "type": "channel", "external_id": "UCBJycsmduvYEL83R_U4JriQ", "title": "Competitor: MKBHD", "url": "https://youtube.com/@mkbhd", "notes": "Strong format", "tags": [ "competitor" ] } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `DELETE /api/v1/intel/bookmarks/{bookmark}` **Operation ID:** `deleteIntelBookmark` **Purpose:** Delete Intel Bookmark. **Abilities:** `intel:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `bookmark` — path, required **Response `200` example** ```json { "success": true, "message": "Bookmark deleted successfully" } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/intel/channels/lookup` **Operation ID:** `lookupIntelChannel` **Purpose:** Lookup Intel Channel. **Abilities:** `intel:read` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Request example** ```json { "identifiers": [ "@mkbhd", "UCBJycsmduvYEL83R_U4JriQ" ] } ``` **Response `200` example** ```json { "success": true, "data": { "channels": [ { "channel_id": "UCBJycsmduvYEL83R_U4JriQ", "handle": "mkbhd", "title": "Marques Brownlee", "description": "Channel description (truncated to 500 chars)", "thumbnails": { "default": { "url": "https://i.ytimg.com/..." } }, "subscriber_count": 19000000, "video_count": 1650, "view_count": 4200000000, "published_at": "2008-01-20T00:00:00Z", "country": "US" } ], "errors": [] } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/intel/channels/search` **Operation ID:** `searchIntelChannels` **Purpose:** Search Intel Channels. **Abilities:** `intel:read` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Request example** ```json { "query": "tech reviews", "limit": 10 } ``` **Response `200` example** ```json { "success": true, "data": { "channels": [ { "channel_id": "UCBJycsmduvYEL83R_U4JriQ", "handle": "mkbhd", "title": "Marques Brownlee", "description": "Channel description (truncated to 500 chars)", "thumbnails": { "default": { "url": "https://i.ytimg.com/..." } }, "published_at": "2008-01-20T00:00:00Z", "subscriber_count": 19000000, "video_count": 1650, "view_count": 4200000000, "country": "US" } ], "query": "tech reviews", "total_results": 1, "message": "Channels found matching your criteria." } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/intel/videos/lookup` **Operation ID:** `lookupIntelVideo` **Purpose:** Lookup Intel Video. **Abilities:** `intel:read` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Request example** ```json { "identifiers": [ "dQw4w9WgXcQ", "https://youtube.com/watch?v=abc123" ] } ``` **Response `200` example** ```json { "success": true, "data": { "videos": [ { "video_id": "dQw4w9WgXcQ", "channel": { "channel_id": "UCuAXFkgsw1L7xaCfnd5JJOw", "handle": "RickAstleyVEVO", "title": "Rick Astley" }, "title": "Video Title", "description": "Video description", "published_at": "2009-10-25T06:57:33Z", "thumbnail_url": "https://i.ytimg.com/...", "duration": "PT3M33S", "view_count": 1000000, "like_count": 50000, "comment_count": 10000, "outlier_score": 1.25, "format": "Music", "topic": "Pop", "angle": "Nostalgia", "goals": "Entertainment" } ], "errors": [] } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/intel/videos/search` **Operation ID:** `searchIntelVideos` **Purpose:** Search Intel Videos. **Abilities:** `intel:read` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Request example** ```json { "query": "iPhone 15 review", "limit": 20 } ``` **Response `200` example** ```json { "success": true, "data": { "videos": [ { "video_id": "abc123", "channel": { "channel_id": "UCBJycsmduvYEL83R_U4JriQ", "handle": "mkbhd", "title": "Marques Brownlee" }, "title": "iPhone 15 Review", "description": "Description (truncated to 300 chars)...", "published_at": "2026-01-01T00:00:00Z", "thumbnail_url": "https://i.ytimg.com/...", "view_count": 500000, "like_count": 15000, "comment_count": 1200, "duration": "PT12M", "format": "Review", "topic": "Smartphones", "angle": "Hands-on", "goals": "Inform", "outlier_score": 1.12 } ], "query": "iPhone 15 review", "total_results": 1, "message": "Videos found matching your criteria." } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Projects ### `GET /api/v1/projects` **Operation ID:** `listProjects` **Purpose:** List Projects. **Abilities:** `projects:read` **Parameters** - `Cursor` (shared header parameter) - `channel_ids[]` — query, optional - `search` — query, optional - `include_archived` — query, optional - `limit` — query, optional - `expand` — query, optional **Response `200` example** ```json { "data": [], "meta": { "next_cursor": null } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/projects` **Operation ID:** `createProject` **Purpose:** Create Project. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `optional`; retry `same-key`. **Parameters** - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "channel_id": 1, "source": "idea", "title": "New idea", "stage": "new" } ``` **Response `201` example** ```json { "data": { "id": "project:v1:idea:1", "source": "idea", "title": "New idea", "revision": "revision" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/projects/{project}` **Operation ID:** `getProject` **Purpose:** Get Project. **Abilities:** `projects:read` **Parameters** - `project` — path, required - `expand` — query, optional **Response `200` example** ```json { "data": { "id": "project:v1:idea:1", "source": "idea", "title": "Idea", "revision": "revision" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `PATCH /api/v1/projects/{project}` **Operation ID:** `updateProject` **Purpose:** Update Project. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "title": "Updated title" } ``` **Response `200` example** ```json { "data": { "id": "project:v1:idea:1", "source": "idea", "title": "Updated title", "revision": "revision-2" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `POST /api/v1/projects/{project}/move` **Operation ID:** `moveProject` **Purpose:** Move Project. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "stage": "considering" } ``` **Response `200` example** ```json { "data": { "id": "project:v1:idea:1", "source": "idea", "title": "Idea", "revision": "revision-2" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `POST /api/v1/projects/{project}/promote` **Operation ID:** `promoteProject` **Purpose:** Promote idea Project. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "stage": "scripting" } ``` **Response `200` example** ```json { "data": { "id": "project:v1:script:1", "source": "script", "title": "Idea", "revision": "revision-2" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `POST /api/v1/projects/{project}/archive` **Operation ID:** `archiveProject` **Purpose:** Archive Project. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Response `200` example** ```json { "data": { "id": "project:v1:idea:1", "source": "idea", "title": "Idea", "revision": "revision-2" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `POST /api/v1/projects/{project}/restore` **Operation ID:** `restoreProject` **Purpose:** Restore Project. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Response `200` example** ```json { "data": { "id": "project:v1:idea:1", "source": "idea", "title": "Idea", "revision": "revision-2" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `GET /api/v1/projects/{project}/comments` **Operation ID:** `listProjectComments` **Purpose:** List Project comments. **Abilities:** `projects:read` **Parameters** - `project` — path, required **Response `200` example** ```json { "data": [], "meta": { "truncated": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/projects/{project}/comments` **Operation ID:** `createProjectComment` **Purpose:** Create Project comment. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `optional`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "body": "Ready for review.", "mentioned_user_ids": [] } ``` **Response `201` example** ```json { "data": { "id": 1, "body": "Ready for review.", "author": { "id": 1, "name": "Creator" }, "mentioned_user_ids": [], "edited_at": null, "created_at": "2026-07-22T12:00:00+00:00" }, "meta": { "no_op": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/projects/{project}/activity` **Operation ID:** `listProjectActivity` **Purpose:** List Project activity. **Abilities:** `projects:read` **Parameters** - `project` — path, required **Response `200` example** ```json { "data": [], "meta": { "truncated": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/projects/{project}/attachments` **Operation ID:** `listProjectAttachments` **Purpose:** List Project attachment metadata. **Abilities:** `projects:read` **Parameters** - `project` — path, required **Response `200` example** ```json { "data": [], "meta": { "truncated": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/tasks` **Operation ID:** `listProjectTasks` **Purpose:** List assigned Project tasks. **Abilities:** `projects:read` **Parameters** - `Cursor` (shared header parameter) - `limit` — query, optional - `overdue` — query, optional **Response `200` example** ```json { "data": [], "meta": { "next_cursor": null } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/project-notifications` **Operation ID:** `listProjectNotifications` **Purpose:** List Project notifications. **Abilities:** `notifications:read` **Parameters** - `Cursor` (shared header parameter) - `limit` — query, optional - `unread` — query, optional **Response `200` example** ```json { "data": [], "meta": { "next_cursor": null } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/project-notifications/{notification}/read` **Operation ID:** `readProjectNotification` **Purpose:** Mark one Project notification read. **Abilities:** `notifications:write` **Write safety:** idempotency `required`; concurrency `optional`; retry `same-key`. **Parameters** - `notification` — path, required - `IdempotencyKey` (shared header parameter) **Response `200` example** ```json { "data": { "id": "00000000-0000-4000-8000-000000000001", "type": "kanban_script_status_changed", "project_id": "project:v1:script:1", "target_available": true, "message": "Moved project", "actor": null, "read_at": "2026-07-22T12:00:00+00:00", "created_at": "2026-07-22T11:00:00+00:00" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/project-notifications/read-all` **Operation ID:** `readAllProjectNotifications` **Purpose:** Mark all Project notifications read. **Abilities:** `notifications:write` **Write safety:** idempotency `required`; concurrency `optional`; retry `same-key`. **Parameters** - `IdempotencyKey` (shared header parameter) **Response `200` example** ```json { "data": { "marked_read": 2 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/projects/{project}/production` **Operation ID:** `getProjectProduction` **Purpose:** Get Project production metadata. **Abilities:** `projects:read` **Parameters** - `project` — path, required **Response `200` example** ```json { "data": { "project_id": "project:v1:script:1", "stage": "upload", "thumbnail": { "text": null, "winner_selected": false, "review_status": null, "review_notes": null, "reviewed_at": null }, "upload": { "description": null, "tags": [], "visibility": "public", "made_for_kids": false, "status": null, "publish_at": null, "all_required_checked": true }, "checklist": [], "checklist_total": 0, "checklist_truncated": false }, "meta": { "revision": "project-r1-example", "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `PATCH /api/v1/projects/{project}/production` **Operation ID:** `updateProjectProduction` **Purpose:** Update Project production metadata. **Abilities:** `projects:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `project` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "description": "Ready to upload.", "tags": [ "tutorial" ], "visibility": "unlisted" } ``` **Response `200` example** ```json { "data": { "project_id": "project:v1:script:1", "stage": "upload", "thumbnail": { "text": null, "winner_selected": false, "review_status": null, "review_notes": null, "reviewed_at": null }, "upload": { "description": "Ready to upload.", "tags": [ "tutorial" ], "visibility": "unlisted", "made_for_kids": false, "status": null, "publish_at": null, "all_required_checked": true }, "checklist": [], "checklist_total": 0, "checklist_truncated": false }, "meta": { "revision": "project-r1-example", "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ## Scripts ### `GET /api/v1/channels/{channel}/scripts` **Operation ID:** `listChannelScripts` **Purpose:** List Channel Scripts. **Abilities:** `scripts:read` **Parameters** - `channel` — path, required - `status` — query, optional - `format` — query, optional - `search` — query, optional - `per_page` — query, optional - `page` — query, optional **Response `200` example** ```json { "success": true, "data": [ { "id": 789, "channel_id": 123, "script_number": 12, "title": "Why Apple's AI Changes Everything", "topic": "Break down the key changes...", "angle": "Explain the hidden implication most reviews miss", "length": 1200, "status": "active", "format": "Tutorial", "language": "English", "voice": "neutral", "template_id": 22, "production_status": "scripting", "thread_id": 456, "canvas_url": "https://subscribr.ai/chat/my-channel-thread/canvas/789", "has_outline": true, "has_script": false } ], "pagination": { "current_page": 1, "per_page": 20, "total": 1, "last_page": 1 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/scripts` **Operation ID:** `createChannelScript` **Purpose:** Create Channel Script. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "title": "Why Apple's AI Changes Everything", "topic": "Break down the key changes in Apple Intelligence and what they mean.", "length": 1200, "angle": "Explain the hidden implication most reviews miss", "voice_id": 55, "voice": "neutral", "language": "English", "template_id": 22, "research_urls": [ "https://example.com/source-1" ], "research_texts": [ "Key bullet points" ], "prompt": "Custom starting prompt" } ``` **Response `201` example** ```json { "success": true, "data": { "script_id": 789, "script_number": 12, "thread_id": 456, "status": "active", "canvas_url": "https://subscribr.ai/chat/my-channel-thread/canvas/789" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/scripts/{script}` **Operation ID:** `getScript` **Purpose:** Get Script. **Abilities:** `scripts:read` **Parameters** - `script` — path, required **Response `200` example** ```json { "success": true, "data": { "id": 789, "channel_id": 123, "script_number": 12, "title": "Why Apple's AI Changes Everything", "topic": "Break down the key changes...", "angle": "Explain the hidden implication most reviews miss", "length": 1200, "format": "Tutorial", "language": "English", "voice": "neutral", "template_id": 22, "status": "active", "production_status": "scripting", "thread_id": 456, "canvas_url": "https://subscribr.ai/chat/my-channel-thread/canvas/789", "has_outline": true, "has_script": false, "notes": "Notes for collaborators", "hook": "Open with a surprising fact", "thumbnail": "Apple AI Shock" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/scripts/{script}/agent/generate` **Operation ID:** `startScriptAgentRun` **Purpose:** Start Script Agent Run. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `script` — path, required **Request example** ```json { "model": "minimax_m27", "research": "deep_research", "visual_cues": "on" } ``` **Response `202` example** ```json { "run_id": 42, "status": "queued", "research": "auto", "visual_cues": "off", "model": "kimi_k26", "resolved_model": "kimi-k2.6", "poll_url": "https://subscribr.ai/api/v1/scripts/789/agent/runs/42", "cancel_url": "https://subscribr.ai/api/v1/scripts/789/agent/runs/42/cancel", "message": "Script agent run queued. Poll the poll_url for status updates." } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/scripts/{script}/agent/runs/{run}` **Operation ID:** `getScriptAgentRun` **Purpose:** Get Script Agent Run. **Abilities:** `scripts:read` **Parameters** - `script` — path, required - `run` — path, required **Response `200` example** ```json { "success": true, "data": { "run_id": 42, "status": "running", "current_step": "generating_script", "current_step_label": "Writing script", "elapsed_seconds": 94, "executor": "claude_sdk", "auth_path": "byok" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/scripts/{script}/agent/runs/{run}/cancel` **Operation ID:** `cancelScriptAgentRun` **Purpose:** Cancel Script Agent Run. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `script` — path, required - `run` — path, required **Response `200` example** ```json { "cancelled": true, "run_id": 42, "status": "cancelled", "refunded": true, "message": "Run cancelled. Credits were refunded." } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/scripts/{script}/content` **Operation ID:** `getScriptContent` **Purpose:** Get Script Content. **Abilities:** `scripts:read` **Parameters** - `script` — path, required **Response `200` example** ```json { "success": true, "data": { "script_id": 789, "outline": "# Outline\\n...", "script": "# Script\\n...", "outline_version": 3, "content_version": 7 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/scripts/{script}/export` **Operation ID:** `exportScript` **Purpose:** Export Script. **Abilities:** `scripts:read` **Parameters** - `script` — path, required - `format` — query, required - `include_headings` — query, optional **Response `200` example** ```json { "success": true, "data": { "script_id": 789, "title": "Why Apple's AI Changes Everything", "format": "markdown", "content": "# Script\\n...", "include_headings": true } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/scripts/{script}/generate/poll` **Operation ID:** `pollScriptGeneration` **Purpose:** Poll Script Generation. **Abilities:** `scripts:read` **Parameters** - `script` — path, required - `run_id` — query, required **Response `200` example** ```json { "success": true, "data": { "run_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "status": "completed", "content_type": "script", "outline": "# Outline\n\n## Section 1\n...", "script": "# Script\n\nOpening hook...\n" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/scripts/{script}/outline/generate` **Operation ID:** `generateScriptOutline` **Purpose:** Generate Script Outline. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `script` — path, required **Response `202` example** ```json { "success": true, "data": { "run_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "status": "queued" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/scripts/{script}/script/generate` **Operation ID:** `generateScript` **Purpose:** Generate Script. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `script` — path, required **Response `202` example** ```json { "success": true, "data": { "run_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "status": "queued" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/scripts/{script}/script/humanize` **Operation ID:** `humanizeScript` **Purpose:** Humanize Script. **Abilities:** `scripts:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `script` — path, required **Response `202` example** ```json { "success": true, "data": { "run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "queued" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Team ### `GET /api/v1/team` **Operation ID:** `getTeam` **Purpose:** Get Team. **Abilities:** authenticated credential **Response `200` example** ```json { "team": { "id": 456, "name": "My Content Team", "user_role": "admin", "owner": { "id": 123, "name": "John Doe" }, "subscription": { "plan": "Creator", "status": "active", "trial_ends_at": null, "is_paused": false } } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/team/credits` **Operation ID:** `getTeamCredits` **Purpose:** Get Team Credits. **Abilities:** authenticated credential **Response `200` example** ```json { "credits": { "current_credits": 850, "plan_credits": 1000, "credits_used_this_period": 150, "credits_remaining": 850, "credits_expire_at": "2026-02-28T00:00:00Z", "next_credit_refresh": "2026-03-01T00:00:00Z" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/team/tokens` **Operation ID:** `listApiTokens` **Purpose:** List Api Tokens. **Abilities:** `tokens:manage` **Response `200` example** ```json { "tokens": [ { "id": 123, "name": "Zapier Integration", "abilities": [ "intel:read", "scripts:read" ], "last_used_at": "2026-02-01T18:22:00Z" } ] } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/team/tokens` **Operation ID:** `createApiToken` **Purpose:** Create Api Token. **Abilities:** `tokens:manage` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Request example** ```json { "name": "Automation Token", "abilities": [ "intel:read", "scripts:read", "channels:read" ] } ``` **Response `201` example** ```json { "token": { "id": 456, "name": "Automation Token", "abilities": [ "intel:read", "scripts:read", "channels:read" ], "token": "plain-text-token-value" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `DELETE /api/v1/team/tokens/{token}` **Operation ID:** `deleteApiToken` **Purpose:** Delete Api Token. **Abilities:** `tokens:manage` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `token` — path, required **Response `200` example** ```json { "message": "Token deleted successfully" } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Templates ### `GET /api/v1/channels/{channel}/templates` **Operation ID:** `listChannelTemplates` **Purpose:** List built-in and custom Channel templates. **Abilities:** `templates:read` **Parameters** - `channel` — path, required - `include_archived` — query, optional **Response `200` example** ```json { "data": [], "meta": { "default_template_id": null, "system_count": 20, "custom_count": 0, "custom_truncated": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/templates` **Operation ID:** `createTemplate` **Purpose:** Create a custom Channel template. **Abilities:** `templates:write` **Write safety:** idempotency `required`; concurrency `unsupported`; retry `same-key`. **Parameters** - `channel` — path, required - `IdempotencyKey` (shared header parameter) **Request example** ```json { "name": "My explainer", "description": "A concise teaching format.", "prompt": "Write a clear, structured explainer with a compelling opening, concrete examples, and a concise conclusion for the target audience." } ``` **Response `201` example** ```json { "data": { "id": 22, "kind": "custom", "key": null, "name": "My explainer", "slug": "my-explainer", "category": "custom", "description": "A concise teaching format.", "prompt": "Write a clear structured explainer with a compelling opening and concrete examples for the intended audience.", "is_default": false, "archived": false, "mutable": true, "revision": "template-r1-example", "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:00:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `GET /api/v1/channels/{channel}/templates/{template}` **Operation ID:** `getTemplate` **Purpose:** Get a custom Channel template. **Abilities:** `templates:read` **Parameters** - `channel` — path, required - `template` — path, required **Response `200` example** ```json { "data": { "id": 22, "kind": "custom", "key": null, "name": "My explainer", "slug": "my-explainer", "category": "custom", "description": null, "prompt": "Write a clear structured explainer with a compelling opening and concrete examples for the intended audience.", "is_default": false, "archived": false, "mutable": true, "revision": "template-r1-example", "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:00:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `PATCH /api/v1/channels/{channel}/templates/{template}` **Operation ID:** `updateTemplate` **Purpose:** Update a custom Channel template. **Abilities:** `templates:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `channel` — path, required - `template` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Request example** ```json { "name": "My revised explainer" } ``` **Response `200` example** ```json { "data": { "id": 22, "kind": "custom", "key": null, "name": "My revised explainer", "slug": "my-revised-explainer", "category": "custom", "description": null, "prompt": "Write a clear structured explainer with a compelling opening and concrete examples for the intended audience.", "is_default": false, "archived": false, "mutable": true, "revision": "template-r1-updated", "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:05:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/templates/{template}/archive` **Operation ID:** `archiveTemplate` **Purpose:** Archive a custom Channel template. **Abilities:** `templates:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `channel` — path, required - `template` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Response `200` example** ```json { "data": { "id": 22, "kind": "custom", "key": null, "name": "My explainer", "slug": "my-explainer", "category": "custom", "description": null, "prompt": "Write a clear structured explainer with a compelling opening and concrete examples for the intended audience.", "is_default": false, "archived": true, "mutable": true, "revision": "template-r1-archived", "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:05:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/templates/{template}/restore` **Operation ID:** `restoreTemplate` **Purpose:** Restore an archived custom Channel template. **Abilities:** `templates:write` **Write safety:** idempotency `required`; concurrency `required`; retry `same-key`. **Parameters** - `channel` — path, required - `template` — path, required - `IdempotencyKey` (shared header parameter) - `IfMatch` (shared header parameter) **Response `200` example** ```json { "data": { "id": 22, "kind": "custom", "key": null, "name": "My explainer", "slug": "my-explainer", "category": "custom", "description": null, "prompt": "Write a clear structured explainer with a compelling opening and concrete examples for the intended audience.", "is_default": false, "archived": false, "mutable": true, "revision": "template-r1-restored", "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:10:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ## Thumbnails ### `GET /api/v1/channels/{channel}/thumbnails/generations` **Operation ID:** `listThumbnailGenerations` **Purpose:** List Thumbnail Generations. **Abilities:** `scripts:read`, `thumbnails:read` **Parameters** - `channel` — path, required - `source_type` — query, optional - `page` — query, optional **Response `200` example** ```json { "success": true, "data": [ { "run_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "status": "completed", "source_type": "api_generate", "idea_id": 42, "output_urls": [ "https://subscribr.ai/storage/thumbnails/9b1deb4d_v1.png" ], "created_at": "2026-02-27T10:30:00Z" } ], "meta": { "current_page": 1, "last_page": 3, "per_page": 15, "total": 42 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/thumbnails/generations` **Operation ID:** `createThumbnailGeneration` **Purpose:** Create Thumbnail Generation. **Abilities:** `scripts:write`, `thumbnails:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `channel` — path, required **Request example** ```json { "idea_id": 42, "num_variations": 3, "callback_url": "https://partner.example.com/subscribr/thumbnail-callback", "callback_secret": "whsec_thumbnail_partner_secret" } ``` **Response `202` example** ```json { "success": true, "data": { "run_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "run_ids": [ "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" ], "status": "queued" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/channels/{channel}/thumbnails/generations/{runId}` **Operation ID:** `getThumbnailGeneration` **Purpose:** Get Thumbnail Generation. **Abilities:** `scripts:read`, `thumbnails:read` **Parameters** - `channel` — path, required - `runId` — path, required **Response `200` example** ```json { "success": true, "data": { "run_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "status": "completed", "idea_id": null, "output_urls": [ "https://subscribr.ai/storage/thumbnails/9b1deb4d_v1.png", "https://subscribr.ai/storage/thumbnails/9b1deb4d_v2.png" ], "created_at": "2026-02-27T10:30:00Z", "updated_at": "2026-02-27T10:30:45Z" } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/team/thumbnails/usage` **Operation ID:** `getThumbnailUsage` **Purpose:** Get Thumbnail Usage. **Abilities:** `scripts:read`, `thumbnails:read` **Response `200` example** ```json { "success": true, "data": { "eligible": true, "free_pool": { "limit": 5, "used": 2, "reserved": 1, "remaining": 2, "next_reset": "2026-04-01" }, "addon_pool": { "limit": 50, "used": 10, "reserved": 0, "remaining": 40, "next_reset": "2026-04-15" }, "pack_pool": { "limit": 100, "used": 5, "reserved": 0, "remaining": 95, "next_reset": null }, "total_remaining": 137 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Voices ### `GET /api/v1/channels/{channel}/voices` **Operation ID:** `listChannelVoices` **Purpose:** List Channel Voices. **Abilities:** `voices:read` **Parameters** - `channel` — path, required **Response `200` example** ```json { "data": [ { "id": "2d3b57bd-916d-4ce2-a85b-a65dc8fc97b4", "name": "Default Voice", "framework_version": 2, "schema_version": 2, "checksum": "9b2d", "revision": "voice-r1-example", "writable": true, "profile": { "writing_style_analysis": [] }, "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:00:00Z" } ], "meta": { "default_voice_id": "2d3b57bd-916d-4ce2-a85b-a65dc8fc97b4", "truncated": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/voices/validate` **Operation ID:** `validateVoiceProfile` **Purpose:** Validate and canonicalize a complete Voice Profile v2 without mutating data. **Abilities:** `voices:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `revalidate`. **Parameters** - `channel` — path, required **Request example** ```json { "intent": "create", "name": "Practical guide", "profile": { "writing_style_analysis": { "speaker_archetype": { "label": "Practical guide", "description": "Calm expert.", "axes": { "age_vibe": "experienced peer", "profession_archetype": "strategist", "temperament": "calm", "authority_posture": "confident" } }, "stance_and_relationship": { "narrative_person": "second person", "intimacy_distance": "trusted peer", "certainty_level": "Names uncertainty.", "audience_model": "Experienced creators." }, "delivery_recipe": { "cadence": "Short claims.", "energy": "Warm.", "pacing_and_emphasis": [ "Front-load the point." ] }, "rhetorical_toolkit": { "hook_patterns": [ "Open with a misconception." ], "transitions": [ "Here is the useful part." ], "explanation_patterns": [ "Make it concrete." ], "storytelling_patterns": [ "Start at the decision." ], "cta_patterns": [], "analogy_and_evidence": "Use one analogy.", "humor_and_empathy": "Keep humor light." }, "diction_and_syntax": { "vocabulary_level": "conversational", "word_complexity": "Prefer short words.", "sentence_shape": "Mix short and medium sentences.", "preferred_constructions": [ "Here is the tradeoff." ], "avoid": [ "Empty jargon." ] }, "phrase_kit": { "uses": [], "avoid": [], "replacements": [] }, "jargon_policy": { "allow": [], "explain_with": [ "a tiny example" ] }, "formatting_directives": [ "Use short paragraphs." ], "do_dont": { "do": [ "Lead with value." ], "dont": [ "Invent facts." ], "never_does": [ "Hide uncertainty." ] }, "locale_and_dialect": "Natural American English.", "thinking_style": "Test conclusions against evidence.", "spoken_patterns": { "common_phrases": [], "starter_words": [], "transition_phrases": [] }, "rewriter_directives": [ "Address the listener as you." ], "adherence_checklist": [ "No invented specifics." ], "lexical_glossary": [], "example_paragraph": "Start with the decision your viewer needs to make. Then give them only the evidence that changes it.", "style_examples": [ "Start with the decision your viewer needs to make. Then build the explanation around the evidence that changes that decision." ] } } } ``` **Response `200` example** ```json { "data": { "receipt": "vr2.current.opaque-token", "expires_at": "2026-07-22T12:10:00Z", "voice_id": "2d3b57bd-916d-4ce2-a85b-a65dc8fc97b4", "schema_version": 2, "checksum": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "expected_revision": null, "normalized": { "writing_style_analysis": { "speaker_archetype": { "label": "Practical guide", "description": "Calm expert.", "axes": { "age_vibe": "experienced peer", "profession_archetype": "strategist", "temperament": "calm", "authority_posture": "confident" } }, "stance_and_relationship": { "narrative_person": "second person", "intimacy_distance": "trusted peer", "certainty_level": "Names uncertainty.", "audience_model": "Experienced creators." }, "delivery_recipe": { "cadence": "Short claims.", "energy": "Warm.", "pacing_and_emphasis": [ "Front-load the point." ] }, "rhetorical_toolkit": { "hook_patterns": [ "Open with a misconception." ], "transitions": [ "Here is the useful part." ], "explanation_patterns": [ "Make it concrete." ], "storytelling_patterns": [ "Start at the decision." ], "cta_patterns": [], "analogy_and_evidence": "Use one analogy.", "humor_and_empathy": "Keep humor light." }, "diction_and_syntax": { "vocabulary_level": "conversational", "word_complexity": "Prefer short words.", "sentence_shape": "Mix short and medium sentences.", "preferred_constructions": [ "Here is the tradeoff." ], "avoid": [ "Empty jargon." ] }, "phrase_kit": { "uses": [], "avoid": [], "replacements": [] }, "jargon_policy": { "allow": [], "explain_with": [ "a tiny example" ] }, "formatting_directives": [ "Use short paragraphs." ], "do_dont": { "do": [ "Lead with value." ], "dont": [ "Invent facts." ], "never_does": [ "Hide uncertainty." ] }, "locale_and_dialect": "Natural American English.", "thinking_style": "Test conclusions against evidence.", "spoken_patterns": { "common_phrases": [], "starter_words": [], "transition_phrases": [] }, "rewriter_directives": [ "Address the listener as you." ], "adherence_checklist": [ "No invented specifics." ], "lexical_glossary": [], "example_paragraph": "Start with the decision your viewer needs to make. Then give them only the evidence that changes it.", "style_examples": [ "Start with the decision your viewer needs to make. Then build the explanation around the evidence that changes that decision." ] } }, "diff": [ "voice.created" ], "warnings": [] } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/channels/{channel}/voices/commit` **Operation ID:** `commitVoiceProfile` **Purpose:** Commit an exactly validated Voice Profile receipt. **Abilities:** `voices:write` **Write safety:** idempotency `required`; concurrency `optional`; retry `same-key`. **Parameters** - `channel` — path, required - `Idempotency-Key` — header, required - `If-Match` — header, optional **Request example** ```json { "receipt": "vr2.current.opaque-token", "profile": { "writing_style_analysis": { "speaker_archetype": { "label": "Practical guide", "description": "Calm expert.", "axes": { "age_vibe": "experienced peer", "profession_archetype": "strategist", "temperament": "calm", "authority_posture": "confident" } }, "stance_and_relationship": { "narrative_person": "second person", "intimacy_distance": "trusted peer", "certainty_level": "Names uncertainty.", "audience_model": "Experienced creators." }, "delivery_recipe": { "cadence": "Short claims.", "energy": "Warm.", "pacing_and_emphasis": [ "Front-load the point." ] }, "rhetorical_toolkit": { "hook_patterns": [ "Open with a misconception." ], "transitions": [ "Here is the useful part." ], "explanation_patterns": [ "Make it concrete." ], "storytelling_patterns": [ "Start at the decision." ], "cta_patterns": [], "analogy_and_evidence": "Use one analogy.", "humor_and_empathy": "Keep humor light." }, "diction_and_syntax": { "vocabulary_level": "conversational", "word_complexity": "Prefer short words.", "sentence_shape": "Mix short and medium sentences.", "preferred_constructions": [ "Here is the tradeoff." ], "avoid": [ "Empty jargon." ] }, "phrase_kit": { "uses": [], "avoid": [], "replacements": [] }, "jargon_policy": { "allow": [], "explain_with": [ "a tiny example" ] }, "formatting_directives": [ "Use short paragraphs." ], "do_dont": { "do": [ "Lead with value." ], "dont": [ "Invent facts." ], "never_does": [ "Hide uncertainty." ] }, "locale_and_dialect": "Natural American English.", "thinking_style": "Test conclusions against evidence.", "spoken_patterns": { "common_phrases": [], "starter_words": [], "transition_phrases": [] }, "rewriter_directives": [ "Address the listener as you." ], "adherence_checklist": [ "No invented specifics." ], "lexical_glossary": [], "example_paragraph": "Start with the decision your viewer needs to make. Then give them only the evidence that changes it.", "style_examples": [ "Start with the decision your viewer needs to make. Then build the explanation around the evidence that changes that decision." ] } } } ``` **Response `200` example** ```json { "data": { "id": "2d3b57bd-916d-4ce2-a85b-a65dc8fc97b4", "name": "Practical guide", "framework_version": 2, "schema_version": 2, "checksum": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "revision": "voice-r1-example", "writable": true, "profile": { "writing_style_analysis": { "speaker_archetype": { "label": "Practical guide", "description": "Calm expert.", "axes": { "age_vibe": "experienced peer", "profession_archetype": "strategist", "temperament": "calm", "authority_posture": "confident" } }, "stance_and_relationship": { "narrative_person": "second person", "intimacy_distance": "trusted peer", "certainty_level": "Names uncertainty.", "audience_model": "Experienced creators." }, "delivery_recipe": { "cadence": "Short claims.", "energy": "Warm.", "pacing_and_emphasis": [ "Front-load the point." ] }, "rhetorical_toolkit": { "hook_patterns": [ "Open with a misconception." ], "transitions": [ "Here is the useful part." ], "explanation_patterns": [ "Make it concrete." ], "storytelling_patterns": [ "Start at the decision." ], "cta_patterns": [], "analogy_and_evidence": "Use one analogy.", "humor_and_empathy": "Keep humor light." }, "diction_and_syntax": { "vocabulary_level": "conversational", "word_complexity": "Prefer short words.", "sentence_shape": "Mix short and medium sentences.", "preferred_constructions": [ "Here is the tradeoff." ], "avoid": [ "Empty jargon." ] }, "phrase_kit": { "uses": [], "avoid": [], "replacements": [] }, "jargon_policy": { "allow": [], "explain_with": [ "a tiny example" ] }, "formatting_directives": [ "Use short paragraphs." ], "do_dont": { "do": [ "Lead with value." ], "dont": [ "Invent facts." ], "never_does": [ "Hide uncertainty." ] }, "locale_and_dialect": "Natural American English.", "thinking_style": "Test conclusions against evidence.", "spoken_patterns": { "common_phrases": [], "starter_words": [], "transition_phrases": [] }, "rewriter_directives": [ "Address the listener as you." ], "adherence_checklist": [ "No invented specifics." ], "lexical_glossary": [], "example_paragraph": "Start with the decision your viewer needs to make. Then give them only the evidence that changes it.", "style_examples": [ "Start with the decision your viewer needs to make. Then build the explanation around the evidence that changes that decision." ] } }, "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:05:00Z" }, "meta": { "idempotent_replay": false } } ``` **Response `201` example** ```json { "data": { "id": "2d3b57bd-916d-4ce2-a85b-a65dc8fc97b4", "name": "Practical guide", "framework_version": 2, "schema_version": 2, "checksum": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "revision": "voice-r1-example", "writable": true, "profile": { "writing_style_analysis": { "speaker_archetype": { "label": "Practical guide", "description": "Calm expert.", "axes": { "age_vibe": "experienced peer", "profession_archetype": "strategist", "temperament": "calm", "authority_posture": "confident" } }, "stance_and_relationship": { "narrative_person": "second person", "intimacy_distance": "trusted peer", "certainty_level": "Names uncertainty.", "audience_model": "Experienced creators." }, "delivery_recipe": { "cadence": "Short claims.", "energy": "Warm.", "pacing_and_emphasis": [ "Front-load the point." ] }, "rhetorical_toolkit": { "hook_patterns": [ "Open with a misconception." ], "transitions": [ "Here is the useful part." ], "explanation_patterns": [ "Make it concrete." ], "storytelling_patterns": [ "Start at the decision." ], "cta_patterns": [], "analogy_and_evidence": "Use one analogy.", "humor_and_empathy": "Keep humor light." }, "diction_and_syntax": { "vocabulary_level": "conversational", "word_complexity": "Prefer short words.", "sentence_shape": "Mix short and medium sentences.", "preferred_constructions": [ "Here is the tradeoff." ], "avoid": [ "Empty jargon." ] }, "phrase_kit": { "uses": [], "avoid": [], "replacements": [] }, "jargon_policy": { "allow": [], "explain_with": [ "a tiny example" ] }, "formatting_directives": [ "Use short paragraphs." ], "do_dont": { "do": [ "Lead with value." ], "dont": [ "Invent facts." ], "never_does": [ "Hide uncertainty." ] }, "locale_and_dialect": "Natural American English.", "thinking_style": "Test conclusions against evidence.", "spoken_patterns": { "common_phrases": [], "starter_words": [], "transition_phrases": [] }, "rewriter_directives": [ "Address the listener as you." ], "adherence_checklist": [ "No invented specifics." ], "lexical_glossary": [], "example_paragraph": "Start with the decision your viewer needs to make. Then give them only the evidence that changes it.", "style_examples": [ "Start with the decision your viewer needs to make. Then build the explanation around the evidence that changes that decision." ] } }, "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:00:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `409`, `422`, `429`, `500` ### `GET /api/v1/channels/{channel}/voices/{voice}` **Operation ID:** `getVoiceProfile` **Purpose:** Get a Channel Voice Profile. **Abilities:** `voices:read` **Parameters** - `channel` — path, required - `voice` — path, required **Response `200` example** ```json { "data": { "id": "2d3b57bd-916d-4ce2-a85b-a65dc8fc97b4", "name": "Practical guide", "framework_version": 2, "schema_version": 2, "checksum": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "revision": "voice-r1-example", "writable": true, "profile": { "writing_style_analysis": { "speaker_archetype": { "label": "Practical guide", "description": "Calm expert.", "axes": { "age_vibe": "experienced peer", "profession_archetype": "strategist", "temperament": "calm", "authority_posture": "confident" } }, "stance_and_relationship": { "narrative_person": "second person", "intimacy_distance": "trusted peer", "certainty_level": "Names uncertainty.", "audience_model": "Experienced creators." }, "delivery_recipe": { "cadence": "Short claims.", "energy": "Warm.", "pacing_and_emphasis": [ "Front-load the point." ] }, "rhetorical_toolkit": { "hook_patterns": [ "Open with a misconception." ], "transitions": [ "Here is the useful part." ], "explanation_patterns": [ "Make it concrete." ], "storytelling_patterns": [ "Start at the decision." ], "cta_patterns": [], "analogy_and_evidence": "Use one analogy.", "humor_and_empathy": "Keep humor light." }, "diction_and_syntax": { "vocabulary_level": "conversational", "word_complexity": "Prefer short words.", "sentence_shape": "Mix short and medium sentences.", "preferred_constructions": [ "Here is the tradeoff." ], "avoid": [ "Empty jargon." ] }, "phrase_kit": { "uses": [], "avoid": [], "replacements": [] }, "jargon_policy": { "allow": [], "explain_with": [ "a tiny example" ] }, "formatting_directives": [ "Use short paragraphs." ], "do_dont": { "do": [ "Lead with value." ], "dont": [ "Invent facts." ], "never_does": [ "Hide uncertainty." ] }, "locale_and_dialect": "Natural American English.", "thinking_style": "Test conclusions against evidence.", "spoken_patterns": { "common_phrases": [], "starter_words": [], "transition_phrases": [] }, "rewriter_directives": [ "Address the listener as you." ], "adherence_checklist": [ "No invented specifics." ], "lexical_glossary": [], "example_paragraph": "Start with the decision your viewer needs to make. Then give them only the evidence that changes it.", "style_examples": [ "Start with the decision your viewer needs to make. Then build the explanation around the evidence that changes that decision." ] } }, "created_at": "2026-07-22T12:00:00Z", "updated_at": "2026-07-22T12:00:00Z" }, "meta": { "idempotent_replay": false } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ## Webhooks ### `GET /api/v1/webhooks` **Operation ID:** `listWebhooks` **Purpose:** List Webhooks. **Abilities:** `webhooks:read` **Response `200` example** ```json { "success": true, "data": [ { "id": 12, "name": "Production notifications", "url": "https://example.com/webhooks/subscribr", "events": [ "script.generated", "idea.created" ], "active": true, "success_rate": 98.5, "last_delivery": null } ] } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/webhooks` **Operation ID:** `createWebhook` **Purpose:** Create Webhook. **Abilities:** `webhooks:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Request example** ```json { "name": "Partner hook", "url": "https://example.com/webhooks/subscribr", "events": [ "script.generated" ], "headers": { "X-Partner": "subscribr" }, "timeout": 30 } ``` **Response `201` example** ```json { "success": true, "data": { "id": 13, "name": "Partner hook", "url": "https://example.com/webhooks/subscribr", "events": [ "script.generated" ], "secret": "store-this-secret-once", "active": true, "timeout": 30 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `GET /api/v1/webhooks/{webhook}` **Operation ID:** `getWebhook` **Purpose:** Get Webhook. **Abilities:** `webhooks:read` **Parameters** - `webhook` — path, required **Response `200` example** ```json { "success": true, "data": { "id": 12, "name": "Production notifications", "url": "https://example.com/webhooks/subscribr", "events": [ "script.generated", "idea.created" ], "active": true, "headers": null, "timeout": 30, "success_rate": 98.5, "deliveries": [ { "id": 901, "event_type": "script.generated", "status": "success", "response_code": 200 } ] } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `PUT /api/v1/webhooks/{webhook}` **Operation ID:** `updateWebhook` **Purpose:** Update Webhook. **Abilities:** `webhooks:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `webhook` — path, required **Request example** ```json { "active": false, "headers": { "X-Partner": "updated" }, "timeout": 45 } ``` **Response `200` example** ```json { "success": true, "data": { "id": 12, "name": "Production notifications", "url": "https://example.com/webhooks/subscribr", "events": [ "script.generated" ], "active": false, "timeout": 30 } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `DELETE /api/v1/webhooks/{webhook}` **Operation ID:** `deleteWebhook` **Purpose:** Delete Webhook. **Abilities:** `webhooks:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `webhook` — path, required **Response `200` example** ```json { "success": true, "message": "Webhook deleted successfully" } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500` ### `POST /api/v1/webhooks/{webhook}/test` **Operation ID:** `testWebhook` **Purpose:** Test Webhook. **Abilities:** `webhooks:write` **Write safety:** idempotency `unsupported`; concurrency `unsupported`; retry `never`. **Parameters** - `webhook` — path, required **Response `200` example** ```json { "success": true, "data": { "success": true, "status_code": 200, "response_body": "{\"received\":true}", "error": null } } ``` **Errors:** `400`, `401`, `403`, `404`, `422`, `429`, `500`