{"openapi":"3.0.3","info":{"title":"CutPro API","version":"1.0.0","description":"The CutPro API lets you automate AI-powered video clipping and rendering programmatically.\n\n## Typical workflow\n\n1. **Analyze** a public video URL to preview metadata and credit cost, at no charge (`POST /clips/info`)\n2. **Submit** the video for AI clipping (`POST /clips`). Credits are deducted immediately, unless the workspace is on unlimited usage: `GET /balance` tells you which case you are in\n3. **Poll** the submission until `status` is `completed` or `failed` (`GET /clips/{videoId}/submissions/{submissionId}`)\n4. **Fetch** the AI-generated highlight clips (`GET /clips/{videoId}/submissions/{submissionId}/clips`)\n5. **Optionally** apply one of your templates in bulk (`POST /clips/{videoId}/submissions/{submissionId}/apply_template`)\n6. **Render** each clip to a final MP4 (`POST /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render`)\n7. **Poll** the render until `status` is `completed` (`GET /renders/{renderId}`)\n8. **Download** the rendered video (`GET /renders/{renderId}/download`)\n\nRendered files are kept for as long as your plan allows and then purged. Re-rendering does not need any of the steps above: `POST /renders` takes the `edit_id` of a clip you already own and gives you a fresh MP4, however long ago it was published.\n\n## Live monitoring\n\nMonitor a channel (`POST /monitors` with `type: live`) and every broadcast is clipped while it airs, a batch every 10\nminutes. List the broadcasts (`GET /monitors/{id}/broadcasts`), poll a broadcast's clips\n(`GET /monitors/{id}/broadcasts/{broadcastId}/clips`), optionally template them in bulk, and render each one\n(`POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`). From there it is the same render and post flow as\nany other clip. A `video` monitor needs none of this: each new upload becomes a regular submission in `GET /clips`.\n\n## Transcriptions\n\nSpeech-to-text stands on its own and can be called at any time: it needs no submission, no edit and no render.\nUpload a video or an audio file (`POST /transcriptions/upload`), start the job (`POST /transcriptions`), poll it\n(`GET /transcriptions/{transcriptionId}`), then read the transcript as JSON cues (`/transcript`) or as an SRT/VTT/TXT\nfile (`/download`).\n\n## AI personas\n\nCreate a realistic person from traits, or from photos of the user's own face, and put them in any video in place of\nthe person who appears in it. Read the traits, prices and limits (`GET /personas/catalog`), create the persona\n(`POST /personas`), poll it until its photo is ready (`GET /personas/{id}`), adjust it if needed\n(`POST /personas/{id}/regenerate`) and save it (`POST /personas/{id}/save`). A saved persona can still be regenerated;\nevery photo is kept as a version (`versions`) and `POST /personas/{id}/versions/{versionId}/restore` goes back to one. Then upload a video\n(`POST /personas/sources/upload`), price it (`GET /personas/swap/quote`), start a `swap` video with that price\n(`POST /personas/{id}/videos`) and poll it until it is ready (`GET /personas/{id}/videos/{videoId}`).\n\n## AI images and videos\n\nGenerate an image or a video with any model CutPro offers (Veo, Kling, Seedance, Wan, Nano Banana, GPT Image and more).\nRead the models, their options and prices (`GET /generations/models`), optionally upload reference images\n(`POST /generations/images`), start the generation with the agreed price (`POST /generations`) and poll it until it is\nready (`GET /generations/{id}`). A ready image animates into a video by passing its `output.image_id` in `image_ids`.\n\n## Authentication\n\nPass your API key on every request via the `X-Api-Key` header or as `Authorization: Bearer <key>`.\nYou can generate API keys from your account settings at [cut.pro](https://cut.pro).\n\n## Conventions\n\nEvery field on the wire is `snake_case`. A resource's own identifier is always `id`; a pointer to another\nresource carries its name (`video_id`, `edit_id`, `connection_id`). Every timestamp is an ISO 8601 string, every\nduration and offset is in seconds, and every list answers `{ \"<resource>\": [...], \"pagination\": {...} }`.\n\nThe one deliberate exception is `metadata` in `POST /posts`: those keys are each network's own\n(`privacyLevel`, `categoryId`, `privacyStatus`) and are forwarded untouched, so renaming them here would hide\nwhat actually goes out.\n\n## Errors\n\nEvery error, on every endpoint and every status, has the same body:\n\n```json\n{ \"code\": \"INSUFFICIENT_CREDITS\", \"extra\": { \"credits_needed\": 121, \"current_balance\": 40 } }\n```\n\n`code` is a stable, uppercase, closed set, so switch on it. `extra` only appears when there is something to act on\n(what was missing, which field failed, which ids were rejected). There is never a human-readable message: the\nserver does not know your user's language, and prose cannot be handled in a `switch`.\n\nStates are the opposite: `status` values are lowercase (`queued`, `processing`, `completed`, `failed`), because they\ndescribe where something is, not what went wrong.\n\n| Status | Means | Do |\n|---|---|---|\n| `400` | The request body is wrong | Fix the payload; do not retry as-is |\n| `401` | Key missing, revoked or expired | Check `X-Api-Key` |\n| `402` | Not enough credits | Top up, or read `extra.credits_needed` |\n| `403` | The source or the account is off limits | Nothing to retry |\n| `404` | Does not exist in this workspace | Check the id and the workspace |\n| `409` | Exists, but its state refuses the operation | Wait and retry |\n| `410` | Existed and expired | Re-submit or re-render |\n| `422` | Valid link, unusable video | Try a different source |\n| `429` | Rate limited | Wait `Retry-After` seconds |\n| `5xx` | Our fault | Retry with backoff |\n\n## Rate limits\n\n**600 requests per minute per API key**, in a fixed 60-second window. Every response carries the current state,\nso you can slow down before being cut off:\n\n- `X-RateLimit-Limit`: the ceiling (600)\n- `X-RateLimit-Remaining`: calls still available in this window\n- `X-RateLimit-Reset`: Unix seconds when the window resets\n\nOver the limit you get `429` with `{ \"code\": \"RATE_LIMIT_EXCEEDED\" }` and a `Retry-After` header in seconds. Honour it;\nretrying immediately only burns the next window. `POST /clips/info` has its own, tighter limit of 10 per minute,\nbecause it reaches out to the source platform on every call.\n\nPolling every 5 to 10 seconds per job is the intended pattern and fits the limit with room to spare.\n\n## Workspaces\n\nAn API key is bound to one or more workspaces (Cloudflare-style scoped tokens).\n\n- **Single-workspace key**: every request operates on that workspace automatically. No header needed.\n- **Multi-workspace key**: pass `X-Workspace-Id: <workspace-id>` on every request to pick which workspace\n  the call hits. Without the header, you get `400 MISSING_WORKSPACE_ID` with the list of allowed\n  workspace ids in the response.\n\nCall `GET /workspace` to inspect the workspace the current request resolved to, plus its plan and role.\n\n## Credits\n\nCredits are consumed when a submission is created, and by standalone jobs such as transcriptions and\ntranslations. Check the workspace balance at `GET /balance`, and use `POST /clips/info` to see the exact\ncost before committing.\n\nLive monitoring is charged per 10-minute batch of a broadcast, only for batches that produced clips, and only\nwhile the monitor is on (`POST /monitors/{id}/start` to `POST /monitors/{id}/stop`).\n\nAI personas and AI images and videos are charged per image and per second of video, and always consume credits: the free usage below does\nnot cover them. When one of these calls answers `402 INSUFFICIENT_CREDITS`, `extra.top_up_url` is the page where\ncredits are bought and `extra.is_owner` says whether the key's user can buy them for this workspace.\n\n### Free usage\n\nA workspace can be put on free usage. While it is on, jobs run without consuming credits and are never\nrejected for lack of balance, no matter what the balance says.\n\n- `GET /balance` reports it as `unlimited`, and `unlimited_until` is when the window ends (`null` = no end date).\n- `GET /workspace` carries the same thing as `credits_unlimited` / `credits_unlimited_until`.\n- `POST /clips/info` returns `credits_unlimited` alongside `credits_cost`, so a pre-flight check tells you\n  both what the job is worth and whether it will actually be billed.\n\nNothing is hidden from the record: the job still appears in `GET /balance/history` with the amount it would\nhave cost and `waived: true`, and `balance_after` stays where it was. Fields that report money actually taken\n(`credits_charged`) come back as `0`."},"servers":[{"url":"https://api.cut.pro/api/v1"}],"tags":[{"name":"Workspace","description":"The workspace this request resolved to. Single-workspace keys always resolve to their bound workspace. Multi-workspace keys resolve via the `X-Workspace-Id` header: credits, submissions, clips and renders belong to whichever workspace the header selects on each request."},{"name":"Videos","description":"Your clipping library: the source videos you have submitted for AI clipping."},{"name":"Submissions","description":"Clipping jobs: the full lifecycle from pre-flight analysis through AI processing to completion. Each submission is tied to a video and produces a set of generated clips when it completes."},{"name":"Clips","description":"AI-generated highlight clips produced by a completed submission. Each clip includes timestamps, a relevance score, and signed URLs for streaming and downloading. Clips can have a template applied and then be rendered to a final MP4."},{"name":"Renders","description":"Video render jobs. After optionally applying a template to a clip, start a render to produce a final MP4. Poll the render until completed, then download the file.\n\n**Rendered files expire.** Your plan sets how long a finished MP4 stays in storage (`GET /renders/limits` reports it as `render_expiry_hours`); after that the render turns `expired` and the download is gone. The edit itself never expires, so `POST /renders` with its `edit_id` produces a fresh file at any time, however old the clip is."},{"name":"Posts","description":"Multi-platform publishing. Create a post that references one or more edited clips plus the social connections to publish to, then poll it through `pending → processing → completed`. Failed items can be retried or removed without disturbing siblings that already published.\n\nEvery item carries the `metadata` it was published with (title, caption/description and per-network options), so you can read back the exact text that went live. Its `render_id` is `null` once the rendered file is gone: the post stays, the MP4 does not, and `POST /renders` with the item's `edit_id` makes a new one."},{"name":"Templates","description":"Video editing templates that apply visual effects, captions, cropping, and other styles to clips in bulk. List your templates to find an ID to pass to `apply_template`."},{"name":"Balance","description":"Credit balance and ledger of the workspace this API key represents. Credits are consumed when you create a submission. For full workspace metadata (plan, seats, role, member count) see `GET /workspace`."},{"name":"Transcriptions","description":"Standalone speech-to-text. Upload a video or an audio file at any time and get the transcript back as timed JSON cues or as an SRT/VTT/TXT file, with no clipping submission, no edit and no render involved. Optional speaker identification labels who is talking on each cue."},{"name":"Personas","description":"AI personas: a realistic person made from traits or from reference photos of the user's own face, then swapped into library videos while the scene, camera, motion and sound stay as they were. Photos and videos run in the background: create, then poll. Every charge is refunded automatically when a generation fails."},{"name":"Generations","description":"Images and videos generated from a prompt, or from reference images, with the model of your choice. Generations run in the background: create, then poll. Every charge is refunded automatically when a generation fails."},{"name":"Monitoring","description":"Channels this workspace watches for new videos or live broadcasts, clipped automatically. Create a monitor from the channel URL, then start and stop it from your own system: a 24/7 stream can be clipped only while a show is on air by creating it with `enabled: false`, calling `start` when the show begins and `stop` when it ends.\n\nA `live` monitor's clips live under its broadcasts: `GET /monitors/{id}/broadcasts`, then each broadcast's `clips`."},{"name":"Connections","description":"Social media accounts connected to this workspace: the IDs you pass as `connection_id` when creating a post. To connect a new account, `GET /connections/link` gives a cut.pro link that opens that network's sign-in in this workspace."}],"paths":{"/workspace":{"get":{"tags":["Workspace"],"operationId":"getWorkspace","summary":"Get current workspace","description":"Returns information about the workspace this request resolved to: name, plan, credit balance, member count and the role of the user who created the key.\n\nA key bound to one workspace always resolves to it. A key bound to several resolves to the one in the `X-Workspace-Id` header, so call this whenever you need to confirm which workspace a request is actually hitting.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","name","is_personal","status","role","plan_id","plan_name","plan_is_free","credits","credits_unlimited","credits_unlimited_until","seat_count","max_total_seats","member_count","created_at"],"properties":{"id":{"description":"Unique workspace ID","type":"string"},"name":{"description":"Workspace name","type":"string"},"is_personal":{"description":"`true` if this is the user's personal workspace, `false` if it is a team workspace","type":"boolean"},"status":{"description":"Workspace status — typically `active`","type":"string"},"role":{"type":"string","enum":["admin","member"]},"plan_id":{"description":"ID of the current subscription plan","type":"string"},"plan_name":{"description":"Display name of the current plan","type":"string","nullable":true},"plan_is_free":{"description":"`true` if the workspace is on the free plan","type":"boolean"},"credits":{"description":"Current credit balance for this workspace","type":"number"},"credits_unlimited":{"description":"`true` while usage is free for this workspace: jobs run without consuming the balance","type":"boolean"},"credits_unlimited_until":{"description":"ISO 8601 timestamp when the free-usage window ends; `null` means it has no end date","type":"string","nullable":true},"seat_count":{"description":"Extra purchased seats. Legacy: always 0 today, seats come with the plan","type":"number"},"max_total_seats":{"description":"Maximum total seats available on the current plan, including any plan-included free seats","type":"number"},"member_count":{"description":"Total members currently in the workspace, including the owner","type":"number"},"created_at":{"description":"ISO 8601 timestamp of when the workspace was created","type":"string"}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["WORKSPACE_NOT_FOUND"]}},"additionalProperties":false}}}}}}},"/balance":{"get":{"tags":["Balance"],"operationId":"getBalance","summary":"Get balance","description":"Returns your current credit balance. Credits are consumed each time you submit a video for clipping. When `unlimited` is true this workspace is on a courtesy plan: usage still shows up in the history with what it would have cost, but the balance does not move and jobs are never blocked for lack of credits.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["balance","unlimited","unlimited_until"],"properties":{"balance":{"type":"number"},"unlimited":{"description":"`true` while usage is free for this workspace: the balance never decreases","type":"boolean"},"unlimited_until":{"description":"ISO 8601 timestamp when the free-usage window ends; `null` means it has no end date","type":"string","nullable":true}},"additionalProperties":false}}}}}}},"/balance/history":{"get":{"tags":["Balance"],"operationId":"getBalanceHistory","summary":"Get credit history","description":"Returns the credit transaction ledger for this workspace, newest first. Each row shows the delta (`amount`, negative for debits), the resulting balance, and what caused it (`reference_type` + `reference_id`) so you can reconcile against submissions, renewals, refunds, and bonuses.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 50, max: 100)","type":"number"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["credit","debit","refund","bonus","subscription_renewal","subscription_activation"]}},{"name":"reference_type","in":"query","required":false,"schema":{"type":"string","enum":["subscription","refund","bonus","usage","adjustment","championship","championship_prize","championship_refund","championship_period_prize","championship_per_thousand_views","championship_per_post","credit_bundle","workspace_transfer","referral"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["transactions","pagination"],"properties":{"transactions":{"type":"array","items":{"type":"object","required":["id","type","amount","balance_after","reference_type","reference_id","description","waived","expires_at","created_at"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["credit","debit","refund","bonus","subscription_renewal","subscription_activation"]},"amount":{"description":"Signed delta — positive for credits, negative for debits","type":"number"},"balance_after":{"description":"Workspace balance after this transaction was applied","type":"number"},"reference_type":{"nullable":true,"type":"string","enum":["subscription","refund","bonus","usage","adjustment","championship","championship_prize","championship_refund","championship_period_prize","championship_per_thousand_views","championship_per_post","credit_bundle","workspace_transfer","referral"]},"reference_id":{"description":"ID of the related entity — e.g. submission id, subscription id","type":"string","nullable":true},"description":{"type":"string","nullable":true},"waived":{"description":"`true` when the usage was free (courtesy): `amount` is what it would have cost and the balance did not move","type":"boolean"},"expires_at":{"description":"ISO 8601 timestamp — only set for credits that expire","type":"string","nullable":true},"created_at":{"type":"string"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}}}}}}}}},"/videos/upload":{"post":{"x-mcp":{"localFiles":true},"tags":["Videos"],"operationId":"createVideoUpload","summary":"Start an upload","description":"Returns the generated `video_id` plus whatever the file's size requires to upload it directly to storage, then call `POST /videos/upload/complete` to register the upload and get the credit cost.\n\nWhen `mode` is `single`, PUT the bytes to `upload_url` with the same `Content-Type` you declared here.\n\nWhen `mode` is `multipart` the file is past the storage provider's single-PUT ceiling: split it into `part_size`-byte chunks and PUT each one to the matching entry of `part_urls` (index 0 is part 1, the last part may be shorter). Collect each response's `ETag` header and post them to `POST /videos/upload/multipart/complete`.\n\nMax file size comes from your plan — a `FILE_TOO_LARGE` response reports the effective ceiling in `max_size`. Extensions: `.mp4`, `.mov`, `.webm`, `.mkv`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name. Used to detect the extension and as a fallback title.","type":"string"},"file_size":{"description":"Size of the file in bytes. The ceiling comes from your plan.","type":"number"},"content_type":{"description":"MIME type — defaults to `video/mp4`. Must match the bytes you PUT.","type":"string"}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name. Used to detect the extension and as a fallback title.","type":"string"},"file_size":{"description":"Size of the file in bytes. The ceiling comes from your plan.","type":"number"},"content_type":{"description":"MIME type — defaults to `video/mp4`. Must match the bytes you PUT.","type":"string"}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name. Used to detect the extension and as a fallback title.","type":"string"},"file_size":{"description":"Size of the file in bytes. The ceiling comes from your plan.","type":"number"},"content_type":{"description":"MIME type — defaults to `video/mp4`. Must match the bytes you PUT.","type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["mode","video_id","upload_url","expires_in"],"properties":{"mode":{"type":"string","enum":["single"]},"video_id":{"description":"Generated video ID. Pass it to `POST /videos/upload/complete` after the PUT.","type":"string"},"upload_url":{"description":"Presigned PUT URL — upload the raw bytes here.","type":"string"},"expires_in":{"description":"Seconds until `upload_url` expires.","type":"number"}}},{"type":"object","required":["mode","video_id","upload_id","part_urls","part_size","expires_in"],"properties":{"mode":{"type":"string","enum":["multipart"]},"video_id":{"description":"Generated video ID. Pass it to the multipart complete call and then to `POST /videos/upload/complete`.","type":"string"},"upload_id":{"description":"Multipart upload ID — echo it back when completing or aborting.","type":"string"},"part_urls":{"description":"One presigned PUT URL per part, in order. Index 0 is part number 1.","type":"array","items":{"type":"string"}},"part_size":{"description":"Bytes per part. Every part but the last must be exactly this size.","type":"number"},"expires_in":{"description":"Seconds until the part URLs expire.","type":"number"}}}]}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_FILE_TYPE","FILE_TOO_LARGE"]},"extra":{"type":"object","properties":{"allowed_extensions":{"description":"Accepted file extensions. Only on `INVALID_FILE_TYPE`.","type":"array","items":{"type":"string"}},"max_size":{"description":"Largest file your plan accepts, in bytes. Only on `FILE_TOO_LARGE`.","type":"number"}}}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRESIGN_FAILED"]}},"additionalProperties":false}}}}}}},"/videos/upload/multipart/complete":{"post":{"x-mcp":{"localFiles":true},"tags":["Videos"],"operationId":"completeVideoMultipartUpload","summary":"Finalize a multipart upload","description":"Assembles the uploaded parts into the final object. Only needed when `POST /videos/upload` answered with `mode: \"multipart\"`. After this succeeds, call `POST /videos/upload/complete` to register the video.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["video_id","upload_id","parts"],"properties":{"video_id":{"description":"The `video_id` from `POST /videos/upload`.","type":"string"},"upload_id":{"description":"The `upload_id` from `POST /videos/upload`.","type":"string"},"parts":{"description":"Every part you uploaded, ordered by `part_number`.","type":"array","items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"description":"1-indexed part number, matching the `part_urls` position you PUT to.","type":"number"},"etag":{"description":"The `ETag` response header from that part's PUT.","type":"string"}}}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["video_id","upload_id","parts"],"properties":{"video_id":{"description":"The `video_id` from `POST /videos/upload`.","type":"string"},"upload_id":{"description":"The `upload_id` from `POST /videos/upload`.","type":"string"},"parts":{"description":"Every part you uploaded, ordered by `part_number`.","type":"array","items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"description":"1-indexed part number, matching the `part_urls` position you PUT to.","type":"number"},"etag":{"description":"The `ETag` response header from that part's PUT.","type":"string"}}}}}}},"multipart/form-data":{"schema":{"type":"object","required":["video_id","upload_id","parts"],"properties":{"video_id":{"description":"The `video_id` from `POST /videos/upload`.","type":"string"},"upload_id":{"description":"The `upload_id` from `POST /videos/upload`.","type":"string"},"parts":{"description":"Every part you uploaded, ordered by `part_number`.","type":"array","items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"description":"1-indexed part number, matching the `part_urls` position you PUT to.","type":"number"},"etag":{"description":"The `ETag` response header from that part's PUT.","type":"string"}}}}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["video_id"],"properties":{"video_id":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["FILE_NOT_FOUND"]}}}}}}}}},"/videos/upload/multipart/abort":{"post":{"x-mcp":{"localFiles":true},"tags":["Videos"],"operationId":"abortVideoMultipartUpload","summary":"Discard a multipart upload","description":"Releases the parts already uploaded. Without this they keep occupying (and billing) storage — there is no object yet for a lifecycle rule to match.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["video_id","upload_id"],"properties":{"video_id":{"description":"The `video_id` from `POST /videos/upload`.","type":"string"},"upload_id":{"description":"The `upload_id` from `POST /videos/upload`.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["video_id","upload_id"],"properties":{"video_id":{"description":"The `video_id` from `POST /videos/upload`.","type":"string"},"upload_id":{"description":"The `upload_id` from `POST /videos/upload`.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["video_id","upload_id"],"properties":{"video_id":{"description":"The `video_id` from `POST /videos/upload`.","type":"string"},"upload_id":{"description":"The `upload_id` from `POST /videos/upload`.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["video_id"],"properties":{"video_id":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["FILE_NOT_FOUND"]}}}}}}}}},"/videos/upload/complete":{"post":{"x-mcp":{"localFiles":true},"tags":["Videos"],"operationId":"completeVideoUpload","summary":"Complete an upload","description":"Registers a finished upload, captures its dimensions/duration, and returns the video metadata together with the exact credit cost, in the same payload shape as `POST /clips/info`. Pass the returned `video_id` to `POST /clips` to start a clipping submission.\n\nCall this only after the PUT to `upload_url` returned `200`. If the file is missing from storage, this returns `FILE_NOT_FOUND`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["video_id","file_name","duration","width","height"],"properties":{"video_id":{"description":"The `video_id` returned by `POST /videos/upload`.","type":"string"},"file_name":{"description":"Original file name — used as the video title.","type":"string"},"duration":{"description":"Video duration in seconds.","type":"number"},"width":{"description":"Video width in pixels.","type":"number"},"height":{"description":"Video height in pixels.","type":"number"}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["video_id","file_name","duration","width","height"],"properties":{"video_id":{"description":"The `video_id` returned by `POST /videos/upload`.","type":"string"},"file_name":{"description":"Original file name — used as the video title.","type":"string"},"duration":{"description":"Video duration in seconds.","type":"number"},"width":{"description":"Video width in pixels.","type":"number"},"height":{"description":"Video height in pixels.","type":"number"}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["video_id","file_name","duration","width","height"],"properties":{"video_id":{"description":"The `video_id` returned by `POST /videos/upload`.","type":"string"},"file_name":{"description":"Original file name — used as the video title.","type":"string"},"duration":{"description":"Video duration in seconds.","type":"number"},"width":{"description":"Video width in pixels.","type":"number"},"height":{"description":"Video height in pixels.","type":"number"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","title","description","author","platform","duration","thumbnail_url","credits_cost","credits_original","discount_percent","force_watermark","current_balance","credits_unlimited"],"properties":{"id":{"description":"The registered video. Pass it to `POST /clips` as `video_id`.","type":"string"},"title":{"type":"string"},"description":{"type":"string"},"author":{"type":"string"},"platform":{"type":"string"},"duration":{"type":"number"},"thumbnail_url":{"type":"string"},"credits_cost":{"description":"Cost of clipping this video. Charged on submit unless `credits_unlimited` is `true`.","type":"number"},"credits_original":{"description":"Credit cost before any plan discount.","type":"number"},"discount_percent":{"description":"Discount applied by the current plan (0-100).","type":"number"},"force_watermark":{"description":"`true` if generated clips will carry a CutPro watermark.","type":"boolean"},"current_balance":{"description":"Current workspace credit balance.","type":"number"},"credits_unlimited":{"description":"`true` while usage is free for this workspace: the job runs without consuming credits and is never rejected for lack of balance.","type":"boolean"}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["VIDEO_TOO_LONG","VIDEO_TOO_SHORT"]},"extra":{"type":"object","required":["duration"],"properties":{"duration":{"description":"Measured duration of the uploaded file, in seconds.","type":"number"},"max_duration":{"description":"Longest video your plan accepts, in seconds. Only on `VIDEO_TOO_LONG`.","type":"number"}}}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["FILE_NOT_FOUND"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INTERNAL_ERROR"]}},"additionalProperties":false}}}}}}},"/clips":{"get":{"tags":["Videos"],"operationId":"listVideos","summary":"List videos","description":"Returns a paginated list of all source videos in your library, ordered by most recent submission. Each item includes lifecycle counters (clips generated, edits, exports, posts) and the status of the latest submission.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 12, max: 100)","type":"number"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["recent","oldest","title","title-desc"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["videos","pagination"],"properties":{"videos":{"type":"array","items":{"type":"object","required":["id","title","author","platform","duration","thumbnail_url","video_url","clips_count","edited_count","exported_count","posted_count","submissions_count"],"properties":{"id":{"description":"Unique video ID","type":"string"},"title":{"description":"Video title as reported by the source platform","type":"string"},"author":{"description":"Channel or creator name","type":"string"},"platform":{"description":"Source platform — e.g. `youtube`, `twitch`, `kick`, `tiktok`, `upload`","type":"string"},"duration":{"description":"Video duration in seconds","type":"number"},"thumbnail_url":{"description":"URL of the video thumbnail image","type":"string"},"video_url":{"description":"Direct URL to the source video, or `null` if no longer available","type":"string","nullable":true},"clips_count":{"description":"Total AI-generated clips available across all submissions","type":"number"},"edited_count":{"description":"Number of clips customised in the editor","type":"number"},"exported_count":{"description":"Number of clips rendered and exported","type":"number"},"posted_count":{"description":"Number of clips posted to social media","type":"number"},"submissions_count":{"description":"Total number of clipping submissions for this video","type":"number"},"last_submission":{"type":"object","required":["status","error_code","waiting_reason","waiting_until","estimated_time","queue_position","is_priority","created_at","completed_at"],"properties":{"status":{"type":"string","enum":["queued","downloading","transcribing","video_analysis","analyzing","finalizing","completed","failed"]},"error_code":{"nullable":true,"type":"string","enum":["DOWNLOAD_FAILED","DOWNLOAD_ACCESS_DENIED","DOWNLOAD_MEMBERS_ONLY","DOWNLOAD_PRIVATE_VIDEO","DOWNLOAD_GEO_RESTRICTED","DOWNLOAD_TIMEOUT","DOWNLOAD_NETWORK","DOWNLOAD_NO_AUDIO","DOWNLOAD_NOT_AVAILABLE","DOWNLOAD_REMOVED_BY_UPLOADER","DOWNLOAD_PREMIERE_NOT_STARTED","DOWNLOAD_LIVE_IN_PROGRESS","TRANSCRIBE_FAILED","VIDEO_ANALYSIS_FAILED","ANALYZE_FAILED","GENERATE_FAILED","EMPTY_TRANSCRIPT","UPLOAD_CORRUPTED","UNKNOWN"]},"waiting_reason":{"description":"Why the submission is waiting on its source: `SOURCE_PREMIERE_SCHEDULED` (scheduled premiere that has not aired), `SOURCE_LIVE_IN_PROGRESS` (livestream still on air), `SOURCE_VOD_PROCESSING` (broadcast ended, platform still publishing the recording).","nullable":true,"type":"string","enum":["SOURCE_PREMIERE_SCHEDULED","SOURCE_LIVE_IN_PROGRESS","SOURCE_VOD_PROCESSING"]},"waiting_until":{"description":"ISO 8601 timestamp announced for the premiere, when known","type":"string","nullable":true},"estimated_time":{"description":"Estimated seconds remaining until completion","type":"number","nullable":true},"queue_position":{"description":"Position in the processing queue; `null` once processing has started","type":"number","nullable":true},"is_priority":{"description":"`true` if this submission has priority processing","type":"boolean"},"created_at":{"description":"ISO 8601 timestamp of when the submission was created","type":"string"},"completed_at":{"description":"ISO 8601 timestamp of when the submission finished, or `null` if still running","type":"string","nullable":true}}}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}}}},"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Submissions"],"operationId":"createSubmission","summary":"Submit a video for clipping","description":"Queues a video for AI clipping. Credits are deducted immediately upon submission. Returns the submission `id` to track progress.\n\nPoll `GET /clips/{videoId}/submissions/{submissionId}` until `status` is `completed` or `failed`, then retrieve the generated clips from `GET /clips/{videoId}/submissions/{submissionId}/clips`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["video_id"],"properties":{"video_id":{"description":"The `video_id` returned by `POST /clips/info`","type":"string"},"source_language":{"type":"string","enum":["auto","en","pt"]},"strategy_id":{"description":"ID of a saved clipping strategy. Omit or pass `null` to use default AI settings","type":"string","nullable":true},"timeframe":{"type":"object","required":["start","end"],"properties":{"start":{"minimum":0,"description":"Process from this offset in seconds (inclusive)","type":"number"},"end":{"minimum":1,"description":"Process up to this offset in seconds (exclusive)","type":"number"}},"description":"Restrict clipping to a portion of the video. Omit to process the full video","nullable":true},"template_id":{"description":"ID of an edit template from `GET /templates` to auto-apply to every generated clip. An unknown one answers `404 TEMPLATE_NOT_FOUND` before anything is charged","type":"string","nullable":true},"translate_to":{"description":"Language code (ISO 639-1, e.g. `en`, `es`) to translate the clips' captions into. Costs more than the plain job, and `credits_charged` reports what was taken; the surcharge is refunded when the video turns out to be spoken in that language already. Omit to keep the strategy's own setting, or pass `\"\"` for no translation.","type":"string"}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["video_id"],"properties":{"video_id":{"description":"The `video_id` returned by `POST /clips/info`","type":"string"},"source_language":{"type":"string","enum":["auto","en","pt"]},"strategy_id":{"description":"ID of a saved clipping strategy. Omit or pass `null` to use default AI settings","type":"string","nullable":true},"timeframe":{"type":"object","required":["start","end"],"properties":{"start":{"minimum":0,"description":"Process from this offset in seconds (inclusive)","type":"number"},"end":{"minimum":1,"description":"Process up to this offset in seconds (exclusive)","type":"number"}},"description":"Restrict clipping to a portion of the video. Omit to process the full video","nullable":true},"template_id":{"description":"ID of an edit template from `GET /templates` to auto-apply to every generated clip. An unknown one answers `404 TEMPLATE_NOT_FOUND` before anything is charged","type":"string","nullable":true},"translate_to":{"description":"Language code (ISO 639-1, e.g. `en`, `es`) to translate the clips' captions into. Costs more than the plain job, and `credits_charged` reports what was taken; the surcharge is refunded when the video turns out to be spoken in that language already. Omit to keep the strategy's own setting, or pass `\"\"` for no translation.","type":"string"}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["video_id"],"properties":{"video_id":{"description":"The `video_id` returned by `POST /clips/info`","type":"string"},"source_language":{"type":"string","enum":["auto","en","pt"]},"strategy_id":{"description":"ID of a saved clipping strategy. Omit or pass `null` to use default AI settings","type":"string","nullable":true},"timeframe":{"type":"object","required":["start","end"],"properties":{"start":{"minimum":0,"description":"Process from this offset in seconds (inclusive)","type":"number"},"end":{"minimum":1,"description":"Process up to this offset in seconds (exclusive)","type":"number"}},"description":"Restrict clipping to a portion of the video. Omit to process the full video","nullable":true},"template_id":{"description":"ID of an edit template from `GET /templates` to auto-apply to every generated clip. An unknown one answers `404 TEMPLATE_NOT_FOUND` before anything is charged","type":"string","nullable":true},"translate_to":{"description":"Language code (ISO 639-1, e.g. `en`, `es`) to translate the clips' captions into. Costs more than the plain job, and `credits_charged` reports what was taken; the surcharge is refunded when the video turns out to be spoken in that language already. Omit to keep the strategy's own setting, or pass `\"\"` for no translation.","type":"string"}},"additionalProperties":false}}}},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id","video_id","status","credits_charged"],"properties":{"id":{"description":"ID of the created submission. Poll it for progress","type":"string"},"video_id":{"description":"ID of the source video","type":"string"},"status":{"type":"string","enum":["queued"]},"credits_charged":{"description":"Credits actually deducted from your balance. `0` when the clip was free, including while this workspace has unlimited usage","type":"number"}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_STRATEGY_OPTIONS","INVALID_TRANSLATE_LANGUAGE","TIMEFRAME_OUT_OF_BOUNDS","TIMEFRAME_TOO_SHORT","VIDEO_TOO_LONG"]}},"additionalProperties":false}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS","CREDIT_CHARGE_FAILED"]},"extra":{"type":"object","required":["credits_needed","current_balance","is_reclip","scope","is_owner"],"properties":{"credits_needed":{"type":"number"},"current_balance":{"type":"number"},"is_reclip":{"type":"boolean"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"type":"boolean"}}}},"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PLATFORM_NOT_SUPPORTED"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["STRATEGY_NOT_FOUND","TEMPLATE_NOT_FOUND","NO_VIDEO_INFO"]}},"additionalProperties":false}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_ALREADY_PROCESSING"]}},"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TOO_MANY_PENDING_CLIPS"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CREDIT_CHARGE_ERROR","PROCESSING_ERROR"]}},"additionalProperties":false}}}}}}},"/clips/info":{"post":{"x-mcp":{"annotations":{"readOnlyHint":true,"openWorldHint":true}},"tags":["Submissions"],"operationId":"analyzeVideo","summary":"Analyze a video","description":"Fetches metadata for a public video URL and calculates the exact credit cost before you commit to clipping. No credits are charged. Use this as a pre-flight check before calling `POST /clips`.\n\nWhen `credits_unlimited` is `true`, this workspace is on free usage: `credits_cost` still tells you what the job is worth, but submitting it will not move your balance.\n\nRate-limited to **10 requests per minute** per user.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"description":"Public video URL (YouTube, Twitch, Kick, TikTok, etc.)","type":"string"}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["url"],"properties":{"url":{"description":"Public video URL (YouTube, Twitch, Kick, TikTok, etc.)","type":"string"}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["url"],"properties":{"url":{"description":"Public video URL (YouTube, Twitch, Kick, TikTok, etc.)","type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","title","description","author","platform","duration","thumbnail_url","credits_cost","credits_original","discount_percent","force_watermark","current_balance","credits_unlimited"],"properties":{"id":{"description":"Unique video ID. Pass it to `POST /clips` as `video_id`","type":"string"},"title":{"description":"Video title","type":"string"},"description":{"description":"Video description","type":"string"},"author":{"description":"Channel or creator name","type":"string"},"platform":{"description":"Source platform — e.g. `youtube`, `twitch`, `kick`, `tiktok`","type":"string"},"duration":{"description":"Video duration in seconds","type":"number"},"thumbnail_url":{"description":"URL of the video thumbnail","type":"string"},"credits_cost":{"description":"Cost of clipping this video, after any discount. Deducted on submit unless `credits_unlimited` is `true`","type":"number"},"credits_original":{"description":"Base credit cost before loyalty or plan discounts","type":"number"},"discount_percent":{"description":"Discount applied as a percentage (0–100). Non-zero for returning users or plan benefits","type":"number"},"force_watermark":{"description":"`true` if generated clips will carry a CutPro watermark — upgrade your plan to remove it","type":"boolean"},"current_balance":{"description":"Your credit balance at the time of this request","type":"number"},"credits_unlimited":{"description":"`true` while usage is free for this workspace: the job runs without consuming credits and is never rejected for lack of balance","type":"boolean"}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_TOO_LONG"]},"extra":{"type":"object","required":["duration","max_duration"],"properties":{"duration":{"type":"number"},"max_duration":{"type":"number"}}}},"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRIVATE_VIDEO","AGE_RESTRICTED","ACCESS_DENIED","PLATFORM_NOT_SUPPORTED","REGION_BLOCKED","COPYRIGHT_BLOCKED"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["METADATA_UNAVAILABLE","VIDEO_ID_NOT_FOUND","UNAVAILABLE"]}},"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["LIVE_STREAM","INVALID_DURATION","PREMIUM_ONLY","PLAYLIST_URL","CHANNEL_URL","SHORTS_NOT_SUPPORTED","INVALID_URL","INVALID_DIMENSIONS","AUDIO_ONLY"]}},"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["RATE_LIMIT_EXCEEDED"]},"extra":{"type":"object","required":["retry_after"],"properties":{"retry_after":{"description":"Seconds to wait before retrying. Also sent as the `Retry-After` header.","type":"number"}}}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["UNKNOWN_ERROR","FAILED_TO_GET_VIDEO"]}},"additionalProperties":false}}}},"503":{"description":"Response for status 503","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SERVICE_UNAVAILABLE"]}},"additionalProperties":false}}}}}}},"/clips/{videoId}":{"delete":{"tags":["Videos"],"operationId":"deleteVideo","summary":"Delete a video","description":"Permanently deletes a video from your library along with all its submissions and generated clips. This action cannot be undone. Submissions still processing are cancelled and their credits refunded.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_FORBIDDEN"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_NOT_FOUND"]}}}}}}}}},"/clips/{videoId}/submissions":{"get":{"tags":["Submissions"],"operationId":"listSubmissions","summary":"List submissions","description":"Returns a paginated list of all clipping submissions for a video, newest first. Use this to audit past runs, find a specific submission ID, or check whether a job is still in progress.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["submissions","pagination"],"properties":{"submissions":{"type":"array","items":{"type":"object","required":["id","status","error_code","estimated_time","queue_position","is_priority","strategy_id","timeframe","credit_cost","is_reclip","clips_count","created_at","completed_at"],"properties":{"id":{"description":"Unique submission ID","type":"string"},"status":{"type":"string","enum":["queued","downloading","transcribing","video_analysis","analyzing","finalizing","completed","failed"]},"error_code":{"nullable":true,"type":"string","enum":["DOWNLOAD_FAILED","DOWNLOAD_ACCESS_DENIED","DOWNLOAD_MEMBERS_ONLY","DOWNLOAD_PRIVATE_VIDEO","DOWNLOAD_GEO_RESTRICTED","DOWNLOAD_TIMEOUT","DOWNLOAD_NETWORK","DOWNLOAD_NO_AUDIO","DOWNLOAD_NOT_AVAILABLE","DOWNLOAD_REMOVED_BY_UPLOADER","DOWNLOAD_PREMIERE_NOT_STARTED","DOWNLOAD_LIVE_IN_PROGRESS","TRANSCRIBE_FAILED","VIDEO_ANALYSIS_FAILED","ANALYZE_FAILED","GENERATE_FAILED","EMPTY_TRANSCRIPT","UPLOAD_CORRUPTED","UNKNOWN"]},"estimated_time":{"description":"Estimated seconds until completion; `null` once processing has started","type":"number","nullable":true},"queue_position":{"description":"Position in the processing queue; `null` once processing has started","type":"number","nullable":true},"is_priority":{"description":"`true` if this submission has priority processing","type":"boolean"},"strategy_id":{"description":"ID of the clipping strategy used; `null` for default settings","type":"string","nullable":true},"timeframe":{"type":"object","required":["start","end"],"properties":{"start":{"description":"Start offset in seconds","type":"number"},"end":{"description":"End offset in seconds","type":"number"}},"description":"Portion of the video that was processed; `null` if the full video was submitted","nullable":true},"credit_cost":{"description":"What this submission is worth in credits. Not what was billed: free usage windows charge nothing","type":"number","nullable":true},"is_reclip":{"description":"`true` if this video was re-submitted — a discounted rate may have applied","type":"boolean"},"clips_count":{"description":"Number of AI-generated clips available; only meaningful when `status` is `completed`","type":"number"},"created_at":{"description":"ISO 8601 timestamp of when this submission was created","type":"string"},"completed_at":{"description":"ISO 8601 timestamp of when this submission finished, or `null` if still running","type":"string","nullable":true}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_NOT_FOUND"]}},"additionalProperties":false}}}}}}},"/clips/{videoId}/submissions/{submissionId}":{"get":{"tags":["Submissions"],"operationId":"getSubmission","summary":"Get submission","description":"Returns the current status of a clipping submission. Poll this endpoint until `status` is `completed` or `failed`.\n\nWe recommend polling every **5–10 seconds**. When `status` is `queued`, use `queue_position` and `estimated_time` to give feedback to your users.\n\nA submission can sit at `downloading` because the SOURCE is not fully published yet — a scheduled premiere, a livestream still on air, or a recording the platform is still processing. In that case `waiting_reason` is set (and `waiting_until` carries the announced start time, when the platform provides one). This is not an error and the submission is not stuck: it resumes on its own once the source becomes available. Surface it to your users instead of a generic \"downloading\", and offer them the option to cancel — `DELETE /v1/clips/{videoId}/submissions/{submissionId}` refunds the credits while `waiting_reason` is set.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","video_id","status","error_code","clips_count","queue_position","estimated_time","waiting_reason","waiting_until","created_at","completed_at"],"properties":{"id":{"description":"Unique submission ID","type":"string"},"video_id":{"description":"ID of the source video","type":"string"},"status":{"type":"string","enum":["queued","downloading","transcribing","video_analysis","analyzing","finalizing","completed","failed"]},"error_code":{"nullable":true,"type":"string","enum":["DOWNLOAD_FAILED","DOWNLOAD_ACCESS_DENIED","DOWNLOAD_MEMBERS_ONLY","DOWNLOAD_PRIVATE_VIDEO","DOWNLOAD_GEO_RESTRICTED","DOWNLOAD_TIMEOUT","DOWNLOAD_NETWORK","DOWNLOAD_NO_AUDIO","DOWNLOAD_NOT_AVAILABLE","DOWNLOAD_REMOVED_BY_UPLOADER","DOWNLOAD_PREMIERE_NOT_STARTED","DOWNLOAD_LIVE_IN_PROGRESS","TRANSCRIBE_FAILED","VIDEO_ANALYSIS_FAILED","ANALYZE_FAILED","GENERATE_FAILED","EMPTY_TRANSCRIPT","UPLOAD_CORRUPTED","UNKNOWN"]},"clips_count":{"description":"Number of AI-generated clips available; only meaningful when `status` is `completed`","type":"number"},"queue_position":{"description":"Position in the processing queue; `null` once processing has started","type":"number","nullable":true},"estimated_time":{"description":"Estimated seconds until completion; `null` once processing has started","type":"number","nullable":true},"waiting_reason":{"description":"Why the submission is waiting on its source: `SOURCE_PREMIERE_SCHEDULED` (scheduled premiere that has not aired), `SOURCE_LIVE_IN_PROGRESS` (livestream still on air), `SOURCE_VOD_PROCESSING` (broadcast ended, platform still publishing the recording).","nullable":true,"type":"string","enum":["SOURCE_PREMIERE_SCHEDULED","SOURCE_LIVE_IN_PROGRESS","SOURCE_VOD_PROCESSING"]},"waiting_until":{"description":"ISO 8601 timestamp the platform announced for the premiere, when known; `null` if there is no announced time","type":"string","nullable":true},"created_at":{"description":"ISO 8601 timestamp of when this submission was created","type":"string"},"completed_at":{"description":"ISO 8601 timestamp of when this submission finished, or `null` if still running","type":"string","nullable":true}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_NOT_FOUND","SUBMISSION_NOT_FOUND"]}},"additionalProperties":false}}}},"410":{"description":"Response for status 410","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_EXPIRED"]}},"additionalProperties":false}}}}}},"delete":{"tags":["Submissions"],"operationId":"deleteSubmission","summary":"Delete submission","description":"Permanently deletes a submission and all its generated clips. This action cannot be undone. A submission still processing is cancelled and its credits refunded.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_FORBIDDEN"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_NOT_FOUND","SUBMISSION_NOT_FOUND"]}}}}}}}}},"/clips/{videoId}/submissions/{submissionId}/retry":{"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Submissions"],"operationId":"retrySubmission","summary":"Retry a failed submission","description":"Runs a `failed` submission again with the exact settings it was created with (strategy, timeframe, template, translation) and returns the NEW submission, charged like `POST /clips`. The failed one stays in the history. Retrying a submission that did not fail answers `409 SUBMISSION_NOT_FAILED`.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id","video_id","status","credits_charged"],"properties":{"id":{"description":"ID of the created submission. Poll it for progress","type":"string"},"video_id":{"description":"ID of the source video","type":"string"},"status":{"type":"string","enum":["queued"]},"credits_charged":{"description":"Credits actually deducted from your balance. `0` when the clip was free, including while this workspace has unlimited usage","type":"number"}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_STRATEGY_OPTIONS","INVALID_TRANSLATE_LANGUAGE","TIMEFRAME_OUT_OF_BOUNDS","TIMEFRAME_TOO_SHORT","VIDEO_TOO_LONG"]}},"additionalProperties":false}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS","CREDIT_CHARGE_FAILED"]},"extra":{"type":"object","required":["credits_needed","current_balance","is_reclip","scope","is_owner"],"properties":{"credits_needed":{"type":"number"},"current_balance":{"type":"number"},"is_reclip":{"type":"boolean"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"type":"boolean"}}}},"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PLATFORM_NOT_SUPPORTED"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_NOT_FOUND","STRATEGY_NOT_FOUND","TEMPLATE_NOT_FOUND","NO_VIDEO_INFO"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_NOT_FAILED","VIDEO_ALREADY_PROCESSING"]}}}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TOO_MANY_PENDING_CLIPS"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CREDIT_CHARGE_ERROR","PROCESSING_ERROR"]}},"additionalProperties":false}}}}}}},"/clips/{videoId}/submissions/{submissionId}/apply_template":{"post":{"x-mcp":{"annotations":{"destructiveHint":true}},"tags":["Clips"],"operationId":"applyTemplate","summary":"Apply template to clips","description":"Asynchronously applies one of your saved templates to all (or a subset of) the generated clips in a submission. The job runs in the background — returns immediately with the number of clips being processed.\n\nOnce a template is applied, each clip gets its own edit settings that you can then render via `POST /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render`.\n\nOnly one batch job can run at a time per account. Returns `429` if another is already running.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["template_id"],"properties":{"template_id":{"description":"ID of the template to apply — must be one of your own templates (see `GET /templates`)","type":"string"},"clip_ids":{"description":"Subset of clip IDs to apply the template to. Omit to apply to all clips in the submission","type":"array","items":{"type":"string"}}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["template_id"],"properties":{"template_id":{"description":"ID of the template to apply — must be one of your own templates (see `GET /templates`)","type":"string"},"clip_ids":{"description":"Subset of clip IDs to apply the template to. Omit to apply to all clips in the submission","type":"array","items":{"type":"string"}}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["template_id"],"properties":{"template_id":{"description":"ID of the template to apply — must be one of your own templates (see `GET /templates`)","type":"string"},"clip_ids":{"description":"Subset of clip IDs to apply the template to. Omit to apply to all clips in the submission","type":"array","items":{"type":"string"}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["clips_count"],"properties":{"clips_count":{"description":"0: no clips matched the filter","type":"number"}},"additionalProperties":false}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["clips_count"],"properties":{"clips_count":{"description":"Number of clips the template is being applied to","type":"number"}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_NOT_FOUND","TEMPLATE_NOT_FOUND"]}},"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["BATCH_ALREADY_RUNNING"]}},"additionalProperties":false}}}}}}},"/clips/{videoId}/submissions/{submissionId}/clips":{"get":{"x-mcp":{"ui":true},"tags":["Clips"],"operationId":"listClips","summary":"List generated clips","description":"Returns the AI-generated highlight clips produced by a completed submission. Each clip includes its timestamp range within the source video, an AI relevance score, and signed URLs for streaming and downloading.\n\nSort by `rating` (default) to surface the most impactful clips first. Download and play URLs are time-limited signed URLs — fetch them fresh when needed rather than caching them long-term.\n\nReturns `410` if the submission has expired. Re-submit the video to generate new clips.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["rating","duration","title","start_time"]}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"min_rating","in":"query","required":false,"schema":{"minimum":0,"maximum":10,"description":"Only return clips with `rating` ≥ this value (0–10)","type":"number"}},{"name":"max_rating","in":"query","required":false,"schema":{"minimum":0,"maximum":10,"description":"Only return clips with `rating` ≤ this value (0–10)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["clips","pagination"],"properties":{"clips":{"type":"array","items":{"type":"object","required":["id","title","description","rating","start_time","end_time","language","created_at","thumbnail_url","download_url","play_url","has_template_applied","edit_id"],"properties":{"id":{"description":"Unique clip ID","type":"string"},"title":{"description":"AI-generated title for this clip","type":"string"},"description":{"description":"AI-generated description explaining why this moment is worth clipping","type":"string"},"rating":{"description":"AI relevance score from 0 to 10 — higher values indicate more engaging or viral-potential content","type":"number"},"start_time":{"description":"Clip start offset within the source video, in seconds","type":"number"},"end_time":{"description":"Clip end offset within the source video, in seconds","type":"number"},"language":{"description":"Detected transcription language (e.g. `en`, `pt`)","type":"string"},"created_at":{"description":"ISO 8601 timestamp of when this clip was generated","type":"string"},"thumbnail_url":{"description":"Signed URL for the clip thumbnail — time-limited, fetch fresh when needed","type":"string"},"download_url":{"description":"Signed URL to download the raw (unrendered) clip — time-limited, fetch fresh when needed","type":"string"},"play_url":{"description":"Signed URL to stream the raw clip — time-limited, fetch fresh when needed","type":"string"},"has_template_applied":{"description":"`true` if a template has been applied to this clip and it is ready to render","type":"boolean"},"edit_id":{"description":"Edit of this clip, once a template was applied or it was rendered. Pass it to `POST /renders` or `POST /posts`","type":"string","nullable":true}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_NOT_FOUND"]}},"additionalProperties":false}}}},"410":{"description":"Response for status 410","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SUBMISSION_EXPIRED"]}},"additionalProperties":false}}}}}}},"/clips/{videoId}/submissions/{submissionId}/clips/{clipId}":{"delete":{"tags":["Clips"],"operationId":"deleteClip","summary":"Delete a clip","description":"Permanently deletes a single generated clip. This action cannot be undone.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clipId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_RESULT_FORBIDDEN"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_NOT_FOUND","SUBMISSION_NOT_FOUND","CLIP_RESULT_NOT_FOUND"]}}}}}}}}},"/clips/{videoId}/submissions/{submissionId}/clips/{clipId}/subtitles":{"get":{"tags":["Clips"],"operationId":"downloadClipSubtitles","summary":"Download a clip's captions","description":"Returns the clip's captions as an SRT file or plain text. When the clip has an edit, its own captions are used (with any fix or translation made there); otherwise the source transcript cut to the clip. Timestamps start at `00:00`, lined up with the clip's own video, so the file can go straight next to the rendered MP4.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clipId","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["srt","txt"]}}],"responses":{"200":{"description":"Response for status 200","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_NOT_FOUND","SUBMISSION_NOT_FOUND","CLIP_RESULT_NOT_FOUND","NO_SUBTITLES"]}}}}}}}}},"/clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render":{"post":{"x-mcp":{"ui":true},"tags":["Renders"],"operationId":"renderClip","summary":"Render a clip","description":"Queues a clip for video rendering. Returns the render `id` you can use to poll status via `GET /renders/{renderId}`.\n\nIf a template has been applied to the clip (see `apply_template`), the rendered video will include all template customisations (captions, effects, cropping, etc.). Otherwise the clip is rendered with default settings.\n\nIf an identical render has already been completed, returns `200` with `from_cache: true` and a ready `download_url`. Returns `409` if the same clip is already being rendered.","security":[{"apiKey":[]}],"parameters":[{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}},{"name":"submissionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clipId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","status","has_watermark","output_resolution","from_cache","download_url"],"properties":{"id":{"description":"ID of the completed cached render","type":"string"},"edit_id":{"description":"Edit this render was produced from. Pass it to `POST /renders` to make a fresh file later, or to `POST /posts` to publish it.","type":"string"},"status":{"type":"string","enum":["completed"]},"has_watermark":{"type":"boolean"},"output_resolution":{"type":"string"},"from_cache":{"type":"boolean","enum":[true]},"download_url":{"description":"Signed URL to download the rendered video","type":"string"}},"additionalProperties":false}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","status","has_watermark","output_resolution","from_cache","download_url"],"properties":{"id":{"description":"ID of the render job. Poll `GET /renders/{renderId}` for status","type":"string"},"edit_id":{"description":"Edit this render was produced from. Pass it to `POST /renders` to make a fresh file later, or to `POST /posts` to publish it.","type":"string"},"status":{"type":"string","enum":["queued","waiting_quality"]},"has_watermark":{"description":"`true` if the rendered video will include a CutPro watermark","type":"boolean"},"output_resolution":{"description":"Output resolution — e.g. `720p` or `1080p`","type":"string"},"from_cache":{"type":"boolean","enum":[false]},"download_url":{"description":"Always `null` while the render is queued — fetch from `GET /renders/{renderId}/download` once completed.","type":"string","nullable":true}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CLIP_RESULT_NOT_FOUND"]}},"additionalProperties":false}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_ALREADY_IN_PROGRESS"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_FAILED","RENDER_SETUP_FAILED"]}},"additionalProperties":false}}}}}}},"/connections":{"get":{"tags":["Connections"],"operationId":"listConnections","summary":"List connections","description":"Returns the active social connections in this workspace — the IDs you pass as `connection_id` when creating a post. Each entry includes the platform, public profile info (username, avatar, bio) and the latest captured audience metrics (followers, posts, likes). Revoked or disconnected accounts are excluded.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 50, max: 100)","type":"number"}},{"name":"platform","in":"query","required":false,"schema":{"type":"string","enum":["youtube","tiktok","instagram","bluesky","threads","linkedin","pinterest","facebook","twitch","kick","discord"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["connections","pagination"],"properties":{"connections":{"type":"array","items":{"type":"object","required":["id","platform","username","avatar_url","biography","followers_count","posts_count","likes_count","is_verified","created_at"],"properties":{"id":{"type":"string"},"platform":{"description":"Source platform, e.g. `youtube`, `tiktok`, `instagram`, `bluesky`, `threads`, `linkedin`, `pinterest`, `facebook`","type":"string"},"username":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"biography":{"type":"string","nullable":true},"followers_count":{"type":"number","nullable":true},"posts_count":{"type":"number","nullable":true},"likes_count":{"type":"number","nullable":true},"is_verified":{"type":"boolean","nullable":true},"created_at":{"type":"string","nullable":true}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}}}}},"/connections/link":{"get":{"tags":["Connections"],"operationId":"getConnectionLink","summary":"Get the link to connect an account","description":"A cut.pro link that opens the sign-in of that network right away, in this workspace. Give it to the user when the account they want to post to is missing from `GET /connections`; once they come back, list the connections again and carry on.","security":[{"apiKey":[]}],"parameters":[{"name":"platform","in":"query","required":true,"schema":{"type":"string","enum":["youtube","tiktok","instagram","bluesky","threads","linkedin","pinterest","facebook","twitch","kick","discord"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}}}}},"/connections/{id}":{"get":{"tags":["Connections"],"operationId":"getConnection","summary":"Get a connection","description":"Returns a single connection by ID, with the latest captured audience metrics.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","platform","username","avatar_url","biography","followers_count","posts_count","likes_count","is_verified","created_at"],"properties":{"id":{"type":"string"},"platform":{"description":"Source platform, e.g. `youtube`, `tiktok`, `instagram`, `bluesky`, `threads`, `linkedin`, `pinterest`, `facebook`","type":"string"},"username":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"biography":{"type":"string","nullable":true},"followers_count":{"type":"number","nullable":true},"posts_count":{"type":"number","nullable":true},"likes_count":{"type":"number","nullable":true},"is_verified":{"type":"boolean","nullable":true},"created_at":{"type":"string","nullable":true}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CONNECTION_NOT_FOUND"]}}}}}}}}},"/monitors":{"get":{"tags":["Monitoring"],"operationId":"listMonitors","summary":"List monitored channels","description":"Returns the channels this workspace monitors, with whether each one is on right now and the settings its clips use.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 50, max: 100)","type":"number"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["live","video"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["monitors","pagination"],"properties":{"monitors":{"type":"array","items":{"type":"object","required":["id","type","platform","username","display_name","avatar_url","enabled","enabled_at","strategy_id","template_id","video_min_duration","video_max_duration","days_of_week","hours_of_day"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["live","video"]},"platform":{"type":"string","enum":["youtube","twitch","kick"]},"username":{"type":"string"},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"enabled_at":{"description":"ISO 8601 timestamp of when the current monitoring period started; `null` while off. Stopping is refused for the first 10 minutes after it.","type":"string","nullable":true},"strategy_id":{"description":"Clipping strategy applied to every clip","type":"string"},"template_id":{"description":"Edit template applied to every clip; `null` = none","type":"string","nullable":true},"video_min_duration":{"description":"`video` only: shorter uploads are skipped, in seconds","type":"number","nullable":true},"video_max_duration":{"description":"`video` only: longer uploads are skipped, in seconds","type":"number","nullable":true},"days_of_week":{"description":"`video` only: days an upload is accepted, 0 = Sunday; empty = every day","type":"array","items":{"type":"number"}},"hours_of_day":{"description":"`video` only: `[from, to]` hour ranges an upload is accepted, in the workspace owner's timezone","type":"array","items":{"type":"array","items":{"type":"number"}}}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}}}},"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Monitoring"],"operationId":"createMonitor","summary":"Monitor a channel","description":"Starts watching a YouTube, Twitch or Kick channel from its URL. A `live` monitor clips each broadcast while it airs, charged per 10-minute batch; a `video` monitor clips each new upload. It is born on unless `enabled` is `false`, which is how a 24/7 stream is set up once and then switched with `start` and `stop`. Refusals: `400`, `402`, `403`, `404`, `409 ALREADY_MONITORING`, and `429` (10 per minute, because it looks the channel up on the platform).","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["channel","type"],"properties":{"channel":{"description":"Channel URL, e.g. `https://www.youtube.com/@handle`, `https://www.twitch.tv/login` or `https://kick.com/slug`","type":"string"},"type":{"type":"string","enum":["live","video"]},"enabled":{"description":"Start monitoring right away. Defaults to `true`","type":"boolean"},"strategy_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a clipping strategy. On create, omit to use the default AI settings","type":"string"},"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of an edit template from `GET /templates`; `null` = none","type":"string","nullable":true},"video_min_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"video_max_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"days_of_week":{"type":"array","items":{"minimum":0,"maximum":6,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":6,"type":"integer"}]}},"hours_of_day":{"type":"array","items":{"minItems":2,"maxItems":2,"type":"array","items":{"minimum":0,"maximum":23,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":23,"type":"integer"}]}}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["channel","type"],"properties":{"channel":{"description":"Channel URL, e.g. `https://www.youtube.com/@handle`, `https://www.twitch.tv/login` or `https://kick.com/slug`","type":"string"},"type":{"type":"string","enum":["live","video"]},"enabled":{"description":"Start monitoring right away. Defaults to `true`","type":"boolean"},"strategy_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a clipping strategy. On create, omit to use the default AI settings","type":"string"},"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of an edit template from `GET /templates`; `null` = none","type":"string","nullable":true},"video_min_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"video_max_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"days_of_week":{"type":"array","items":{"minimum":0,"maximum":6,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":6,"type":"integer"}]}},"hours_of_day":{"type":"array","items":{"minItems":2,"maxItems":2,"type":"array","items":{"minimum":0,"maximum":23,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":23,"type":"integer"}]}}}}}},"multipart/form-data":{"schema":{"type":"object","required":["channel","type"],"properties":{"channel":{"description":"Channel URL, e.g. `https://www.youtube.com/@handle`, `https://www.twitch.tv/login` or `https://kick.com/slug`","type":"string"},"type":{"type":"string","enum":["live","video"]},"enabled":{"description":"Start monitoring right away. Defaults to `true`","type":"boolean"},"strategy_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a clipping strategy. On create, omit to use the default AI settings","type":"string"},"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of an edit template from `GET /templates`; `null` = none","type":"string","nullable":true},"video_min_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"video_max_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"days_of_week":{"type":"array","items":{"minimum":0,"maximum":6,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":6,"type":"integer"}]}},"hours_of_day":{"type":"array","items":{"minItems":2,"maxItems":2,"type":"array","items":{"minimum":0,"maximum":23,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":23,"type":"integer"}]}}}}}}}},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id","type","platform","username","display_name","avatar_url","enabled","enabled_at","strategy_id","template_id","video_min_duration","video_max_duration","days_of_week","hours_of_day"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["live","video"]},"platform":{"type":"string","enum":["youtube","twitch","kick"]},"username":{"type":"string"},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"enabled_at":{"description":"ISO 8601 timestamp of when the current monitoring period started; `null` while off. Stopping is refused for the first 10 minutes after it.","type":"string","nullable":true},"strategy_id":{"description":"Clipping strategy applied to every clip","type":"string"},"template_id":{"description":"Edit template applied to every clip; `null` = none","type":"string","nullable":true},"video_min_duration":{"description":"`video` only: shorter uploads are skipped, in seconds","type":"number","nullable":true},"video_max_duration":{"description":"`video` only: longer uploads are skipped, in seconds","type":"number","nullable":true},"days_of_week":{"description":"`video` only: days an upload is accepted, 0 = Sunday; empty = every day","type":"array","items":{"type":"number"}},"hours_of_day":{"description":"`video` only: `[from, to]` hour ranges an upload is accepted, in the workspace owner's timezone","type":"array","items":{"type":"array","items":{"type":"number"}}}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_CHANNEL_URL","INVALID_DURATION_RANGE"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","current_balance"],"properties":{"credits_needed":{"description":"Credits the next 10-minute batch costs","type":"number"},"current_balance":{"type":"number"}}}}}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["LIVE_CLIPS_NOT_AVAILABLE","PLATFORM_NOT_SUPPORTED"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","CREATOR_NOT_FOUND","STRATEGY_NOT_FOUND","TEMPLATE_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["ALREADY_MONITORING"]}}},{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["MINIMUM_MONITORING_TIME"]},"extra":{"type":"object","required":["remaining_seconds"],"properties":{"remaining_seconds":{"description":"Seconds until stopping is allowed","type":"number"}}}}}]}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["RATE_LIMIT_EXCEEDED"]},"extra":{"type":"object","required":["retry_after"],"properties":{"retry_after":{"description":"Seconds to wait","type":"number"}}}}}}}}}}},"/monitors/{id}":{"get":{"tags":["Monitoring"],"operationId":"getMonitor","summary":"Get a monitored channel","description":"Returns one monitored channel and whether it is on. Monitoring can also turn itself off when the balance runs out.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","type","platform","username","display_name","avatar_url","enabled","enabled_at","strategy_id","template_id","video_min_duration","video_max_duration","days_of_week","hours_of_day"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["live","video"]},"platform":{"type":"string","enum":["youtube","twitch","kick"]},"username":{"type":"string"},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"enabled_at":{"description":"ISO 8601 timestamp of when the current monitoring period started; `null` while off. Stopping is refused for the first 10 minutes after it.","type":"string","nullable":true},"strategy_id":{"description":"Clipping strategy applied to every clip","type":"string"},"template_id":{"description":"Edit template applied to every clip; `null` = none","type":"string","nullable":true},"video_min_duration":{"description":"`video` only: shorter uploads are skipped, in seconds","type":"number","nullable":true},"video_max_duration":{"description":"`video` only: longer uploads are skipped, in seconds","type":"number","nullable":true},"days_of_week":{"description":"`video` only: days an upload is accepted, 0 = Sunday; empty = every day","type":"array","items":{"type":"number"}},"hours_of_day":{"description":"`video` only: `[from, to]` hour ranges an upload is accepted, in the workspace owner's timezone","type":"array","items":{"type":"array","items":{"type":"number"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND"]}},"additionalProperties":false}}}}}},"patch":{"x-mcp":{"annotations":{"openWorldHint":true}},"tags":["Monitoring"],"operationId":"updateMonitor","summary":"Update a monitor","description":"Changes only the fields sent; `null` clears `template_id` and the duration limits. `enabled` follows the same rules as `start` and `stop`. Refusals: `400 INVALID_DURATION_RANGE`, `402`, `403`, `404`, `409 MINIMUM_MONITORING_TIME`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"strategy_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a clipping strategy. On create, omit to use the default AI settings","type":"string"},"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of an edit template from `GET /templates`; `null` = none","type":"string","nullable":true},"video_min_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"video_max_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"days_of_week":{"type":"array","items":{"minimum":0,"maximum":6,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":6,"type":"integer"}]}},"hours_of_day":{"type":"array","items":{"minItems":2,"maxItems":2,"type":"array","items":{"minimum":0,"maximum":23,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":23,"type":"integer"}]}}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"strategy_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a clipping strategy. On create, omit to use the default AI settings","type":"string"},"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of an edit template from `GET /templates`; `null` = none","type":"string","nullable":true},"video_min_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"video_max_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"days_of_week":{"type":"array","items":{"minimum":0,"maximum":6,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":6,"type":"integer"}]}},"hours_of_day":{"type":"array","items":{"minItems":2,"maxItems":2,"type":"array","items":{"minimum":0,"maximum":23,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":23,"type":"integer"}]}}}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"strategy_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a clipping strategy. On create, omit to use the default AI settings","type":"string"},"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of an edit template from `GET /templates`; `null` = none","type":"string","nullable":true},"video_min_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"video_max_duration":{"minimum":1,"maximum":3600,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":3600,"type":"integer"}],"nullable":true},"days_of_week":{"type":"array","items":{"minimum":0,"maximum":6,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":6,"type":"integer"}]}},"hours_of_day":{"type":"array","items":{"minItems":2,"maxItems":2,"type":"array","items":{"minimum":0,"maximum":23,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"maximum":23,"type":"integer"}]}}}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","type","platform","username","display_name","avatar_url","enabled","enabled_at","strategy_id","template_id","video_min_duration","video_max_duration","days_of_week","hours_of_day"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["live","video"]},"platform":{"type":"string","enum":["youtube","twitch","kick"]},"username":{"type":"string"},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"enabled_at":{"description":"ISO 8601 timestamp of when the current monitoring period started; `null` while off. Stopping is refused for the first 10 minutes after it.","type":"string","nullable":true},"strategy_id":{"description":"Clipping strategy applied to every clip","type":"string"},"template_id":{"description":"Edit template applied to every clip; `null` = none","type":"string","nullable":true},"video_min_duration":{"description":"`video` only: shorter uploads are skipped, in seconds","type":"number","nullable":true},"video_max_duration":{"description":"`video` only: longer uploads are skipped, in seconds","type":"number","nullable":true},"days_of_week":{"description":"`video` only: days an upload is accepted, 0 = Sunday; empty = every day","type":"array","items":{"type":"number"}},"hours_of_day":{"description":"`video` only: `[from, to]` hour ranges an upload is accepted, in the workspace owner's timezone","type":"array","items":{"type":"array","items":{"type":"number"}}}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_CHANNEL_URL","INVALID_DURATION_RANGE"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","current_balance"],"properties":{"credits_needed":{"description":"Credits the next 10-minute batch costs","type":"number"},"current_balance":{"type":"number"}}}}}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["LIVE_CLIPS_NOT_AVAILABLE","PLATFORM_NOT_SUPPORTED"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","CREATOR_NOT_FOUND","STRATEGY_NOT_FOUND","TEMPLATE_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["ALREADY_MONITORING"]}}},{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["MINIMUM_MONITORING_TIME"]},"extra":{"type":"object","required":["remaining_seconds"],"properties":{"remaining_seconds":{"description":"Seconds until stopping is allowed","type":"number"}}}}}]}}}}}},"delete":{"tags":["Monitoring"],"operationId":"deleteMonitor","summary":"Stop watching a channel","description":"Removes the monitor and turns it off. Clips it already produced stay in the workspace, and creating a monitor for the same channel and `type` again brings this one back with its history and automations, under the same `id`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND"]}},"additionalProperties":false}}}}}}},"/monitors/{id}/start":{"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Monitoring"],"operationId":"startMonitor","summary":"Start monitoring","description":"Turns monitoring on. For a `live` monitor, a channel that is already live starts being recorded within about a minute, and clips come from what airs from then on; nothing before the start is clipped. Calling it on a monitor that is already on changes nothing and answers `200`. Refusals: `402`, `403`, `404`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","type","platform","username","display_name","avatar_url","enabled","enabled_at","strategy_id","template_id","video_min_duration","video_max_duration","days_of_week","hours_of_day"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["live","video"]},"platform":{"type":"string","enum":["youtube","twitch","kick"]},"username":{"type":"string"},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"enabled_at":{"description":"ISO 8601 timestamp of when the current monitoring period started; `null` while off. Stopping is refused for the first 10 minutes after it.","type":"string","nullable":true},"strategy_id":{"description":"Clipping strategy applied to every clip","type":"string"},"template_id":{"description":"Edit template applied to every clip; `null` = none","type":"string","nullable":true},"video_min_duration":{"description":"`video` only: shorter uploads are skipped, in seconds","type":"number","nullable":true},"video_max_duration":{"description":"`video` only: longer uploads are skipped, in seconds","type":"number","nullable":true},"days_of_week":{"description":"`video` only: days an upload is accepted, 0 = Sunday; empty = every day","type":"array","items":{"type":"number"}},"hours_of_day":{"description":"`video` only: `[from, to]` hour ranges an upload is accepted, in the workspace owner's timezone","type":"array","items":{"type":"array","items":{"type":"number"}}}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_CHANNEL_URL","INVALID_DURATION_RANGE"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","current_balance"],"properties":{"credits_needed":{"description":"Credits the next 10-minute batch costs","type":"number"},"current_balance":{"type":"number"}}}}}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["LIVE_CLIPS_NOT_AVAILABLE","PLATFORM_NOT_SUPPORTED"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","CREATOR_NOT_FOUND","STRATEGY_NOT_FOUND","TEMPLATE_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["ALREADY_MONITORING"]}}},{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["MINIMUM_MONITORING_TIME"]},"extra":{"type":"object","required":["remaining_seconds"],"properties":{"remaining_seconds":{"description":"Seconds until stopping is allowed","type":"number"}}}}}]}}}}}}},"/monitors/{id}/stop":{"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Monitoring"],"operationId":"stopMonitor","summary":"Stop monitoring","description":"Turns monitoring off. No new batch is clipped or charged after this, and a recording in progress stops within about a minute. Monitoring must stay on for at least 10 minutes before it can be stopped: earlier you get `409` with `extra.remaining_seconds`. Calling it on a monitor that is already off changes nothing and answers `200`. Refusals: `404`, `409`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","type","platform","username","display_name","avatar_url","enabled","enabled_at","strategy_id","template_id","video_min_duration","video_max_duration","days_of_week","hours_of_day"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["live","video"]},"platform":{"type":"string","enum":["youtube","twitch","kick"]},"username":{"type":"string"},"display_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true},"enabled":{"type":"boolean"},"enabled_at":{"description":"ISO 8601 timestamp of when the current monitoring period started; `null` while off. Stopping is refused for the first 10 minutes after it.","type":"string","nullable":true},"strategy_id":{"description":"Clipping strategy applied to every clip","type":"string"},"template_id":{"description":"Edit template applied to every clip; `null` = none","type":"string","nullable":true},"video_min_duration":{"description":"`video` only: shorter uploads are skipped, in seconds","type":"number","nullable":true},"video_max_duration":{"description":"`video` only: longer uploads are skipped, in seconds","type":"number","nullable":true},"days_of_week":{"description":"`video` only: days an upload is accepted, 0 = Sunday; empty = every day","type":"array","items":{"type":"number"}},"hours_of_day":{"description":"`video` only: `[from, to]` hour ranges an upload is accepted, in the workspace owner's timezone","type":"array","items":{"type":"array","items":{"type":"number"}}}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_CHANNEL_URL","INVALID_DURATION_RANGE"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","current_balance"],"properties":{"credits_needed":{"description":"Credits the next 10-minute batch costs","type":"number"},"current_balance":{"type":"number"}}}}}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["LIVE_CLIPS_NOT_AVAILABLE","PLATFORM_NOT_SUPPORTED"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","CREATOR_NOT_FOUND","STRATEGY_NOT_FOUND","TEMPLATE_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["ALREADY_MONITORING"]}}},{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["MINIMUM_MONITORING_TIME"]},"extra":{"type":"object","required":["remaining_seconds"],"properties":{"remaining_seconds":{"description":"Seconds until stopping is allowed","type":"number"}}}}}]}}}}}}},"/monitors/{id}/broadcasts":{"get":{"tags":["Monitoring"],"operationId":"listBroadcasts","summary":"List broadcasts of a live monitor","description":"Returns the channel's broadcasts, newest first, each with how many clips this workspace got from it. A broadcast with `ended_at: null` is on air and keeps producing clips every 10 minutes while the monitor is on. Only `live` monitors have broadcasts: a `video` monitor answers `400 INVALID_OBSERVING_TYPE`, and its clips arrive as regular submissions in `GET /clips`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["broadcasts","pagination"],"properties":{"broadcasts":{"type":"array","items":{"type":"object","required":["id","title","category","language","is_mature","tags","started_at","ended_at","clips_count","thumbnail_url","recording_expired"],"properties":{"id":{"description":"The platform's own id for the broadcast","type":"string"},"title":{"type":"string"},"category":{"description":"Game or category the channel set for the broadcast; empty when none","type":"string"},"language":{"type":"string"},"is_mature":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"started_at":{"description":"ISO 8601 timestamp of when the broadcast went on air","type":"string"},"ended_at":{"description":"ISO 8601 timestamp of when it went off air; `null` while it is still live","type":"string","nullable":true},"clips_count":{"description":"Clips this workspace got from the broadcast","type":"number"},"thumbnail_url":{"type":"string","nullable":true},"recording_expired":{"description":"`true` once the recording was purged: its clips can no longer be listed or rendered","type":"boolean"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_OBSERVING_TYPE"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND"]}},"additionalProperties":false}}}}}}},"/monitors/{id}/broadcasts/{broadcastId}/clips":{"get":{"tags":["Monitoring"],"operationId":"listBroadcastClips","summary":"List clips of a broadcast","description":"Returns the clips this workspace got from one broadcast, best rated first by default. While the broadcast is on air, new clips land every 10 minutes, so poll this list rather than waiting for the broadcast to end.\n\nA clip with an `edit_id` is ready to render or post; one without it renders with the default layout through `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`. Returns `410` once the recording was purged.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}},{"name":"broadcastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["rating","duration","title","created_at"]}},{"name":"order","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"]}},{"name":"min_rating","in":"query","required":false,"schema":{"minimum":0,"maximum":10,"description":"Only clips with `rating` at or above this value","type":"number"}},{"name":"max_rating","in":"query","required":false,"schema":{"minimum":0,"maximum":10,"description":"Only clips with `rating` at or below this value","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["clips","pagination"],"properties":{"clips":{"type":"array","items":{"type":"object","required":["id","title","description","rating","started_at","ended_at","duration","thumbnail_url","play_url","edit_id","render_id","rendering"],"properties":{"id":{"type":"string"},"title":{"description":"AI-generated title","type":"string"},"description":{"description":"AI-generated explanation of why the moment is worth clipping","type":"string","nullable":true},"rating":{"description":"AI relevance score from 0 to 10","type":"number"},"started_at":{"description":"ISO 8601 timestamp of when the moment started airing","type":"string"},"ended_at":{"description":"ISO 8601 timestamp of when the moment finished airing","type":"string"},"duration":{"description":"Length of the clip, in seconds","type":"number"},"thumbnail_url":{"description":"Signed URL, time-limited: fetch fresh when needed","type":"string","nullable":true},"play_url":{"description":"Signed URL to stream the raw clip, time-limited: fetch fresh when needed","type":"string"},"edit_id":{"description":"Edit of this clip, once a template was applied (by the monitor or `apply_template`) or it was rendered. Pass it to `POST /renders` or `POST /posts`","type":"string","nullable":true},"render_id":{"description":"Latest finished render that still matches the edit; download it from `GET /renders/{renderId}/download`","type":"string","nullable":true},"rendering":{"description":"`true` while a render of this clip is queued or running","type":"boolean"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_OBSERVING_TYPE"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","STREAM_NOT_FOUND"]}},"additionalProperties":false}}}},"410":{"description":"Response for status 410","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RECORDING_EXPIRED"]}},"additionalProperties":false}}}}}}},"/monitors/{id}/broadcasts/{broadcastId}/clips/apply_template":{"post":{"x-mcp":{"annotations":{"destructiveHint":true}},"tags":["Monitoring"],"operationId":"applyBroadcastTemplate","summary":"Apply template to broadcast clips","description":"Applies one of your templates to every clip of a broadcast, or to the `clip_ids` given, in the background. Each clip's `edit_id` shows up in `GET /monitors/{id}/broadcasts/{broadcastId}/clips` as it is done. To template every future clip instead, set `template_id` on the monitor. Only one batch runs at a time per account: another one answers `429`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}},{"name":"broadcastId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["template_id"],"properties":{"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a template from `GET /templates`","type":"string"},"clip_ids":{"description":"Subset of clip IDs. Omit to apply to every clip of the broadcast","type":"array","items":{"type":"string"}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["template_id"],"properties":{"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a template from `GET /templates`","type":"string"},"clip_ids":{"description":"Subset of clip IDs. Omit to apply to every clip of the broadcast","type":"array","items":{"type":"string"}}}}},"multipart/form-data":{"schema":{"type":"object","required":["template_id"],"properties":{"template_id":{"pattern":"^[0-9]{1,19}$","description":"ID of a template from `GET /templates`","type":"string"},"clip_ids":{"description":"Subset of clip IDs. Omit to apply to every clip of the broadcast","type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["clips_count"],"properties":{"clips_count":{"description":"0: no clips matched","type":"number"}}}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["clips_count"],"properties":{"clips_count":{"description":"Number of clips the template is being applied to","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_OBSERVING_TYPE"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","TEMPLATE_NOT_FOUND"]}}}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["BATCH_ALREADY_RUNNING"]}}}}}}}}},"/monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render":{"post":{"tags":["Renders"],"operationId":"renderBroadcastClip","summary":"Render a broadcast clip","description":"Queues a live clip for rendering and returns the render `id` to poll with `GET /renders/{renderId}`. The clip renders with its template when one was applied, otherwise with the default layout. If an identical render is already in storage, returns `200` with `from_cache: true` and a ready `download_url`; `409` if the same clip is already rendering.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"pattern":"^[0-9]{1,19}$","type":"string"}},{"name":"broadcastId","in":"path","required":true,"schema":{"type":"string"}},{"name":"clipId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","status","has_watermark","output_resolution","from_cache","download_url"],"properties":{"id":{"description":"ID of the completed cached render","type":"string"},"edit_id":{"description":"Edit this render was produced from. Pass it to `POST /renders` to make a fresh file later, or to `POST /posts` to publish it.","type":"string"},"status":{"type":"string","enum":["completed"]},"has_watermark":{"type":"boolean"},"output_resolution":{"type":"string"},"from_cache":{"type":"boolean","enum":[true]},"download_url":{"description":"Signed URL to download the rendered video","type":"string"}},"additionalProperties":false}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","status","has_watermark","output_resolution","from_cache","download_url"],"properties":{"id":{"description":"ID of the render job. Poll `GET /renders/{renderId}` for status.","type":"string"},"edit_id":{"description":"Edit this render was produced from. Pass it to `POST /renders` to make a fresh file later, or to `POST /posts` to publish it.","type":"string"},"status":{"type":"string","enum":["queued","waiting_quality"]},"has_watermark":{"type":"boolean"},"output_resolution":{"type":"string"},"from_cache":{"type":"boolean","enum":[false]},"download_url":{"description":"Always `null` while the render is queued. Fetch it from `GET /renders/{renderId}/download` once completed.","type":"string","nullable":true}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_OBSERVING_TYPE"]}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MONITORING_NOT_FOUND","CLIP_NOT_FOUND","EDIT_NOT_FOUND"]}},"additionalProperties":false}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_ALREADY_IN_PROGRESS"]}},"additionalProperties":false}}}},"410":{"description":"Response for status 410","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RECORDING_EXPIRED"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_FAILED"]}},"additionalProperties":false}}}}}}},"/posts":{"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Posts"],"operationId":"createPost","summary":"Create a post","description":"Creates a multi-platform post for one or more edited clips. Each entry under `videos` references an `edit_id` (the rendered or apply_template'd clip) plus a list of target connections with platform-specific metadata.\n\n`metadata` is the only part of this API that keeps each network's own field names (`privacyLevel`, `categoryId`, `privacyStatus`): they are forwarded to the network as-is, so renaming them here would only hide what actually goes out.\n\nPass `scheduled_at` (ISO 8601, must be in the future) to schedule the post; omit it to publish immediately.\n\nImmediate posts kick off rendering + publishing in the background — poll `GET /posts/{id}` until every item is `completed` or `failed`. Failed items can be retried with `POST /posts/{id}/items/{itemId}/retry`.\n\nNetworks still rolling out reject the whole request with `PLATFORM_UNAVAILABLE` before anything is created.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["videos"],"properties":{"videos":{"minItems":1,"description":"List of clips to publish. Each item has an `edit_id` plus per-target metadata.","type":"array","items":{"type":"object","required":["edit_id","targets"],"properties":{"edit_id":{"description":"Edit to publish: the `edit_id` a render returns.","type":"string"},"targets":{"minItems":1,"type":"array","items":{"type":"object","required":["connection_id","metadata"],"properties":{"connection_id":{"description":"Connection to publish to, from `GET /connections`.","type":"string"},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","required":["title","channel"],"properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","required":["title","categoryId","privacyStatus"],"properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","required":["title","privacyLevel"],"properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","required":["text"],"properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","required":["boardId","title","description"],"properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","required":["title"],"properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}}}}}}}}},"scheduled_at":{"description":"ISO 8601 future timestamp to schedule the post. Omit for immediate publish.","type":"string","nullable":true}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["videos"],"properties":{"videos":{"minItems":1,"description":"List of clips to publish. Each item has an `edit_id` plus per-target metadata.","type":"array","items":{"type":"object","required":["edit_id","targets"],"properties":{"edit_id":{"description":"Edit to publish: the `edit_id` a render returns.","type":"string"},"targets":{"minItems":1,"type":"array","items":{"type":"object","required":["connection_id","metadata"],"properties":{"connection_id":{"description":"Connection to publish to, from `GET /connections`.","type":"string"},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","required":["title","channel"],"properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","required":["title","categoryId","privacyStatus"],"properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","required":["title","privacyLevel"],"properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","required":["text"],"properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","required":["boardId","title","description"],"properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","required":["title"],"properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}}}}}}}}},"scheduled_at":{"description":"ISO 8601 future timestamp to schedule the post. Omit for immediate publish.","type":"string","nullable":true}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["videos"],"properties":{"videos":{"minItems":1,"description":"List of clips to publish. Each item has an `edit_id` plus per-target metadata.","type":"array","items":{"type":"object","required":["edit_id","targets"],"properties":{"edit_id":{"description":"Edit to publish: the `edit_id` a render returns.","type":"string"},"targets":{"minItems":1,"type":"array","items":{"type":"object","required":["connection_id","metadata"],"properties":{"connection_id":{"description":"Connection to publish to, from `GET /connections`.","type":"string"},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","required":["title","channel"],"properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","required":["title","categoryId","privacyStatus"],"properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","required":["title","privacyLevel"],"properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","required":["text"],"properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","required":["boardId","title","description"],"properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","required":["title"],"properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}}}}}}}}},"scheduled_at":{"description":"ISO 8601 future timestamp to schedule the post. Omit for immediate publish.","type":"string","nullable":true}},"additionalProperties":false}}}},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id","item_count","scheduled_at","status"],"properties":{"id":{"type":"string"},"item_count":{"type":"number"},"scheduled_at":{"type":"string","nullable":true},"status":{"type":"string","enum":["pending","processing"]}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_SCHEDULED_AT","INVALID_METADATA","INVALID_CONNECTIONS","PLATFORM_UNAVAILABLE"]},"extra":{"type":"object","properties":{"field":{"description":"Metadata path that failed validation, e.g. `youtube.categoryId`. Only on `INVALID_METADATA`.","type":"string"},"platform":{"description":"Network that is not open for publishing yet. Only on `PLATFORM_UNAVAILABLE`.","type":"string"},"invalid_connections":{"description":"Connection ids that are unknown, revoked or cannot publish video.","type":"array","items":{"type":"string"}}}}},"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["DAILY_LIMIT_EXCEEDED"]},"extra":{"type":"object","required":["platform","connection_id","daily_limit","used_today","batch_count"],"properties":{"platform":{"type":"string"},"connection_id":{"type":"string"},"daily_limit":{"type":"number"},"used_today":{"type":"number"},"batch_count":{"description":"Items this request would add to that account on that day","type":"number"}}}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["EDITS_NOT_FOUND"]},"extra":{"type":"object","required":["invalid_edits"],"properties":{"invalid_edits":{"type":"array","items":{"type":"string"}}}}},"additionalProperties":false}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["DUPLICATE_POST"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["UNKNOWN_ERROR"]}},"additionalProperties":false}}}}}},"get":{"tags":["Posts"],"operationId":"listPosts","summary":"List posts","description":"Returns a paginated list of posts in this workspace, newest first. Each post includes its items with current status and error codes.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","processing","completed","partial","failed","cancelled"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["posts","pagination"],"properties":{"posts":{"type":"array","items":{"type":"object","required":["id","status","scheduled_at","created_at","updated_at","item_count","items"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","partial","failed","cancelled"]},"scheduled_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"item_count":{"type":"number"},"items":{"type":"array","items":{"type":"object","required":["id","platform","connection_id","edit_id","render_id","status","published_url","error_code","metadata","created_at","updated_at","posted_at"],"properties":{"id":{"type":"string"},"platform":{"type":"string","enum":["youtube","tiktok","instagram","bluesky","threads","linkedin","pinterest","facebook","carmedia","twitter","telegram","mastodon","discordserver","dailymotion","tumblr","slack"]},"connection_id":{"type":"string"},"edit_id":{"type":"string","nullable":true},"render_id":{"description":"Render backing this item. `null` once the render is gone (expired, failed or cancelled): there is no file left to download.","type":"string","nullable":true},"status":{"type":"string","enum":["pending","rendering","publishing","completed","failed"]},"published_url":{"type":"string","nullable":true},"error_code":{"type":"string","nullable":true},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}},"description":"Publishing metadata of this item (title, caption/description and per-network options), in the same shape accepted by `POST /posts`.","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"posted_at":{"type":"string","nullable":true}}}}},"additionalProperties":false}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}}}}},"/posts/{id}":{"get":{"tags":["Posts"],"operationId":"getPost","summary":"Get a post","description":"Returns full status of a post including every item. Poll this endpoint to track immediate posts through `pending → rendering → publishing → completed`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","status","scheduled_at","created_at","updated_at","item_count","items"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","partial","failed","cancelled"]},"scheduled_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"item_count":{"type":"number"},"items":{"type":"array","items":{"type":"object","required":["id","platform","connection_id","edit_id","render_id","status","published_url","error_code","metadata","created_at","updated_at","posted_at"],"properties":{"id":{"type":"string"},"platform":{"type":"string","enum":["youtube","tiktok","instagram","bluesky","threads","linkedin","pinterest","facebook","carmedia","twitter","telegram","mastodon","discordserver","dailymotion","tumblr","slack"]},"connection_id":{"type":"string"},"edit_id":{"type":"string","nullable":true},"render_id":{"description":"Render backing this item. `null` once the render is gone (expired, failed or cancelled): there is no file left to download.","type":"string","nullable":true},"status":{"type":"string","enum":["pending","rendering","publishing","completed","failed"]},"published_url":{"type":"string","nullable":true},"error_code":{"type":"string","nullable":true},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}},"description":"Publishing metadata of this item (title, caption/description and per-network options), in the same shape accepted by `POST /posts`.","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"posted_at":{"type":"string","nullable":true}}}}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["POST_NOT_FOUND"]}},"additionalProperties":false}}}}}},"delete":{"x-mcp":{"annotations":{"openWorldHint":true}},"tags":["Posts"],"operationId":"cancelPost","summary":"Cancel a post","description":"Cancels every item of the post that is not public yet, so none of them will publish. Already-published items remain live on the destination platforms. Nothing is erased: CutPro keeps the record of the cancellation, and a fully cancelled post no longer appears in listings.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"}}},"patch":{"x-mcp":{"annotations":{"openWorldHint":true}},"tags":["Posts"],"operationId":"updatePost","summary":"Update a post","description":"Updates a post that is still pending. Two things can change:\n\n• `scheduled_at` — reschedule (must be at least 1 minute in the future) or set to `null` to publish immediately. Only allowed while every item is still in `pending` state.\n\n• `items` — replace the set of pending items. Items with `item_id` are updated in place, items without are inserted, and pending items not present in the body are deleted. Items that already finished publishing are never touched.\n\nAt least one of `scheduled_at` or `items` must be provided.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scheduled_at":{"description":"ISO 8601 future timestamp, or `null` to clear the schedule and publish immediately.","type":"string","nullable":true},"items":{"minItems":1,"type":"array","items":{"type":"object","required":["edit_id","connection_id","metadata"],"properties":{"item_id":{"description":"Existing pending item ID. Omit to insert a new item.","type":"string"},"edit_id":{"type":"string"},"connection_id":{"type":"string"},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","required":["title","channel"],"properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","required":["title","categoryId","privacyStatus"],"properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","required":["title","privacyLevel"],"properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","required":["text"],"properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","required":["boardId","title","description"],"properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","required":["title"],"properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}}}}}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"scheduled_at":{"description":"ISO 8601 future timestamp, or `null` to clear the schedule and publish immediately.","type":"string","nullable":true},"items":{"minItems":1,"type":"array","items":{"type":"object","required":["edit_id","connection_id","metadata"],"properties":{"item_id":{"description":"Existing pending item ID. Omit to insert a new item.","type":"string"},"edit_id":{"type":"string"},"connection_id":{"type":"string"},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","required":["title","channel"],"properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","required":["title","categoryId","privacyStatus"],"properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","required":["title","privacyLevel"],"properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","required":["text"],"properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","required":["boardId","title","description"],"properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","required":["title"],"properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}}}}}}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"scheduled_at":{"description":"ISO 8601 future timestamp, or `null` to clear the schedule and publish immediately.","type":"string","nullable":true},"items":{"minItems":1,"type":"array","items":{"type":"object","required":["edit_id","connection_id","metadata"],"properties":{"item_id":{"description":"Existing pending item ID. Omit to insert a new item.","type":"string"},"edit_id":{"type":"string"},"connection_id":{"type":"string"},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","required":["title","channel"],"properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","required":["channelId"],"properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","required":["title","categoryId","privacyStatus"],"properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","required":["title","privacyLevel"],"properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","required":["text"],"properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","required":["boardId","title","description"],"properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","required":["title"],"properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}}}}}}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","status","scheduled_at","created_at","updated_at","item_count","items"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","partial","failed","cancelled"]},"scheduled_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"item_count":{"type":"number"},"items":{"type":"array","items":{"type":"object","required":["id","platform","connection_id","edit_id","render_id","status","published_url","error_code","metadata","created_at","updated_at","posted_at"],"properties":{"id":{"type":"string"},"platform":{"type":"string","enum":["youtube","tiktok","instagram","bluesky","threads","linkedin","pinterest","facebook","carmedia","twitter","telegram","mastodon","discordserver","dailymotion","tumblr","slack"]},"connection_id":{"type":"string"},"edit_id":{"type":"string","nullable":true},"render_id":{"description":"Render backing this item. `null` once the render is gone (expired, failed or cancelled): there is no file left to download.","type":"string","nullable":true},"status":{"type":"string","enum":["pending","rendering","publishing","completed","failed"]},"published_url":{"type":"string","nullable":true},"error_code":{"type":"string","nullable":true},"metadata":{"type":"object","properties":{"tumblr":{"type":"object","properties":{"title":{"maxLength":300,"type":"string"},"text":{"maxLength":4096,"type":"string"},"tags":{"maxItems":30,"type":"array","items":{"maxLength":140,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"slack":{"type":"object","properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":4000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"dailymotion":{"type":"object","properties":{"title":{"minLength":1,"maxLength":255,"type":"string"},"description":{"maxLength":3000,"type":"string"},"channel":{"minLength":1,"maxLength":32,"type":"string"},"tags":{"maxItems":150,"type":"array","items":{"maxLength":50,"type":"string"}},"visibility":{"type":"string","enum":["public","private"]},"coverImageId":{"maxLength":64,"type":"string"}}},"telegram":{"type":"object","properties":{"text":{"maxLength":4096,"type":"string"},"silent":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"mastodon":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"visibility":{"type":"string","enum":["public","unlisted","private"]},"sensitive":{"type":"boolean"},"spoilerText":{"maxLength":200,"type":"string"},"language":{"minLength":2,"maxLength":8,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"discordserver":{"type":"object","properties":{"channelId":{"minLength":1,"maxLength":32,"type":"string"},"text":{"maxLength":2000,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"youtube":{"type":"object","properties":{"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"maxLength":5000,"type":"string"},"categoryId":{"type":"string"},"privacyStatus":{"type":"string","enum":["public","private","unlisted"]},"license":{"type":"string","enum":["youtube","creativeCommon"]},"embeddable":{"type":"boolean"},"publicStatsViewable":{"type":"boolean"},"madeForKids":{"type":"boolean"},"selfDeclaredMadeForKids":{"type":"boolean"},"tags":{"maxItems":500,"type":"array","items":{"maxLength":30,"type":"string"}},"notifySubscribers":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"}}},"tiktok":{"type":"object","properties":{"title":{"minLength":1,"maxLength":2200,"type":"string"},"photoTitle":{"maxLength":90,"type":"string"},"privacyLevel":{"type":"string","enum":["PUBLIC_TO_EVERYONE","MUTUAL_FOLLOW_FRIENDS","FOLLOWER_OF_CREATOR","SELF_ONLY"]},"disableDuet":{"type":"boolean"},"disableComment":{"type":"boolean"},"disableStitch":{"type":"boolean"},"coverImageId":{"maxLength":64,"type":"string"},"brandContentToggle":{"type":"boolean"},"brandOrganicToggle":{"type":"boolean"},"isAigc":{"type":"boolean"}}},"instagram":{"type":"object","properties":{"caption":{"maxLength":2200,"type":"string"},"captionGroups":{"type":"object","properties":{"hook":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"emoji":{"maxItems":30,"type":"array","items":{"maxLength":40,"type":"string"}},"body":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"cta":{"maxItems":30,"type":"array","items":{"maxLength":500,"type":"string"}},"hashtags":{"maxItems":30,"type":"array","items":{"maxLength":100,"type":"string"}}}},"captionParts":{"maxItems":30,"type":"array","items":{"maxLength":2200,"type":"string"}},"captionAutoEnvelope":{"type":"boolean"},"captionTemplate":{"maxLength":8000,"type":"string"},"coverUrl":{"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"thumbOffset":{"minimum":0,"type":"number"},"shareToFeed":{"type":"boolean"},"audioName":{"type":"string"},"collaborators":{"maxItems":3,"type":"array","items":{"type":"string"}},"userTags":{"type":"array","items":{"type":"string"}},"trialReel":{"type":"string","enum":["off","MANUAL","SS_PERFORMANCE"]},"firstComment":{"maxLength":2200,"type":"string"}}},"facebook":{"type":"object","properties":{"description":{"maxLength":63206,"type":"string"},"postType":{"type":"string","enum":["reel","feed"]},"link":{"maxLength":2048,"type":"string"},"videoTitle":{"maxLength":255,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":8000,"type":"string"}}},"bluesky":{"type":"object","properties":{"text":{"maxLength":300,"type":"string"},"languages":{"maxItems":3,"type":"array","items":{"minLength":2,"maxLength":8,"type":"string"}},"coverImageId":{"maxLength":64,"type":"string"}}},"threads":{"type":"object","properties":{"text":{"maxLength":500,"type":"string"},"replyControl":{"type":"string","enum":["everyone","accounts_you_follow","mentioned_only"]},"coverImageId":{"maxLength":64,"type":"string"},"firstComment":{"maxLength":500,"type":"string"}}},"linkedin":{"type":"object","properties":{"text":{"minLength":1,"maxLength":3000,"type":"string"},"visibility":{"type":"string","enum":["PUBLIC","CONNECTIONS"]},"coverImageId":{"maxLength":64,"type":"string"}}},"pinterest":{"type":"object","properties":{"boardId":{"minLength":1,"type":"string"},"title":{"minLength":1,"maxLength":100,"type":"string"},"description":{"minLength":1,"maxLength":800,"type":"string"},"link":{"maxLength":2048,"type":"string"},"coverImageUrl":{"maxLength":2048,"type":"string"},"coverImageId":{"maxLength":64,"type":"string"}}},"carmedia":{"type":"object","properties":{"title":{"minLength":1,"maxLength":200,"type":"string"},"description":{"maxLength":2000,"type":"string"},"visibility":{"type":"string","enum":["public"]},"coverImageId":{"maxLength":64,"type":"string"}}},"twitter":{"type":"object","properties":{"text":{"maxLength":280,"type":"string"},"replySettings":{"type":"string","enum":["everyone","following","mentionedUsers"]},"coverImageId":{"maxLength":64,"type":"string"}}}},"description":"Publishing metadata of this item (title, caption/description and per-network options), in the same shape accepted by `POST /posts`.","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"},"posted_at":{"type":"string","nullable":true}}}}},"additionalProperties":false}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_SCHEDULED_AT","SCHEDULE_LOCKED","ITEM_NOT_EDITABLE","INVALID_CONNECTIONS","ITEMS_EMPTY","NOTHING_TO_UPDATE"]},"extra":{"type":"object","properties":{"item_id":{"description":"Item that is no longer pending. Only on `ITEM_NOT_EDITABLE`.","type":"string"},"invalid_connections":{"type":"array","items":{"type":"string"}}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["POST_NOT_FOUND","EDITS_NOT_FOUND"]},"extra":{"type":"object","required":["invalid_edits"],"properties":{"invalid_edits":{"type":"array","items":{"type":"string"}}}}}}}}}}}},"/posts/{id}/publish":{"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Posts"],"operationId":"publishPost","summary":"Trigger publish","description":"Forces the publishing pipeline to run for a post that is currently `pending`, `failed`, or stuck. Useful for scheduled posts you want to publish early, or to nudge a post whose worker missed its window.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","processed","successful_items","failed_items"],"properties":{"id":{"type":"string"},"processed":{"type":"boolean"},"successful_items":{"type":"number"},"failed_items":{"type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["NO_PENDING_ITEMS"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["POST_NOT_FOUND"]}}}}}}}}},"/posts/{id}/items/{itemId}/retry":{"post":{"x-mcp":{"annotations":{"destructiveHint":true,"openWorldHint":true}},"tags":["Posts"],"operationId":"retryPostItem","summary":"Retry a failed item","description":"Re-queues a `failed` item for publishing. Its `error_code` and previous `render_id` are cleared. Only items currently in `failed` state can be retried.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","status"],"properties":{"id":{"description":"The re-queued item.","type":"string"},"status":{"type":"string","enum":["pending"]}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["ITEM_NOT_FAILED"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["POST_NOT_FOUND","ITEM_NOT_FOUND"]}}}}}}}}},"/posts/{id}/items/{itemId}":{"delete":{"x-mcp":{"annotations":{"openWorldHint":true}},"tags":["Posts"],"operationId":"deletePostItem","summary":"Delete a post item","description":"Cancels a single `pending`, `rendering` or `failed` item so it never publishes. A `rendering` item also aborts its render job when no other item still needs it. An item already `completed` is deleted from the destination network first, and only on networks that allow it. The network's refusal comes back as a `400` and nothing changes here. An item in `publishing` cannot be cancelled: the media is already on its way.\n\nCancelled items stop appearing in listings, and CutPro keeps the record. When nothing of the parent post is left, `post_deleted: true` is returned.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"itemId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","post_deleted"],"properties":{"id":{"description":"The removed item.","type":"string"},"post_deleted":{"description":"`true` when that was the last item and the whole post is now cancelled.","type":"boolean"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["ITEM_NOT_REMOVABLE","PUBLISHED_ID_MISSING","CONNECTION_NOT_FOUND","CONNECTION_INVALID","DELETE_NOT_SUPPORTED","DELETE_FAILED","DELETE_LIMIT_REACHED","PERMISSION_MISSING"]}}}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["POST_FORBIDDEN"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["POST_NOT_FOUND","ITEM_NOT_FOUND"]}}}}}}}}},"/renders/limits":{"get":{"tags":["Renders"],"operationId":"getRenderLimits","summary":"Get render quota","description":"Returns the workspace's current render usage and plan-level render limits. Use this before kicking off a render to avoid being throttled — if `usage.total_pending >= usage.max_concurrent`, a new render will be rejected with `429`.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["usage","plan"],"properties":{"usage":{"type":"object","required":["active_count","queued_count","total_pending","max_concurrent"],"properties":{"active_count":{"description":"Renders currently encoding","type":"number"},"queued_count":{"description":"Renders waiting in the queue","type":"number"},"total_pending":{"description":"active + queued","type":"number"},"max_concurrent":{"description":"Max simultaneous renders allowed by the workspace's plan","type":"number"}}},"plan":{"type":"object","required":["video_quality","watermark","priority_processing","max_concurrent_renders","render_expiry_hours"],"properties":{"video_quality":{"description":"Maximum output resolution, e.g. `720p` or `1080p`","type":"string"},"watermark":{"description":"`true` if rendered videos carry a CutPro watermark","type":"boolean"},"priority_processing":{"description":"`true` if this workspace is on the priority render queue","type":"boolean"},"max_concurrent_renders":{"type":"number"},"render_expiry_hours":{"description":"Hours after which a completed render's file is purged from storage","type":"number"}}}},"additionalProperties":false}}}}}}},"/renders":{"post":{"tags":["Renders"],"operationId":"createRender","summary":"Render an edit","description":"Renders an edit you already own and returns the render `id` to poll with `GET /renders/{renderId}`. This is how you get a fresh MP4 of a clip you published months ago: the edit never expires, so re-rendering it always works, even after the rendered file itself was purged.\n\nIf an identical render is already sitting in storage, returns `200` with `from_cache: true` and a ready `download_url`. Returns `409` if the same edit is already rendering.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["edit_id"],"properties":{"edit_id":{"description":"Edit to render: the `edit_id` of a post item, of a clip render, or of an earlier render of your own.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["edit_id"],"properties":{"edit_id":{"description":"Edit to render: the `edit_id` of a post item, of a clip render, or of an earlier render of your own.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["edit_id"],"properties":{"edit_id":{"description":"Edit to render: the `edit_id` of a post item, of a clip render, or of an earlier render of your own.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","status","has_watermark","output_resolution","from_cache","download_url"],"properties":{"id":{"description":"ID of the completed cached render","type":"string"},"edit_id":{"description":"Edit this render was produced from. Pass it to `POST /renders` to make a fresh file later, or to `POST /posts` to publish it.","type":"string"},"status":{"type":"string","enum":["completed"]},"has_watermark":{"type":"boolean"},"output_resolution":{"type":"string"},"from_cache":{"type":"boolean","enum":[true]},"download_url":{"description":"Signed URL to download the rendered video","type":"string"}},"additionalProperties":false}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","status","has_watermark","output_resolution","from_cache","download_url"],"properties":{"id":{"description":"ID of the render job. Poll `GET /renders/{renderId}` for status.","type":"string"},"edit_id":{"description":"Edit this render was produced from. Pass it to `POST /renders` to make a fresh file later, or to `POST /posts` to publish it.","type":"string"},"status":{"type":"string","enum":["queued","waiting_quality"]},"has_watermark":{"type":"boolean"},"output_resolution":{"type":"string"},"from_cache":{"type":"boolean","enum":[false]},"download_url":{"description":"Always `null` while the render is queued. Fetch it from `GET /renders/{renderId}/download` once completed.","type":"string","nullable":true}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["EDIT_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_ALREADY_IN_PROGRESS"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_FAILED"]}},"additionalProperties":false}}}}}},"get":{"tags":["Renders"],"operationId":"listRenders","summary":"List renders","description":"Returns a paginated list of all your render jobs, newest first. Filter by `status` to focus on processing, completed, or failed renders.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["processing","completed","failed","expired"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["renders","pagination"],"properties":{"renders":{"type":"array","items":{"type":"object","required":["id","edit_id","name","status","progress","output_resolution","created_at","started_at","completed_at"],"properties":{"id":{"description":"Unique render ID","type":"string"},"edit_id":{"description":"Edit this render was produced from. It never expires: pass it to `POST /renders` for a fresh file, or to `POST /posts` to publish it.","type":"string"},"name":{"description":"Name of the edit / clip being rendered","type":"string","nullable":true},"status":{"type":"string","enum":["queued","active","completed","failed","cancelled","expired","waiting_quality"]},"progress":{"description":"Render progress from 0 to 100","type":"number"},"output_resolution":{"description":"Output resolution, e.g. `720p` or `1080p`","type":"string","nullable":true},"created_at":{"description":"ISO 8601 timestamp of when the render was queued","type":"string"},"started_at":{"description":"ISO 8601 timestamp of when rendering started","type":"string","nullable":true},"completed_at":{"description":"ISO 8601 timestamp of when the render finished","type":"string","nullable":true}},"additionalProperties":false}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}}}}},"/renders/bulk-download":{"post":{"tags":["Renders"],"operationId":"createBulkDownload","summary":"Start a bulk download","description":"Packages a set of completed renders into a single zip file. Returns the job `id` immediately, then poll `GET /renders/bulk-download/{jobId}` until `status` is `completed`, then download the zip from the returned URL.\n\nUp to 500 renders per job. Renders that don't belong to your workspace are silently skipped; the job fails with `NO_VALID_RENDERS` if none survive that filter.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["render_ids"],"properties":{"render_ids":{"description":"Render IDs to include in the zip.","type":"array","items":{"type":"string"}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["render_ids"],"properties":{"render_ids":{"description":"Render IDs to include in the zip.","type":"array","items":{"type":"string"}}}}},"multipart/form-data":{"schema":{"type":"object","required":["render_ids"],"properties":{"render_ids":{"description":"Render IDs to include in the zip.","type":"array","items":{"type":"string"}}}}}}},"responses":{"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["NO_RENDERS_SELECTED","TOO_MANY_RENDERS"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["NO_VALID_RENDERS"]}}}}}}}}},"/renders/bulk-download/{jobId}":{"get":{"tags":["Renders"],"operationId":"getBulkDownload","summary":"Get bulk download status","description":"Returns the current state of a bulk download job. Poll every 5–10 seconds until `status` is `completed`. Once complete, `download_url` is a signed URL valid for one hour; the underlying file is purged once `expires_at` passes.","security":[{"apiKey":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","status","progress","render_count","file_size","error_code","created_at","completed_at","expires_at","download_url","filename"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["queued","active","completed","failed"]},"progress":{"description":"0 to 100","type":"number"},"render_count":{"type":"number"},"file_size":{"description":"Final zip size in bytes; `null` until completed","type":"number","nullable":true},"error_code":{"type":"string","nullable":true},"created_at":{"type":"string"},"completed_at":{"type":"string","nullable":true},"expires_at":{"type":"string"},"download_url":{"description":"Signed URL valid for 1h. Only populated when `status` is `completed`.","type":"string","nullable":true},"filename":{"type":"string","nullable":true}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["JOB_NOT_FOUND"]}}}}}},"410":{"description":"Response for status 410","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["JOB_EXPIRED"]}}}}}}}}},"/renders/{renderId}":{"get":{"x-mcp":{"ui":true},"tags":["Renders"],"operationId":"getRender","summary":"Get render status","description":"Returns the current status of a render job. Poll this endpoint until `status` is `completed` or `failed`.\n\nWe recommend polling every **5–10 seconds**. Use `progress` (0–100) to display a progress bar to your users.","security":[{"apiKey":[]}],"parameters":[{"name":"renderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","edit_id","name","status","progress","output_resolution","created_at","started_at","completed_at"],"properties":{"id":{"description":"Unique render ID","type":"string"},"edit_id":{"description":"Edit this render was produced from. It never expires: pass it to `POST /renders` for a fresh file, or to `POST /posts` to publish it.","type":"string"},"name":{"description":"Name of the edit / clip being rendered","type":"string","nullable":true},"status":{"type":"string","enum":["queued","active","completed","failed","cancelled","expired","waiting_quality"]},"progress":{"description":"Render progress from 0 to 100","type":"number"},"output_resolution":{"description":"Output resolution, e.g. `720p` or `1080p`","type":"string","nullable":true},"created_at":{"description":"ISO 8601 timestamp of when the render was queued","type":"string"},"started_at":{"description":"ISO 8601 timestamp of when rendering started","type":"string","nullable":true},"completed_at":{"description":"ISO 8601 timestamp of when the render finished","type":"string","nullable":true}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_NOT_FOUND"]}},"additionalProperties":false}}}}}},"delete":{"tags":["Renders"],"operationId":"deleteRender","summary":"Cancel or delete a render","description":"Cancels a queued or active render, or permanently deletes a completed/failed/expired render record. Deleting a completed render also removes the rendered video file from storage.","security":[{"apiKey":[]}],"parameters":[{"name":"renderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_FORBIDDEN"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_NOT_FOUND"]}}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CANCEL_FAILED"]}}}}}}}}},"/renders/{renderId}/download":{"get":{"x-mcp":{"ui":true},"tags":["Renders"],"operationId":"downloadRender","summary":"Get render download URL","description":"Returns a time-limited signed URL to download the completed rendered video as an MP4. The URL expires after **1 hour** — fetch it fresh each time rather than caching it.\n\nReturns `410` if the file has been purged from storage (renders expire according to your plan's retention period).","security":[{"apiKey":[]}],"parameters":[{"name":"renderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["url","filename"],"properties":{"url":{"description":"Signed download URL — valid for 1 hour","type":"string"},"filename":{"description":"Suggested filename for the downloaded file","type":"string"}},"additionalProperties":false}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_NOT_FOUND"]}},"additionalProperties":false}}}},"410":{"description":"Response for status 410","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["RENDER_FILE_EXPIRED"]}},"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SIGNED_URL_FAILED"]}},"additionalProperties":false}}}}}}},"/templates":{"get":{"tags":["Templates"],"operationId":"listTemplates","summary":"List templates","description":"Returns a paginated list of video editing templates. Use `filter=mine` (default) to list your own templates, or `filter=public` for CutPro's built-in public templates.\n\nPass a template's `id` to `POST /clips/{videoId}/submissions/{submissionId}/apply_template` to apply it in bulk to your generated clips.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}},{"name":"filter","in":"query","required":false,"schema":{"type":"string","enum":["mine","public"]}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["recent","most_recent","name"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["templates","pagination"],"properties":{"templates":{"type":"array","items":{"type":"object","required":["id","name","description","category","aspect_ratio","auto_add_captions","is_public","thumbnail_url","created_at"],"properties":{"id":{"description":"Unique template ID — use this when calling `apply_template`","type":"string"},"name":{"description":"Template name","type":"string"},"description":{"description":"Short description of what the template does","type":"string","nullable":true},"category":{"description":"Template category, e.g. `gaming`, `podcast`, `education`","type":"string","nullable":true},"aspect_ratio":{"description":"Target aspect ratio — e.g. `9:16`, `1:1`, `16:9`","type":"string","nullable":true},"auto_add_captions":{"description":"`true` if this template automatically adds AI captions","type":"boolean"},"is_public":{"description":"`true` if this is a public CutPro template","type":"boolean"},"thumbnail_url":{"description":"Signed URL for the template thumbnail — time-limited, fetch fresh when needed","type":"string","nullable":true},"created_at":{"description":"ISO 8601 timestamp of when the template was created","type":"string"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}},"additionalProperties":false}}}}}}},"/transcriptions/upload":{"post":{"x-mcp":{"localFiles":true},"tags":["Transcriptions"],"operationId":"createTranscriptionUpload","summary":"Start an upload","description":"Returns the generated `media_id` plus a presigned PUT URL. Upload the raw bytes to `upload_url` with the same `Content-Type` you declared here, then call `POST /transcriptions` with the `media_id` to start the job.\n\nBoth video and audio files are accepted, so an audio-only podcast never has to be wrapped in a video container. The ceiling is the smaller of your plan's upload limit and the storage quota you still have free; `FILE_TOO_LARGE` reports the effective ceiling in `max_size` and `STORAGE_LIMIT_EXCEEDED` means the quota is full.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name. The extension decides whether this is treated as audio or video.","type":"string"},"file_size":{"description":"Size of the file in bytes.","type":"number"},"content_type":{"description":"MIME type. Defaults to `audio/mpeg` or `video/mp4`, and must match the bytes you PUT.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name. The extension decides whether this is treated as audio or video.","type":"string"},"file_size":{"description":"Size of the file in bytes.","type":"number"},"content_type":{"description":"MIME type. Defaults to `audio/mpeg` or `video/mp4`, and must match the bytes you PUT.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name. The extension decides whether this is treated as audio or video.","type":"string"},"file_size":{"description":"Size of the file in bytes.","type":"number"},"content_type":{"description":"MIME type. Defaults to `audio/mpeg` or `video/mp4`, and must match the bytes you PUT.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["media_id","kind","upload_url","expires_in"],"properties":{"media_id":{"description":"Generated media ID. Pass it to `POST /transcriptions`.","type":"string"},"kind":{"type":"string","enum":["video","audio"]},"upload_url":{"description":"Presigned PUT URL. Upload the raw bytes here.","type":"string"},"expires_in":{"description":"Seconds until `upload_url` expires.","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_FILE_TYPE","FILE_TOO_LARGE"]},"extra":{"type":"object","properties":{"allowed_extensions":{"description":"Accepted file extensions. Only on `INVALID_FILE_TYPE`.","type":"array","items":{"type":"string"}},"max_size":{"description":"Largest file your plan accepts, in bytes. Only on `FILE_TOO_LARGE`.","type":"number"}}}},"additionalProperties":false}}}},"406":{"description":"Response for status 406","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["STORAGE_LIMIT_EXCEEDED"]}}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRESIGN_FAILED"]}}}}}}}}},"/transcriptions":{"post":{"x-mcp":{"annotations":{"destructiveHint":true}},"tags":["Transcriptions"],"operationId":"createTranscription","summary":"Transcribe a media file","description":"Starts a transcription for a media file you uploaded via `POST /transcriptions/upload`. Credits are charged per minute of audio, plus a surcharge when `speaker_labels` is requested. Check the balance at `GET /balance` first.\n\nResponds `202` with `status: processing` when the ASR worker was dispatched: poll `GET /transcriptions/{transcriptionId}` until `status` is `ready` (or `failed` / `no_speech`), then fetch the text.\n\nResponds `200` when nothing had to run. That happens when the same audio was already transcribed (the transcript is shared per media, so a re-run is a cache hit and `credits_charged` is `0`), or when the audio is silent, which comes back as `no_speech` and is not billed.\n\nPassing a `media_id` that is already in your library re-runs it. That is how a transcript created without diarization is upgraded: ask again with `speaker_labels: true` and the audio is reprocessed, because the speaker column cannot be added after the fact.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["media_id"],"properties":{"media_id":{"description":"The `media_id` from `POST /transcriptions/upload`, or one already in your library.","type":"string"},"speaker_labels":{"description":"Identify who is speaking on each cue. Costs more and forces a full re-run. Default `false`.","type":"boolean"},"source_language":{"description":"Spoken language, e.g. `pt`. Omit to auto-detect, but pin it for short clips, where detection routinely mistakes Portuguese for Spanish.","type":"string"},"file_name":{"description":"Original file name, used as the job title. Required for a media you just uploaded.","type":"string"},"file_size":{"description":"Size in bytes. Required for a media you just uploaded.","type":"number"},"duration":{"description":"Duration in seconds. Fallback only: the stored file is probed and its real duration wins.","type":"number"},"content_type":{"description":"MIME type of the uploaded file.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["media_id"],"properties":{"media_id":{"description":"The `media_id` from `POST /transcriptions/upload`, or one already in your library.","type":"string"},"speaker_labels":{"description":"Identify who is speaking on each cue. Costs more and forces a full re-run. Default `false`.","type":"boolean"},"source_language":{"description":"Spoken language, e.g. `pt`. Omit to auto-detect, but pin it for short clips, where detection routinely mistakes Portuguese for Spanish.","type":"string"},"file_name":{"description":"Original file name, used as the job title. Required for a media you just uploaded.","type":"string"},"file_size":{"description":"Size in bytes. Required for a media you just uploaded.","type":"number"},"duration":{"description":"Duration in seconds. Fallback only: the stored file is probed and its real duration wins.","type":"number"},"content_type":{"description":"MIME type of the uploaded file.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["media_id"],"properties":{"media_id":{"description":"The `media_id` from `POST /transcriptions/upload`, or one already in your library.","type":"string"},"speaker_labels":{"description":"Identify who is speaking on each cue. Costs more and forces a full re-run. Default `false`.","type":"boolean"},"source_language":{"description":"Spoken language, e.g. `pt`. Omit to auto-detect, but pin it for short clips, where detection routinely mistakes Portuguese for Spanish.","type":"string"},"file_name":{"description":"Original file name, used as the job title. Required for a media you just uploaded.","type":"string"},"file_size":{"description":"Size in bytes. Required for a media you just uploaded.","type":"number"},"duration":{"description":"Duration in seconds. Fallback only: the stored file is probed and its real duration wins.","type":"number"},"content_type":{"description":"MIME type of the uploaded file.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","status","credits_charged"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["ready","no_speech"]},"credits_charged":{"type":"number"}}}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","status","credits_charged"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["processing"]},"credits_charged":{"description":"Credits debited when the job was dispatched.","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_METADATA_REQUIRED","MEDIA_TOO_LONG"]},"extra":{"type":"object","properties":{"duration":{"description":"Measured duration of the audio, in seconds.","type":"number"},"max_duration":{"description":"Longest audio your plan accepts, in seconds.","type":"number"}}}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","is_owner"],"properties":{"credits_needed":{"type":"number"},"is_owner":{"description":"`true` if the key's user owns the workspace and can top it up.","type":"boolean"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_NOT_FOUND"]}}}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNREADABLE"]}}}}}}}},"get":{"tags":["Transcriptions"],"operationId":"listTranscriptions","summary":"List transcriptions","description":"Returns a paginated list of the workspace's transcription jobs, newest first.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["transcriptions","pagination"],"properties":{"transcriptions":{"type":"array","items":{"type":"object","required":["id","media_id","title","duration_seconds","status","language","speaker_labels","speaker_count","credits_charged","media_type","created_at","completed_at"],"properties":{"id":{"description":"Unique transcription job ID","type":"string"},"media_id":{"description":"The uploaded media this job transcribed. Reuse it to re-run the same file.","type":"string"},"title":{"description":"Job title, derived from the uploaded file name","type":"string"},"duration_seconds":{"description":"Measured duration of the audio, in seconds. This is what was billed.","type":"number"},"status":{"type":"string","enum":["processing","ready","failed","no_speech"]},"language":{"description":"Detected (or pinned) spoken language as a BCP-47-ish code, e.g. `pt`","type":"string","nullable":true},"speaker_labels":{"description":"`true` if this job was billed with speaker identification","type":"boolean"},"speaker_count":{"description":"Distinct speakers found. Only populated when `speaker_labels` is `true`.","type":"number","nullable":true},"credits_charged":{"description":"Credits actually debited for this job. `0` when nothing was charged, including while the workspace has unlimited usage","type":"number"},"media_type":{"type":"string","enum":["image","video","audio","font"]},"created_at":{"description":"ISO 8601 timestamp of when the job was created","type":"string"},"completed_at":{"description":"ISO 8601 timestamp of when the job reached a terminal status","type":"string","nullable":true}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}}}}}}}}},"/transcriptions/{transcriptionId}":{"get":{"tags":["Transcriptions"],"operationId":"getTranscription","summary":"Get transcription status","description":"Returns the current state of a transcription job. Poll every **5–10 seconds** while `status` is `processing`.\n\nOnce `status` is `ready`, fetch the text with `GET /transcriptions/{transcriptionId}/transcript` (JSON cues) or `GET /transcriptions/{transcriptionId}/download` (SRT, VTT or plain text).","security":[{"apiKey":[]}],"parameters":[{"name":"transcriptionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","media_id","title","duration_seconds","status","language","speaker_labels","speaker_count","credits_charged","media_type","created_at","completed_at"],"properties":{"id":{"description":"Unique transcription job ID","type":"string"},"media_id":{"description":"The uploaded media this job transcribed. Reuse it to re-run the same file.","type":"string"},"title":{"description":"Job title, derived from the uploaded file name","type":"string"},"duration_seconds":{"description":"Measured duration of the audio, in seconds. This is what was billed.","type":"number"},"status":{"type":"string","enum":["processing","ready","failed","no_speech"]},"language":{"description":"Detected (or pinned) spoken language as a BCP-47-ish code, e.g. `pt`","type":"string","nullable":true},"speaker_labels":{"description":"`true` if this job was billed with speaker identification","type":"boolean"},"speaker_count":{"description":"Distinct speakers found. Only populated when `speaker_labels` is `true`.","type":"number","nullable":true},"credits_charged":{"description":"Credits actually debited for this job. `0` when nothing was charged, including while the workspace has unlimited usage","type":"number"},"media_type":{"type":"string","enum":["image","video","audio","font"]},"created_at":{"description":"ISO 8601 timestamp of when the job was created","type":"string"},"completed_at":{"description":"ISO 8601 timestamp of when the job reached a terminal status","type":"string","nullable":true}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TRANSCRIPTION_NOT_FOUND"]}}}}}}}},"delete":{"tags":["Transcriptions"],"operationId":"deleteTranscription","summary":"Delete a transcription","description":"Removes the job from the list and from every read endpoint. The uploaded media stays in your library, so the same `media_id` can be transcribed again, and that re-run is a cache hit, not a second charge.","security":[{"apiKey":[]}],"parameters":[{"name":"transcriptionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TRANSCRIPTION_NOT_FOUND"]}}}}}}}}},"/transcriptions/{transcriptionId}/transcript":{"get":{"tags":["Transcriptions"],"operationId":"getTranscriptionCues","summary":"Get the transcript as JSON","description":"Returns the transcript as timed cues, ready to render or index without parsing a subtitle file. Timings are in seconds from the start of the audio.\n\n`speaker` is only ever filled when the job was billed with `speaker_labels`; on every other job it is `null`.\n\nReturns `409 TRANSCRIPTION_NOT_READY` while the worker is still running. Keep polling `GET /transcriptions/{transcriptionId}`.","security":[{"apiKey":[]}],"parameters":[{"name":"transcriptionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["language","speaker_labels","cues"],"properties":{"language":{"description":"Language the audio was transcribed as.","type":"string","nullable":true},"speaker_labels":{"type":"boolean"},"cues":{"type":"array","items":{"type":"object","required":["start","end","text","speaker"],"properties":{"start":{"description":"Start offset in seconds.","type":"number"},"end":{"description":"End offset in seconds.","type":"number"},"text":{"type":"string"},"speaker":{"description":"Speaker label, e.g. `A`. `null` unless the job was diarized.","type":"string","nullable":true}}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TRANSCRIPTION_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TRANSCRIPTION_NOT_READY"]}}}}}}}}},"/transcriptions/{transcriptionId}/download":{"get":{"tags":["Transcriptions"],"operationId":"downloadTranscription","summary":"Download the transcript as a subtitle file","description":"Returns the transcript as a ready-to-use subtitle file (`srt` by default, `vtt` or `txt`) with the matching `Content-Type` and a `Content-Disposition` filename. The body is the file itself, not JSON.\n\nSpeaker names are written into the file only when the job was billed with `speaker_labels`; pass `speakers=false` to leave them out of a diarized transcript.\n\nReturns `409 TRANSCRIPTION_NOT_READY` while the worker is still running. Keep polling `GET /transcriptions/{transcriptionId}`.","security":[{"apiKey":[]}],"parameters":[{"name":"transcriptionId","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["srt","vtt","txt"]}},{"name":"speakers","in":"query","required":false,"schema":{"description":"Include speaker names. Default `true`, and inert unless the job was diarized.","type":"boolean"}}],"responses":{"200":{"description":"The subtitle file contents.","content":{"text/plain":{"schema":{"description":"The subtitle file contents.","type":"string"}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TRANSCRIPTION_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TRANSCRIPTION_NOT_READY"]}}}}}}}}},"/personas/catalog":{"get":{"tags":["Personas"],"operationId":"getPersonaCatalog","summary":"Get traits, prices and limits","description":"Everything a client needs to build the persona form without hardcoding it: every trait option, the defaults, which traits still apply when reference photos are used, the prices in credits and the limits of a source video. Prices follow what the models cost and can change at any time, so read them from here.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["chip_options","default_chips","face_photo_groups","max_face_photos","video_styles","pricing","video_limits"],"properties":{"chip_options":{"description":"Trait group (the keys of `chips`) to the options it accepts.","type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"default_chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"face_photo_groups":{"description":"Trait groups that still apply when the persona is made from face photos. The others are ignored: the photos decide them. In these groups `photo` keeps the trait as the photos show it; without photos it falls back to the default.","type":"array","items":{"type":"string"}},"max_face_photos":{"description":"Most reference photos one persona accepts.","type":"number"},"video_styles":{"description":"Values `style` accepts in `GET /personas/swap/quote` and `POST /personas/{id}/videos`.","type":"array","items":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]}},"pricing":{"type":"object","required":["photo_credits","photo_with_references_credits","scene_photo_credits","video_economy_credits_per_second","video_standard_credits_per_second","video_short_max_seconds","video_short_credits_per_second","video_mid_max_seconds","video_mid_credits_per_second","video_long_credits_per_second"],"properties":{"photo_credits":{"description":"One persona photo from traits only.","type":"number"},"photo_with_references_credits":{"description":"One persona photo made from reference photos, and every one-line edit (`note`) of an existing photo.","type":"number"},"scene_photo_credits":{"description":"One photo of a saved persona in a scene (`POST /personas/{id}/shots`); a `style` doubles it.","type":"number"},"video_economy_credits_per_second":{"description":"Per second of the source at `quality: economy`.","type":"number"},"video_standard_credits_per_second":{"description":"Per second of the source at `quality: standard`.","type":"number"},"video_short_max_seconds":{"description":"Longest source billed at the short rate of `quality: high`.","type":"number"},"video_short_credits_per_second":{"description":"Per second of a source up to `video_short_max_seconds`, at `quality: high`.","type":"number"},"video_mid_max_seconds":{"description":"Longest source billed at the mid rate of `quality: high`.","type":"number"},"video_mid_credits_per_second":{"description":"Per second of a source longer than `video_short_max_seconds` and up to `video_mid_max_seconds`, at `quality: high`.","type":"number"},"video_long_credits_per_second":{"description":"Per second of the whole source when it is longer than `video_mid_max_seconds`, at `quality: high`.","type":"number"}}},"video_limits":{"type":"object","required":["min_seconds","max_seconds","standard","max_file_size","min_side","max_side","extensions"],"properties":{"min_seconds":{"type":"number"},"max_seconds":{"description":"Longest source at `quality: high`.","type":"number"},"standard":{"description":"Tighter limits that apply at `quality: standard` and `quality: economy`, on top of the ones here.","type":"object","required":["max_seconds","max_file_size","extensions"],"properties":{"max_seconds":{"type":"number"},"max_file_size":{"description":"Bytes.","type":"number"},"extensions":{"type":"array","items":{"type":"string"}}}},"max_file_size":{"description":"Bytes.","type":"number"},"min_side":{"description":"Smallest width and height, in pixels.","type":"number"},"max_side":{"description":"Largest width and height, in pixels.","type":"number"},"extensions":{"type":"array","items":{"type":"string"}}}}}}}}},"502":{"description":"Response for status 502","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNAVAILABLE"]}}}}}}}}},"/personas/presets":{"get":{"x-mcp":{"annotations":{"readOnlyHint":true}},"tags":["Personas"],"operationId":"listPersonaPresets","summary":"List ready-made characters","description":"Characters whose photo already exists. `POST /personas/presets/{presetId}` turns one into a persona for free, ready to name, save and use in videos. `favorite` is the key's user's star, set with `PUT /personas/presets/{presetId}/favorite`.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["presets"],"properties":{"presets":{"type":"array","items":{"type":"object","required":["id","name","category","favorite","favorite_count","image_url","face_url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"default":"weird","description":"`weird`, `cartoon` (live-action takes on cartoon looks), `creator` (everyday creators) or `influencers` (influencer personas).","type":"string","enum":["weird","cartoon","creator","influencers"]},"favorite":{"type":"boolean"},"favorite_count":{"description":"How many users starred this character.","type":"number"},"image_url":{"description":"Signed URL of the character photo (close-up and full body), valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of the close-up portrait, valid for one hour.","type":"string","nullable":true}}}}}}}}}}}},"/personas/presets/{presetId}":{"post":{"x-mcp":{"ui":true},"tags":["Personas"],"operationId":"createPersonaFromPreset","summary":"Create a persona from a ready-made character","description":"Free and instant: the character's photo becomes the first version of a new persona with `image_status: ready`. With `name` the persona is saved at once (`status: ready`) and can be used in videos right away; without it, it is a `draft` to name with `POST /personas/{id}/save`.","security":[{"apiKey":[]}],"parameters":[{"name":"presetId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"minLength":1,"maxLength":60,"description":"Name to save the persona with.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"minLength":1,"maxLength":60,"description":"Name to save the persona with.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"minLength":1,"maxLength":60,"description":"Name to save the persona with.","type":"string"}}}}}},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id","name","status","chips","uses_face_photos","preset_id","image_status","error_code","image_url","eta","versions"],"properties":{"id":{"type":"string"},"name":{"description":"Empty until the persona is saved.","type":"string"},"status":{"type":"string","enum":["draft","ready"]},"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"uses_face_photos":{"description":"`true` when the persona was made from reference photos: the face, skin, eyes and hair come from them.","type":"boolean"},"preset_id":{"description":"The ready-made character this persona started from. Such a persona stays that character: `chips` are ignored on regenerate, a `note` still edits it.","type":"string","nullable":true},"image_status":{"type":"string","enum":["generating","ready","failed"]},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"image_url":{"description":"Signed URL of the persona photo (close-up and full body side by side). Valid for one hour.","type":"string","nullable":true},"eta":{"description":"Only while `image_status` is `generating`.","type":"object","required":["started_at","expected_seconds"],"properties":{"started_at":{"description":"ISO 8601 timestamp of when this generation started.","type":"string"},"expected_seconds":{"description":"Typical duration of a generation like this one, `null` until there is history to estimate from.","type":"number","nullable":true}},"nullable":true},"versions":{"description":"Every photo the persona has had, newest first, up to 30. Each generation or edit that finishes adds one and makes it current.","type":"array","items":{"type":"object","required":["id","current","image_url","face_url","feedback","feedback_reason","created_at"],"properties":{"id":{"description":"Pass it to `POST /personas/{id}/versions/{versionId}/restore` to go back to this photo.","type":"string"},"current":{"description":"`true` for the photo the persona uses now.","type":"boolean"},"image_url":{"description":"Signed URL of this version's photo, valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of this version's close-up portrait, valid for one hour.","type":"string","nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the photo feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRESET_NOT_FOUND","PERSONA_NOT_FOUND"]}}}}}},"502":{"description":"Response for status 502","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNAVAILABLE"]}}}}}}}}},"/personas/presets/{presetId}/favorite":{"put":{"tags":["Personas"],"operationId":"favoritePersonaPreset","summary":"Star a ready-made character","description":"`favorite: true` stars the character for the key's user, `false` removes the star.","security":[{"apiKey":[]}],"parameters":[{"name":"presetId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["favorite"],"properties":{"favorite":{"type":"boolean"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["favorite"],"properties":{"favorite":{"type":"boolean"}}}},"multipart/form-data":{"schema":{"type":"object","required":["favorite"],"properties":{"favorite":{"type":"boolean"}}}}}},"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRESET_NOT_FOUND"]}}}}}}}}},"/personas":{"get":{"x-mcp":{"ui":true},"tags":["Personas"],"operationId":"listPersonas","summary":"List personas","description":"Returns the workspace's personas, newest first, drafts included. `image_status` and `video_generating` say what is still being generated, so one call shows every persona in progress.","security":[{"apiKey":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["personas","pagination"],"properties":{"personas":{"type":"array","items":{"type":"object","required":["id","name","status","image_status","video_generating","face_url","created_at"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","ready"]},"image_status":{"type":"string","enum":["generating","ready","failed"]},"video_generating":{"description":"`true` while at least one of the persona's videos is `processing`.","type":"boolean"},"face_url":{"description":"Signed URL of the close-up portrait, valid for one hour. `null` before the first photo is ready.","type":"string","nullable":true},"created_at":{"type":"string"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}}}}}}}},"post":{"x-mcp":{"ui":true,"annotations":{"destructiveHint":true}},"tags":["Personas"],"operationId":"createPersona","summary":"Create a persona","description":"Creates a draft persona and starts generating its photo: a close-up portrait and a full-body shot of the same person. Credits are charged now (see `GET /personas/catalog`), even on a workspace with unlimited usage, and refunded if the photo fails.\n\nWith `face_ids` the persona keeps the identity of the person in the photos, and only the traits listed in `face_photo_groups` are applied.\n\nResponds `202` with `image_status: generating`. Poll `GET /personas/{id}` every 5 seconds until it is `ready` or `failed`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chips"],"properties":{"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"face_ids":{"minItems":1,"maxItems":6,"description":"Ids from `POST /personas/faces`, uploaded in the last 24 hours.","type":"array","items":{"type":"string"}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["chips"],"properties":{"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"face_ids":{"minItems":1,"maxItems":6,"description":"Ids from `POST /personas/faces`, uploaded in the last 24 hours.","type":"array","items":{"type":"string"}}}}},"multipart/form-data":{"schema":{"type":"object","required":["chips"],"properties":{"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"face_ids":{"minItems":1,"maxItems":6,"description":"Ids from `POST /personas/faces`, uploaded in the last 24 hours.","type":"array","items":{"type":"string"}}}}}}},"responses":{"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","name","status","chips","uses_face_photos","preset_id","image_status","error_code","image_url","eta","versions"],"properties":{"id":{"type":"string"},"name":{"description":"Empty until the persona is saved.","type":"string"},"status":{"type":"string","enum":["draft","ready"]},"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"uses_face_photos":{"description":"`true` when the persona was made from reference photos: the face, skin, eyes and hair come from them.","type":"boolean"},"preset_id":{"description":"The ready-made character this persona started from. Such a persona stays that character: `chips` are ignored on regenerate, a `note` still edits it.","type":"string","nullable":true},"image_status":{"type":"string","enum":["generating","ready","failed"]},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"image_url":{"description":"Signed URL of the persona photo (close-up and full body side by side). Valid for one hour.","type":"string","nullable":true},"eta":{"description":"Only while `image_status` is `generating`.","type":"object","required":["started_at","expected_seconds"],"properties":{"started_at":{"description":"ISO 8601 timestamp of when this generation started.","type":"string"},"expected_seconds":{"description":"Typical duration of a generation like this one, `null` until there is history to estimate from.","type":"number","nullable":true}},"nullable":true},"versions":{"description":"Every photo the persona has had, newest first, up to 30. Each generation or edit that finishes adds one and makes it current.","type":"array","items":{"type":"object","required":["id","current","image_url","face_url","feedback","feedback_reason","created_at"],"properties":{"id":{"description":"Pass it to `POST /personas/{id}/versions/{versionId}/restore` to go back to this photo.","type":"string"},"current":{"description":"`true` for the photo the persona uses now.","type":"boolean"},"image_url":{"description":"Signed URL of this version's photo, valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of this version's close-up portrait, valid for one hour.","type":"string","nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the photo feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","scope","is_owner","top_up_url"],"properties":{"credits_needed":{"type":"number"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"description":"`true` if the key's user can buy credits for this workspace; otherwise ask its owner.","type":"boolean"},"top_up_url":{"description":"Page where credits are bought, for the workspace selected in the app.","type":"string"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["FACE_NOT_FOUND","PERSONA_NOT_FOUND"]}}}}}}}}},"/personas/faces":{"post":{"x-mcp":{"localFiles":true},"tags":["Personas"],"operationId":"uploadPersonaFace","summary":"Upload a reference photo","description":"Sends one photo of a real person as `multipart/form-data`, to make a persona that looks like them. Only the user's own face, as an adult, is allowed: `own_face_adult` must be `true` and is the user's statement of that. JPEG, PNG, WebP or HEIC up to 10 MB. A close, sharp photo of the face gives the most faithful result.\n\nPass the returned `id` in `face_ids` of `POST /personas` within 24 hours. Up to 6 photos per persona.","security":[{"apiKey":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","required":["photo","own_face_adult"],"properties":{"photo":{"description":"The image file.","type":"string","format":"binary"},"own_face_adult":{"description":"Confirms the photo shows the user themself, and that they are 18 or older.","type":"string","enum":["true"]}}}}},"required":true},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"description":"Face photo id, for `face_ids`.","type":"string"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_IMAGE"]}}}}}}}}},"/personas/swap/quote":{"get":{"x-mcp":{"annotations":{"readOnlyHint":true}},"tags":["Personas"],"operationId":"quotePersonaSwap","summary":"Price a swap video","description":"Measures a library video and returns what swapping its person for a persona costs at the given `quality`. Nothing is charged. Pass the returned `credits` to `POST /personas/{id}/videos` with `type: swap` and the same `quality`, which refuses with `PRICE_CHANGED` if the price is different. `replace` does not change the price, except `none` (needs a `style`), which pays no scene for the person. Besides the rate per second, the price can include a small amount for each scene of the video where the person appears, so the person stays the same across cuts, and a `style` adds that same amount again per scene.\n\n`VIDEO_DURATION_OUT_OF_RANGE` and `VIDEO_UNSUPPORTED` (format, size or resolution) follow `video_limits` of `GET /personas/catalog` for that `quality`; a video refused at `standard` may still fit `high`.","security":[{"apiKey":[]}],"parameters":[{"name":"media_id","in":"query","required":true,"schema":{"description":"The `media_id` from `POST /personas/sources/upload`, or any video already in the library.","type":"string"}},{"name":"quality","in":"query","required":false,"schema":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]}},{"name":"replace","in":"query","required":false,"schema":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]}},{"name":"style","in":"query","required":false,"schema":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["media_id","quality","replace","style","seconds","credits"],"properties":{"media_id":{"type":"string"},"quality":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]},"replace":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"],"nullable":true},"seconds":{"description":"Measured duration of the video.","type":"number"},"credits":{"description":"Price of the persona video, in credits.","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_DURATION_OUT_OF_RANGE","VIDEO_UNSUPPORTED","STYLE_UNSUPPORTED","STYLE_REQUIRED"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_NOT_FOUND"]}}}}}},"502":{"description":"Response for status 502","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNAVAILABLE"]}}}}}}}}},"/personas/sources/upload":{"post":{"x-mcp":{"localFiles":true},"tags":["Personas"],"operationId":"createPersonaSourceUpload","summary":"Upload a source video","description":"Starts the upload of the video whose person will be swapped for a persona. Returns a `media_id` and a presigned PUT URL: PUT the raw bytes to `upload_url` with the same `Content-Type`, then call `POST /personas/sources/upload/complete`.\n\nMP4 or MOV only, within `video_limits` of `GET /personas/catalog`. The video goes to the workspace library and counts toward its storage. A video already in the library needs no upload: use its id as `media_id`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name; its extension must be `.mp4` or `.mov`.","type":"string"},"file_size":{"description":"Size of the file in bytes.","type":"number"},"content_type":{"description":"MIME type, `video/mp4` or `video/quicktime`. Must match the bytes you PUT.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name; its extension must be `.mp4` or `.mov`.","type":"string"},"file_size":{"description":"Size of the file in bytes.","type":"number"},"content_type":{"description":"MIME type, `video/mp4` or `video/quicktime`. Must match the bytes you PUT.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["file_name","file_size"],"properties":{"file_name":{"description":"Original file name; its extension must be `.mp4` or `.mov`.","type":"string"},"file_size":{"description":"Size of the file in bytes.","type":"number"},"content_type":{"description":"MIME type, `video/mp4` or `video/quicktime`. Must match the bytes you PUT.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["media_id","upload_url","expires_in"],"properties":{"media_id":{"description":"Pass it to the complete call, then to `GET /personas/swap/quote` and `POST /personas/{id}/videos`.","type":"string"},"upload_url":{"description":"Presigned PUT URL. Upload the raw bytes here.","type":"string"},"expires_in":{"description":"Seconds until `upload_url` expires.","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_FILE_TYPE","FILE_TOO_LARGE"]},"extra":{"type":"object","properties":{"allowed_extensions":{"description":"Accepted file extensions. Only on `INVALID_FILE_TYPE`.","type":"array","items":{"type":"string"}},"max_size":{"description":"Largest file your plan accepts, in bytes. Only on `FILE_TOO_LARGE`.","type":"number"}}}},"additionalProperties":false}}}},"406":{"description":"Response for status 406","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["STORAGE_LIMIT_EXCEEDED"]}}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRESIGN_FAILED"]}}}}}}}}},"/personas/sources/upload/complete":{"post":{"x-mcp":{"localFiles":true},"tags":["Personas"],"operationId":"completePersonaSourceUpload","summary":"Complete a source video upload","description":"Registers the uploaded video in the library. Call it after the PUT to `upload_url` returned `200`, then price the video with `GET /personas/swap/quote`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["media_id","file_name"],"properties":{"media_id":{"description":"The `media_id` from `POST /personas/sources/upload`.","type":"string"},"file_name":{"description":"Original file name, used as the library title.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["media_id","file_name"],"properties":{"media_id":{"description":"The `media_id` from `POST /personas/sources/upload`.","type":"string"},"file_name":{"description":"Original file name, used as the library title.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["media_id","file_name"],"properties":{"media_id":{"description":"The `media_id` from `POST /personas/sources/upload`.","type":"string"},"file_name":{"description":"Original file name, used as the library title.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["media_id"],"properties":{"media_id":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["FILE_NOT_FOUND"]}}}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNREADABLE"]}}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INTERNAL_ERROR"]}}}}}}}}},"/personas/{id}":{"get":{"x-mcp":{"ui":true},"tags":["Personas"],"operationId":"getPersona","summary":"Get a persona","description":"Returns the persona with its photo. Poll it every 5 seconds while `image_status` is `generating`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","name","status","chips","uses_face_photos","preset_id","image_status","error_code","image_url","eta","versions"],"properties":{"id":{"type":"string"},"name":{"description":"Empty until the persona is saved.","type":"string"},"status":{"type":"string","enum":["draft","ready"]},"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"uses_face_photos":{"description":"`true` when the persona was made from reference photos: the face, skin, eyes and hair come from them.","type":"boolean"},"preset_id":{"description":"The ready-made character this persona started from. Such a persona stays that character: `chips` are ignored on regenerate, a `note` still edits it.","type":"string","nullable":true},"image_status":{"type":"string","enum":["generating","ready","failed"]},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"image_url":{"description":"Signed URL of the persona photo (close-up and full body side by side). Valid for one hour.","type":"string","nullable":true},"eta":{"description":"Only while `image_status` is `generating`.","type":"object","required":["started_at","expected_seconds"],"properties":{"started_at":{"description":"ISO 8601 timestamp of when this generation started.","type":"string"},"expected_seconds":{"description":"Typical duration of a generation like this one, `null` until there is history to estimate from.","type":"number","nullable":true}},"nullable":true},"versions":{"description":"Every photo the persona has had, newest first, up to 30. Each generation or edit that finishes adds one and makes it current.","type":"array","items":{"type":"object","required":["id","current","image_url","face_url","feedback","feedback_reason","created_at"],"properties":{"id":{"description":"Pass it to `POST /personas/{id}/versions/{versionId}/restore` to go back to this photo.","type":"string"},"current":{"description":"`true` for the photo the persona uses now.","type":"boolean"},"image_url":{"description":"Signed URL of this version's photo, valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of this version's close-up portrait, valid for one hour.","type":"string","nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the photo feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND"]}}}}}}}},"delete":{"tags":["Personas"],"operationId":"deletePersona","summary":"Delete a persona","description":"Removes the persona and its videos from every listing. A generation still running finishes or is refunded as usual, and edits already created from its videos stay in the workspace.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND"]}}}}}}}}},"/personas/{id}/regenerate":{"post":{"x-mcp":{"ui":true,"annotations":{"destructiveHint":true}},"tags":["Personas"],"operationId":"regeneratePersona","summary":"Regenerate or edit the persona photo","description":"Generates the photo again, for drafts and saved personas alike. Send new `chips` to change traits, nothing to try again with the same ones, or a one-line `note` (for example `make the jacket red`) to edit the current photo keeping the same person. When it finishes, the new photo becomes a new version and the current one; the traits change only then, so a failed generation leaves the persona as it was. Earlier versions stay in `versions` and videos already made keep their photo. Charged like a new photo; a `note` is priced as `photo_with_references_credits`.\n\n`CARD_LOCKED` means a photo is already generating, or a `note` was sent before the first photo exists.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"note":{"minLength":1,"maxLength":120,"description":"One-line change applied over the current photo.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"note":{"minLength":1,"maxLength":120,"description":"One-line change applied over the current photo.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"note":{"minLength":1,"maxLength":120,"description":"One-line change applied over the current photo.","type":"string"}}}}}},"responses":{"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","name","status","chips","uses_face_photos","preset_id","image_status","error_code","image_url","eta","versions"],"properties":{"id":{"type":"string"},"name":{"description":"Empty until the persona is saved.","type":"string"},"status":{"type":"string","enum":["draft","ready"]},"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"uses_face_photos":{"description":"`true` when the persona was made from reference photos: the face, skin, eyes and hair come from them.","type":"boolean"},"preset_id":{"description":"The ready-made character this persona started from. Such a persona stays that character: `chips` are ignored on regenerate, a `note` still edits it.","type":"string","nullable":true},"image_status":{"type":"string","enum":["generating","ready","failed"]},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"image_url":{"description":"Signed URL of the persona photo (close-up and full body side by side). Valid for one hour.","type":"string","nullable":true},"eta":{"description":"Only while `image_status` is `generating`.","type":"object","required":["started_at","expected_seconds"],"properties":{"started_at":{"description":"ISO 8601 timestamp of when this generation started.","type":"string"},"expected_seconds":{"description":"Typical duration of a generation like this one, `null` until there is history to estimate from.","type":"number","nullable":true}},"nullable":true},"versions":{"description":"Every photo the persona has had, newest first, up to 30. Each generation or edit that finishes adds one and makes it current.","type":"array","items":{"type":"object","required":["id","current","image_url","face_url","feedback","feedback_reason","created_at"],"properties":{"id":{"description":"Pass it to `POST /personas/{id}/versions/{versionId}/restore` to go back to this photo.","type":"string"},"current":{"description":"`true` for the photo the persona uses now.","type":"boolean"},"image_url":{"description":"Signed URL of this version's photo, valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of this version's close-up portrait, valid for one hour.","type":"string","nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the photo feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","scope","is_owner","top_up_url"],"properties":{"credits_needed":{"type":"number"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"description":"`true` if the key's user can buy credits for this workspace; otherwise ask its owner.","type":"boolean"},"top_up_url":{"description":"Page where credits are bought, for the workspace selected in the app.","type":"string"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CARD_LOCKED"]}}}}}}}}},"/personas/{id}/versions/{versionId}/restore":{"post":{"tags":["Personas"],"operationId":"restorePersonaVersion","summary":"Restore a persona version","description":"Makes an earlier photo from `versions` the current one again, with the traits it was made from. Free and instant; new videos use the restored photo and videos already made are not touched. `CARD_LOCKED` means a photo is generating: wait for it to finish.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","name","status","chips","uses_face_photos","preset_id","image_status","error_code","image_url","eta","versions"],"properties":{"id":{"type":"string"},"name":{"description":"Empty until the persona is saved.","type":"string"},"status":{"type":"string","enum":["draft","ready"]},"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"uses_face_photos":{"description":"`true` when the persona was made from reference photos: the face, skin, eyes and hair come from them.","type":"boolean"},"preset_id":{"description":"The ready-made character this persona started from. Such a persona stays that character: `chips` are ignored on regenerate, a `note` still edits it.","type":"string","nullable":true},"image_status":{"type":"string","enum":["generating","ready","failed"]},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"image_url":{"description":"Signed URL of the persona photo (close-up and full body side by side). Valid for one hour.","type":"string","nullable":true},"eta":{"description":"Only while `image_status` is `generating`.","type":"object","required":["started_at","expected_seconds"],"properties":{"started_at":{"description":"ISO 8601 timestamp of when this generation started.","type":"string"},"expected_seconds":{"description":"Typical duration of a generation like this one, `null` until there is history to estimate from.","type":"number","nullable":true}},"nullable":true},"versions":{"description":"Every photo the persona has had, newest first, up to 30. Each generation or edit that finishes adds one and makes it current.","type":"array","items":{"type":"object","required":["id","current","image_url","face_url","feedback","feedback_reason","created_at"],"properties":{"id":{"description":"Pass it to `POST /personas/{id}/versions/{versionId}/restore` to go back to this photo.","type":"string"},"current":{"description":"`true` for the photo the persona uses now.","type":"boolean"},"image_url":{"description":"Signed URL of this version's photo, valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of this version's close-up portrait, valid for one hour.","type":"string","nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the photo feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND","VERSION_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CARD_LOCKED"]}}}}}}}}},"/personas/{id}/versions/{versionId}/feedback":{"post":{"tags":["Personas"],"operationId":"ratePersonaVersion","summary":"Rate a persona photo","description":"Records whether a photo from `versions` was liked. Send `down` with a `reason`, or `null` to clear the rating. Free; it only teaches us what to improve.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["vote"],"properties":{"vote":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"reason":{"default":"not_realistic","description":"Why the photo was disliked: `not_realistic` (looks artificial), `wrong_traits` (not what was asked), `not_like_me` (does not look like the reference photos), `defects` (deformed hands, face or body), `other`.","type":"string","enum":["not_realistic","wrong_traits","not_like_me","defects","other"]}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["vote"],"properties":{"vote":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"reason":{"default":"not_realistic","description":"Why the photo was disliked: `not_realistic` (looks artificial), `wrong_traits` (not what was asked), `not_like_me` (does not look like the reference photos), `defects` (deformed hands, face or body), `other`.","type":"string","enum":["not_realistic","wrong_traits","not_like_me","defects","other"]}}}},"multipart/form-data":{"schema":{"type":"object","required":["vote"],"properties":{"vote":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"reason":{"default":"not_realistic","description":"Why the photo was disliked: `not_realistic` (looks artificial), `wrong_traits` (not what was asked), `not_like_me` (does not look like the reference photos), `defects` (deformed hands, face or body), `other`.","type":"string","enum":["not_realistic","wrong_traits","not_like_me","defects","other"]}}}}}},"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND","VERSION_NOT_FOUND"]}}}}}}}}},"/personas/{id}/videos/{videoId}/feedback":{"post":{"tags":["Personas"],"operationId":"ratePersonaVideo","summary":"Rate a persona video","description":"Records whether a persona video was liked. Send `down` with a `reason`, or `null` to clear the rating. Free. `down` also cancels the posts of this video that are still scheduled.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["vote"],"properties":{"vote":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"reason":{"default":"different_person","description":"Why the video was disliked: `different_person` (does not look like the persona), `scene_changed` (the original scene was not kept), `defects` (glitches or a deformed face or body), `bad_motion` (motion or lips out of sync), `product_wrong` (the product came out different), `speech_wrong` (a word, name or number was said wrong), `other`.","type":"string","enum":["different_person","scene_changed","defects","bad_motion","product_wrong","speech_wrong","other"]}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["vote"],"properties":{"vote":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"reason":{"default":"different_person","description":"Why the video was disliked: `different_person` (does not look like the persona), `scene_changed` (the original scene was not kept), `defects` (glitches or a deformed face or body), `bad_motion` (motion or lips out of sync), `product_wrong` (the product came out different), `speech_wrong` (a word, name or number was said wrong), `other`.","type":"string","enum":["different_person","scene_changed","defects","bad_motion","product_wrong","speech_wrong","other"]}}}},"multipart/form-data":{"schema":{"type":"object","required":["vote"],"properties":{"vote":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"reason":{"default":"different_person","description":"Why the video was disliked: `different_person` (does not look like the persona), `scene_changed` (the original scene was not kept), `defects` (glitches or a deformed face or body), `bad_motion` (motion or lips out of sync), `product_wrong` (the product came out different), `speech_wrong` (a word, name or number was said wrong), `other`.","type":"string","enum":["different_person","scene_changed","defects","bad_motion","product_wrong","speech_wrong","other"]}}}}}},"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_NOT_FOUND"]}}}}}}}}},"/personas/{id}/save":{"post":{"tags":["Personas"],"operationId":"savePersona","summary":"Save or rename a persona","description":"Approves the current photo and names the persona, which can then be used in videos. On a persona already saved it only renames it. The photo can still be regenerated or edited later, as new versions. `CARD_NOT_READY` means a draft whose photo is not `ready` yet.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"minLength":1,"maxLength":60,"type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["name"],"properties":{"name":{"minLength":1,"maxLength":60,"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["name"],"properties":{"name":{"minLength":1,"maxLength":60,"type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","name","status","chips","uses_face_photos","preset_id","image_status","error_code","image_url","eta","versions"],"properties":{"id":{"type":"string"},"name":{"description":"Empty until the persona is saved.","type":"string"},"status":{"type":"string","enum":["draft","ready"]},"chips":{"description":"One option per trait group. `GET /personas/catalog` lists every option and the defaults.","type":"object","required":["vibe","gender","age","origin","skin","eyes","hair_style","hair_color","facial_hair","face","body","outfit","accessory","mark"],"properties":{"vibe":{"default":"natural","type":"string","enum":["natural","bold","eccentric"]},"gender":{"default":"female","type":"string","enum":["female","male","androgynous"]},"age":{"default":"18_24","type":"string","enum":["18_24","25_34","35_44","45_59","60_plus"]},"origin":{"default":"latin","type":"string","enum":["latin","african","european","east_asian","south_asian","middle_eastern","indigenous","mixed"]},"skin":{"default":"very_light","type":"string","enum":["very_light","light","medium","olive","brown","dark"]},"eyes":{"default":"brown","type":"string","enum":["brown","hazel","green","blue","gray","amber","ice_blue"]},"hair_style":{"default":"buzz","type":"string","enum":["buzz","short","long_straight","long_wavy","curly","coily","braids","bald","bob","pixie","bowl","mullet","mohawk","afro","dreadlocks","pompadour","slicked_back","high_bun","pigtails","beehive","perm","shag"]},"hair_color":{"default":"black","type":"string","enum":["black","brown","blonde","red","gray","dyed","platinum","white","pink","blue","green","purple","two_tone","highlights"]},"facial_hair":{"default":"photo","type":"string","enum":["photo","none","stubble","full_beard","long_beard","goatee","moustache","handlebar","pencil"]},"face":{"default":"none","type":"string","enum":["none","dimples","high_cheekbones","full_lips","thick_brows","unibrow","gap_teeth","strong_jaw","hooked_nose","button_nose","jug_ears","eye_bags","cleft_chin"]},"body":{"default":"photo","type":"string","enum":["photo","slim","average","athletic","curvy","plus_size","muscular","lanky"]},"outfit":{"default":"photo","type":"string","enum":["photo","basic","streetwear","sporty","y2k","goth","punk","suit","retro_70s","aerobics_80s","grunge","preppy","boho","workwear","cowboy","skater","minimalist","glam","techwear","beach"]},"accessory":{"default":"photo","type":"string","enum":["photo","none","sunglasses","cap","beanie","bucket_hat","cowboy_hat","bandana","headband","headphones","gold_chain","pearl_necklace","hoop_earrings","scarf","crossbody_bag"]},"mark":{"default":"none","type":"string","enum":["none","glasses","freckles","beauty_mark","nose_piercing","hand_tattoo","hair_streak","septum_ring","face_tattoo","brow_scar","brow_slits","gold_grill","braces","vitiligo","ear_piercings","face_gems","bleached_brows"]}}},"uses_face_photos":{"description":"`true` when the persona was made from reference photos: the face, skin, eyes and hair come from them.","type":"boolean"},"preset_id":{"description":"The ready-made character this persona started from. Such a persona stays that character: `chips` are ignored on regenerate, a `note` still edits it.","type":"string","nullable":true},"image_status":{"type":"string","enum":["generating","ready","failed"]},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"image_url":{"description":"Signed URL of the persona photo (close-up and full body side by side). Valid for one hour.","type":"string","nullable":true},"eta":{"description":"Only while `image_status` is `generating`.","type":"object","required":["started_at","expected_seconds"],"properties":{"started_at":{"description":"ISO 8601 timestamp of when this generation started.","type":"string"},"expected_seconds":{"description":"Typical duration of a generation like this one, `null` until there is history to estimate from.","type":"number","nullable":true}},"nullable":true},"versions":{"description":"Every photo the persona has had, newest first, up to 30. Each generation or edit that finishes adds one and makes it current.","type":"array","items":{"type":"object","required":["id","current","image_url","face_url","feedback","feedback_reason","created_at"],"properties":{"id":{"description":"Pass it to `POST /personas/{id}/versions/{versionId}/restore` to go back to this photo.","type":"string"},"current":{"description":"`true` for the photo the persona uses now.","type":"boolean"},"image_url":{"description":"Signed URL of this version's photo, valid for one hour.","type":"string","nullable":true},"face_url":{"description":"Signed URL of this version's close-up portrait, valid for one hour.","type":"string","nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the photo feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["CARD_NOT_READY"]}}}}}}}}},"/personas/{id}/videos":{"post":{"x-mcp":{"ui":true,"annotations":{"destructiveHint":true}},"tags":["Personas"],"operationId":"createPersonaVideo","summary":"Create a persona video","description":"Starts a video with a saved persona. `type` picks the kind of video; today the only one is `swap`, which keeps the scene, camera, motion and sound of a library video and replaces its main person with the persona. `quality` (default `standard`) and `replace` (default `person`) pick how; `style` (none by default) redraws it in a drawing technique; quote and create with the same `quality` and `style`. `version_id` picks which of the persona's `versions` to use, the current one when left out. Charged per second of the source, plus a small amount per scene where the person appears, even on a workspace with unlimited usage, and refunded automatically if it fails. Picking a `target` never raises the price above the quote.\n\nPrice it first with `GET /personas/swap/quote` and send that `credits`: when the server measures a different price it refuses with `409 PRICE_CHANGED` and the right one in `extra`, so nothing is ever charged above what was confirmed.\n\nResponds `202`. Poll `GET /personas/{id}/videos/{videoId}` every 10 seconds until `ready` or `failed`; the result also lands in the library with an `edit_id` for `POST /renders` and `POST /posts`. `VIDEO_IN_PROGRESS` means this persona is already working on the same version with the same video.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","media_id","credits"],"properties":{"type":{"description":"The kind of video to make; only `swap` is made here.","type":"string","enum":["swap"]},"media_id":{"description":"Library video whose person is replaced.","type":"string"},"credits":{"minimum":0,"description":"The price returned by `GET /personas/swap/quote` for this `media_id` and `quality`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"The price returned by `GET /personas/swap/quote` for this `media_id` and `quality`.","type":"integer"}]},"quality":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]},"replace":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]},"version_id":{"description":"A persona version id from `versions`. Defaults to the current version.","type":"string"},"target":{"description":"Picks who becomes the persona: a person seen in the video, or whoever is filming. Defaults to the main person. Refused with `TARGET_UNSUPPORTED` past the end of the video or on high-quality sources longer than `video_mid_max_seconds`, and with `TARGET_NOT_A_PERSON` when nobody is at that spot.","anyOf":[{"description":"A person seen in the video.","type":"object","required":["seconds","x","y"],"properties":{"seconds":{"minimum":0,"description":"The moment of the source, in seconds, where the person is chosen.","type":"number"},"x":{"minimum":0,"maximum":1,"description":"Horizontal center of the person at that moment, 0 at the left edge and 1 at the right.","type":"number"},"y":{"minimum":0,"maximum":1,"description":"Vertical center of the person at that moment, 0 at the top and 1 at the bottom.","type":"number"},"box":{"description":"The box around the whole person at that moment. Sharper than `x` and `y` alone when people stand close together.","type":"object","required":["x","y","width","height"],"properties":{"x":{"minimum":0,"maximum":1,"description":"Left edge of the person, 0 to 1 across the picture.","type":"number"},"y":{"minimum":0,"maximum":1,"description":"Top edge of the person, 0 to 1 down the picture.","type":"number"},"width":{"exclusiveMinimum":0,"maximum":1,"description":"Width of the person, as a share of the picture's width.","type":"number"},"height":{"exclusiveMinimum":0,"maximum":1,"description":"Height of the person, as a share of the picture's height.","type":"number"}}}}},{"description":"Whoever is filming.","type":"object","required":["camera"],"properties":{"seconds":{"minimum":0,"description":"A moment where whoever films shows their face, if they turn the camera to themselves. Found automatically when left out.","type":"number"},"camera":{"description":"Replaces whoever holds the camera in a first-person video: their hands, arms and anything of their body in view, and their face wherever the camera turns to them. Nobody new is added to the scene.","type":"boolean","enum":[true]}}}]}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["type","media_id","credits"],"properties":{"type":{"description":"The kind of video to make; only `swap` is made here.","type":"string","enum":["swap"]},"media_id":{"description":"Library video whose person is replaced.","type":"string"},"credits":{"minimum":0,"description":"The price returned by `GET /personas/swap/quote` for this `media_id` and `quality`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"The price returned by `GET /personas/swap/quote` for this `media_id` and `quality`.","type":"integer"}]},"quality":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]},"replace":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]},"version_id":{"description":"A persona version id from `versions`. Defaults to the current version.","type":"string"},"target":{"description":"Picks who becomes the persona: a person seen in the video, or whoever is filming. Defaults to the main person. Refused with `TARGET_UNSUPPORTED` past the end of the video or on high-quality sources longer than `video_mid_max_seconds`, and with `TARGET_NOT_A_PERSON` when nobody is at that spot.","anyOf":[{"description":"A person seen in the video.","type":"object","required":["seconds","x","y"],"properties":{"seconds":{"minimum":0,"description":"The moment of the source, in seconds, where the person is chosen.","type":"number"},"x":{"minimum":0,"maximum":1,"description":"Horizontal center of the person at that moment, 0 at the left edge and 1 at the right.","type":"number"},"y":{"minimum":0,"maximum":1,"description":"Vertical center of the person at that moment, 0 at the top and 1 at the bottom.","type":"number"},"box":{"description":"The box around the whole person at that moment. Sharper than `x` and `y` alone when people stand close together.","type":"object","required":["x","y","width","height"],"properties":{"x":{"minimum":0,"maximum":1,"description":"Left edge of the person, 0 to 1 across the picture.","type":"number"},"y":{"minimum":0,"maximum":1,"description":"Top edge of the person, 0 to 1 down the picture.","type":"number"},"width":{"exclusiveMinimum":0,"maximum":1,"description":"Width of the person, as a share of the picture's width.","type":"number"},"height":{"exclusiveMinimum":0,"maximum":1,"description":"Height of the person, as a share of the picture's height.","type":"number"}}}}},{"description":"Whoever is filming.","type":"object","required":["camera"],"properties":{"seconds":{"minimum":0,"description":"A moment where whoever films shows their face, if they turn the camera to themselves. Found automatically when left out.","type":"number"},"camera":{"description":"Replaces whoever holds the camera in a first-person video: their hands, arms and anything of their body in view, and their face wherever the camera turns to them. Nobody new is added to the scene.","type":"boolean","enum":[true]}}}]}}}},"multipart/form-data":{"schema":{"type":"object","required":["type","media_id","credits"],"properties":{"type":{"description":"The kind of video to make; only `swap` is made here.","type":"string","enum":["swap"]},"media_id":{"description":"Library video whose person is replaced.","type":"string"},"credits":{"minimum":0,"description":"The price returned by `GET /personas/swap/quote` for this `media_id` and `quality`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"The price returned by `GET /personas/swap/quote` for this `media_id` and `quality`.","type":"integer"}]},"quality":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]},"replace":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]},"version_id":{"description":"A persona version id from `versions`. Defaults to the current version.","type":"string"},"target":{"description":"Picks who becomes the persona: a person seen in the video, or whoever is filming. Defaults to the main person. Refused with `TARGET_UNSUPPORTED` past the end of the video or on high-quality sources longer than `video_mid_max_seconds`, and with `TARGET_NOT_A_PERSON` when nobody is at that spot.","anyOf":[{"description":"A person seen in the video.","type":"object","required":["seconds","x","y"],"properties":{"seconds":{"minimum":0,"description":"The moment of the source, in seconds, where the person is chosen.","type":"number"},"x":{"minimum":0,"maximum":1,"description":"Horizontal center of the person at that moment, 0 at the left edge and 1 at the right.","type":"number"},"y":{"minimum":0,"maximum":1,"description":"Vertical center of the person at that moment, 0 at the top and 1 at the bottom.","type":"number"},"box":{"description":"The box around the whole person at that moment. Sharper than `x` and `y` alone when people stand close together.","type":"object","required":["x","y","width","height"],"properties":{"x":{"minimum":0,"maximum":1,"description":"Left edge of the person, 0 to 1 across the picture.","type":"number"},"y":{"minimum":0,"maximum":1,"description":"Top edge of the person, 0 to 1 down the picture.","type":"number"},"width":{"exclusiveMinimum":0,"maximum":1,"description":"Width of the person, as a share of the picture's width.","type":"number"},"height":{"exclusiveMinimum":0,"maximum":1,"description":"Height of the person, as a share of the picture's height.","type":"number"}}}}},{"description":"Whoever is filming.","type":"object","required":["camera"],"properties":{"seconds":{"minimum":0,"description":"A moment where whoever films shows their face, if they turn the camera to themselves. Found automatically when left out.","type":"number"},"camera":{"description":"Replaces whoever holds the camera in a first-person video: their hands, arms and anything of their body in view, and their face wherever the camera turns to them. Nobody new is added to the scene.","type":"boolean","enum":[true]}}}]}}}}}},"responses":{"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","status","credits_charged"],"properties":{"id":{"description":"Persona video id.","type":"string"},"status":{"type":"string","enum":["processing"]},"credits_charged":{"description":"Credits debited now. Refunded automatically if the video fails.","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_DURATION_OUT_OF_RANGE","VIDEO_UNSUPPORTED","TARGET_UNSUPPORTED","TARGET_NOT_A_PERSON","STYLE_UNSUPPORTED","STYLE_REQUIRED"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","scope","is_owner","top_up_url"],"properties":{"credits_needed":{"type":"number"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"description":"`true` if the key's user can buy credits for this workspace; otherwise ask its owner.","type":"boolean"},"top_up_url":{"description":"Page where credits are bought, for the workspace selected in the app.","type":"string"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND","VERSION_NOT_FOUND","MEDIA_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRICE_CHANGED","VIDEO_IN_PROGRESS"]},"extra":{"description":"Only on `PRICE_CHANGED`.","type":"object","required":["credits","seconds"],"properties":{"credits":{"description":"The server's price, to confirm and send again.","type":"number"},"seconds":{"description":"Measured duration of the video.","type":"number"}}}}}}}},"502":{"description":"Response for status 502","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNAVAILABLE"]}}}}}}}},"get":{"x-mcp":{"ui":true},"tags":["Personas"],"operationId":"listPersonaVideos","summary":"List a persona's videos","description":"Returns the videos made with this persona, newest first, with signed download URLs for the finished ones. `version_id` keeps only the videos made from that version.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}},{"name":"version_id","in":"query","required":false,"schema":{"description":"Only the videos made from this persona version.","type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["videos","pagination"],"properties":{"videos":{"type":"array","items":{"type":"object","required":["id","type","quality","replace","style","status","version_id","duration_seconds","credits_charged","edit_id","download_url","thumbnail_url","expected_seconds","error_code","feedback","feedback_reason","created_at"],"properties":{"id":{"type":"string"},"type":{"default":"swap","description":"What kind of video this is. `swap` replaces the person in a library video with the persona; `product` is a product ad the persona talks in, made on the web app.","type":"string","enum":["swap","product","motion","control"]},"quality":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]},"replace":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"],"nullable":true},"status":{"type":"string","enum":["processing","ready","failed"]},"version_id":{"description":"The persona version (from the persona's `versions`) whose photo the video was made from.","type":"string","nullable":true},"duration_seconds":{"description":"Measured duration of the source video, which is what was priced.","type":"number"},"credits_charged":{"description":"Credits debited for this video. Refunded automatically when it fails.","type":"number"},"edit_id":{"description":"Edit created from the result, ready for `POST /renders` and `POST /posts`. Set once `ready`.","type":"string","nullable":true},"download_url":{"description":"Signed URL of the resulting MP4, valid for six hours. Set once `ready`; once handed out, the video counts as downloaded and its credits can no longer be asked back.","type":"string","nullable":true},"thumbnail_url":{"description":"Signed URL of the cover image, valid for six hours.","type":"string","nullable":true},"expected_seconds":{"description":"Expected seconds from `created_at` until the video is ready, refined as the job advances. Only while `processing`.","type":"number","nullable":true},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the video feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}}}}}}}}},"/personas/{id}/videos/{videoId}":{"get":{"x-mcp":{"ui":true},"tags":["Personas"],"operationId":"getPersonaVideo","summary":"Get a persona video","description":"Returns one persona video. Poll it every 10 seconds while `status` is `processing`; `download_url` is set once `ready`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"videoId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","type","quality","replace","style","status","version_id","duration_seconds","credits_charged","edit_id","download_url","thumbnail_url","expected_seconds","error_code","feedback","feedback_reason","created_at"],"properties":{"id":{"type":"string"},"type":{"default":"swap","description":"What kind of video this is. `swap` replaces the person in a library video with the persona; `product` is a product ad the persona talks in, made on the web app.","type":"string","enum":["swap","product","motion","control"]},"quality":{"description":"`economy` is `standard` at a lower resolution, upscaled to 1080p, and the cheapest. `standard` follows the persona's traits, up to `video_limits.standard.max_seconds`. `high` also follows the persona's photos, keeps the face closest to them and takes longer videos, at a higher price; prefer it for personas made from face photos.","type":"string","enum":["economy","standard","high"]},"replace":{"description":"What of the video's main person becomes the persona: `head` changes only the head and hair and keeps the body and outfit, `person` replaces the whole person, body and outfit included, `none` replaces nobody and only applies the `style`, which then is required.","type":"string","enum":["head","person","none"]},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"],"nullable":true},"status":{"type":"string","enum":["processing","ready","failed"]},"version_id":{"description":"The persona version (from the persona's `versions`) whose photo the video was made from.","type":"string","nullable":true},"duration_seconds":{"description":"Measured duration of the source video, which is what was priced.","type":"number"},"credits_charged":{"description":"Credits debited for this video. Refunded automatically when it fails.","type":"number"},"edit_id":{"description":"Edit created from the result, ready for `POST /renders` and `POST /posts`. Set once `ready`.","type":"string","nullable":true},"download_url":{"description":"Signed URL of the resulting MP4, valid for six hours. Set once `ready`; once handed out, the video counts as downloaded and its credits can no longer be asked back.","type":"string","nullable":true},"thumbnail_url":{"description":"Signed URL of the cover image, valid for six hours.","type":"string","nullable":true},"expected_seconds":{"description":"Expected seconds from `created_at` until the video is ready, refined as the job advances. Only while `processing`.","type":"number","nullable":true},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"feedback_reason":{"description":"Set with a `down` vote; one of the video feedback reasons.","type":"string","nullable":true},"created_at":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["VIDEO_NOT_FOUND"]}}}}}}}}},"/personas/{id}/shots/product":{"post":{"tags":["Personas"],"operationId":"readPersonaShotProduct","summary":"Read a product from its page link","description":"Free. Reads a product page (most online stores, Shopee and Amazon Brazil) and returns its name, description, price and brand, and keeps up to 3 of its photos, whose ids go in `product.photo_ids` of `POST /personas/{id}/shots`. `partial` is `true` when the price or the photos did not come. `PRODUCT_NOT_READABLE` means the page could not be read (Mercado Livre and TikTok Shop never are): upload the photos with `POST /personas/{id}/shots/photos` and write the fields yourself. Up to 5 reads per minute.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"minLength":1,"maxLength":2048,"description":"Link to the product page.","type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["url"],"properties":{"url":{"minLength":1,"maxLength":2048,"description":"Link to the product page.","type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["url"],"properties":{"url":{"minLength":1,"maxLength":2048,"description":"Link to the product page.","type":"string"}}}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["product","photo_ids","partial"],"properties":{"product":{"type":"object","required":["name","description","price","brand"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"price":{"type":"string"},"brand":{"type":"string","nullable":true}}},"photo_ids":{"type":"array","items":{"type":"string"}},"partial":{"type":"boolean"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRODUCT_URL_INVALID"]}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND"]}}}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRODUCT_NOT_READABLE"]}}}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PRODUCT_RATE_LIMITED"]}}}}}}}}},"/personas/{id}/shots/photos":{"post":{"x-mcp":{"localFiles":true},"tags":["Personas"],"operationId":"uploadPersonaShotPhoto","summary":"Upload a product photo","description":"Sends one photo of a product as `multipart/form-data`. JPEG, PNG, WebP or HEIC up to 10 MB; a sharp photo with the label facing the camera gives the most faithful result. `rights_confirmed` must be `true`: the user states they may use the product and the photo. Pass the returned `id` in `product.photo_ids` of `POST /personas/{id}/shots` within 24 hours.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","required":["photo","rights_confirmed"],"properties":{"photo":{"description":"The image file.","type":"string","format":"binary"},"rights_confirmed":{"description":"Confirms the user may use the product and this photo.","type":"string","enum":["true"]}}}}},"required":true},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"description":"Product photo id, for `product.photo_ids`.","type":"string"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_IMAGE"]}}}}}}}}},"/personas/{id}/shots":{"post":{"x-mcp":{"annotations":{"destructiveHint":true}},"tags":["Personas"],"operationId":"createPersonaShot","summary":"Create a persona photo","description":"Draws a saved persona into a ready `template` scene or into a `scene` you write, optionally holding a product from `product.photo_ids`. A template also decides what the persona does with the product: it is held up to the camera, or used with one hand on `street`. A written `scene` replaces the template, and there `product.action` is `show` (holds it up to the camera, the default) or `use` (uses it with one hand); with neither, a template is picked at random. A written scene that needs both hands on the product (spreading, pouring, opening, eating) is refused with `SCENE_ACTION_UNSUPPORTED` before anything is charged. Costs `pricing.scene_photo_credits` of `GET /personas/catalog`, twice that with a `style`, even on a workspace with unlimited usage, and is refunded automatically if it fails; send that price in `credits`, or the server answers `409 PRICE_CHANGED` with the right one in `extra`.\n\nResponds `202`. Poll `GET /personas/{id}/shots/{shotId}` every 5 seconds until `ready` or `failed`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["aspect_ratio","credits"],"properties":{"template":{"default":"mirror","description":"A ready scene: `mirror` mirror selfie, `kitchen` home kitchen, `bathroom` by the bathroom sink, `sofa` on the living room sofa, `cafe` at a café table, `gym` on a gym bench, `street` walking down a city street, `closeup` close selfie with the product near the face, `story` talking to the front camera, `bedroom` on the edge of the bed.","type":"string","enum":["mirror","kitchen","bathroom","sofa","cafe","gym","street","closeup","story","bedroom"]},"scene":{"minLength":3,"maxLength":500,"description":"Where the persona is and what they do, in any language. Replaces `template`.","type":"string"},"aspect_ratio":{"default":"9:16","type":"string","enum":["9:16","4:5","1:1","16:9"]},"credits":{"minimum":0,"description":"The price from `GET /personas/catalog`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"The price from `GET /personas/catalog`.","type":"integer"}]},"version_id":{"description":"A persona version id from `versions`. Defaults to the current version.","type":"string"},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]},"product":{"type":"object","required":["name","photo_ids"],"properties":{"name":{"maxLength":120,"type":"string"},"description":{"maxLength":600,"type":"string"},"price":{"maxLength":40,"type":"string"},"action":{"description":"Only with a written `scene`; a template decides it.","type":"string","enum":["show","use"]},"photo_ids":{"minItems":1,"maxItems":3,"description":"Ids from `POST /personas/{id}/shots/product` or `POST /personas/{id}/shots/photos`.","type":"array","items":{"type":"string"}}}}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["aspect_ratio","credits"],"properties":{"template":{"default":"mirror","description":"A ready scene: `mirror` mirror selfie, `kitchen` home kitchen, `bathroom` by the bathroom sink, `sofa` on the living room sofa, `cafe` at a café table, `gym` on a gym bench, `street` walking down a city street, `closeup` close selfie with the product near the face, `story` talking to the front camera, `bedroom` on the edge of the bed.","type":"string","enum":["mirror","kitchen","bathroom","sofa","cafe","gym","street","closeup","story","bedroom"]},"scene":{"minLength":3,"maxLength":500,"description":"Where the persona is and what they do, in any language. Replaces `template`.","type":"string"},"aspect_ratio":{"default":"9:16","type":"string","enum":["9:16","4:5","1:1","16:9"]},"credits":{"minimum":0,"description":"The price from `GET /personas/catalog`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"The price from `GET /personas/catalog`.","type":"integer"}]},"version_id":{"description":"A persona version id from `versions`. Defaults to the current version.","type":"string"},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]},"product":{"type":"object","required":["name","photo_ids"],"properties":{"name":{"maxLength":120,"type":"string"},"description":{"maxLength":600,"type":"string"},"price":{"maxLength":40,"type":"string"},"action":{"description":"Only with a written `scene`; a template decides it.","type":"string","enum":["show","use"]},"photo_ids":{"minItems":1,"maxItems":3,"description":"Ids from `POST /personas/{id}/shots/product` or `POST /personas/{id}/shots/photos`.","type":"array","items":{"type":"string"}}}}}}},"multipart/form-data":{"schema":{"type":"object","required":["aspect_ratio","credits"],"properties":{"template":{"default":"mirror","description":"A ready scene: `mirror` mirror selfie, `kitchen` home kitchen, `bathroom` by the bathroom sink, `sofa` on the living room sofa, `cafe` at a café table, `gym` on a gym bench, `street` walking down a city street, `closeup` close selfie with the product near the face, `story` talking to the front camera, `bedroom` on the edge of the bed.","type":"string","enum":["mirror","kitchen","bathroom","sofa","cafe","gym","street","closeup","story","bedroom"]},"scene":{"minLength":3,"maxLength":500,"description":"Where the persona is and what they do, in any language. Replaces `template`.","type":"string"},"aspect_ratio":{"default":"9:16","type":"string","enum":["9:16","4:5","1:1","16:9"]},"credits":{"minimum":0,"description":"The price from `GET /personas/catalog`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"The price from `GET /personas/catalog`.","type":"integer"}]},"version_id":{"description":"A persona version id from `versions`. Defaults to the current version.","type":"string"},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"]},"product":{"type":"object","required":["name","photo_ids"],"properties":{"name":{"maxLength":120,"type":"string"},"description":{"maxLength":600,"type":"string"},"price":{"maxLength":40,"type":"string"},"action":{"description":"Only with a written `scene`; a template decides it.","type":"string","enum":["show","use"]},"photo_ids":{"minItems":1,"maxItems":3,"description":"Ids from `POST /personas/{id}/shots/product` or `POST /personas/{id}/shots/photos`.","type":"array","items":{"type":"string"}}}}}}}}},"responses":{"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"type":"object","required":["id","status","credits_charged"],"properties":{"id":{"description":"Persona photo id.","type":"string"},"status":{"type":"string","enum":["processing"]},"credits_charged":{"type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SCENE_ACTION_UNSUPPORTED"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","scope","is_owner","top_up_url"],"properties":{"credits_needed":{"type":"number"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"description":"`true` if the key's user can buy credits for this workspace; otherwise ask its owner.","type":"boolean"},"top_up_url":{"description":"Page where credits are bought, for the workspace selected in the app.","type":"string"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["PERSONA_NOT_FOUND","VERSION_NOT_FOUND","PHOTO_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["PRICE_CHANGED"]},"extra":{"type":"object","required":["credits"],"properties":{"credits":{"description":"The server's price, to confirm and send again.","type":"number"}}}}}}}},"502":{"description":"Response for status 502","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNAVAILABLE"]}}}}}}}},"get":{"tags":["Personas"],"operationId":"listPersonaShots","summary":"List a persona's photos","description":"Returns the photos made with this persona, newest first, with signed image URLs for the finished ones.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["shots","pagination"],"properties":{"shots":{"type":"array","items":{"type":"object","required":["id","status","version_id","scene","template","product","style","aspect_ratio","credits_charged","image_url","expected_seconds","error_code","feedback","created_at"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["processing","ready","failed"]},"version_id":{"description":"The persona version whose photo the shot was drawn from.","type":"string","nullable":true},"scene":{"description":"The scene the user wrote; empty when a `template` was used.","type":"string"},"template":{"default":"mirror","type":"string","enum":["mirror","kitchen","bathroom","sofa","cafe","gym","street","closeup","story","bedroom"],"nullable":true},"product":{"type":"object","required":["name","description","price","action","photo_ids"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"price":{"type":"string"},"action":{"default":"show","type":"string","enum":["show","use"]},"photo_ids":{"type":"array","items":{"type":"string"}}},"nullable":true},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"],"nullable":true},"aspect_ratio":{"default":"9:16","type":"string","enum":["9:16","4:5","1:1","16:9"]},"credits_charged":{"description":"Credits debited for this photo. Refunded automatically when it fails.","type":"number"},"image_url":{"description":"Signed URL of the JPEG, valid for one hour. Set once `ready`.","type":"string","nullable":true},"expected_seconds":{"description":"Typical seconds from `created_at` until a photo is ready. Only while `processing`.","type":"number","nullable":true},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"created_at":{"type":"string"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}}}}}}}}},"/personas/{id}/shots/{shotId}":{"get":{"tags":["Personas"],"operationId":"getPersonaShot","summary":"Get a persona photo","description":"Returns one persona photo. Poll it every 5 seconds while `status` is `processing`; `image_url` is set once `ready`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"shotId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","status","version_id","scene","template","product","style","aspect_ratio","credits_charged","image_url","expected_seconds","error_code","feedback","created_at"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["processing","ready","failed"]},"version_id":{"description":"The persona version whose photo the shot was drawn from.","type":"string","nullable":true},"scene":{"description":"The scene the user wrote; empty when a `template` was used.","type":"string"},"template":{"default":"mirror","type":"string","enum":["mirror","kitchen","bathroom","sofa","cafe","gym","street","closeup","story","bedroom"],"nullable":true},"product":{"type":"object","required":["name","description","price","action","photo_ids"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"price":{"type":"string"},"action":{"default":"show","type":"string","enum":["show","use"]},"photo_ids":{"type":"array","items":{"type":"string"}}},"nullable":true},"style":{"description":"Redraws the whole video, people and scene, in an animation, illustration, material or camera look while keeping its camera and motion, for example `cel` (hand-painted 2D animation), `felt` (felt puppet stop motion), `toy` (rounded toy 3D), `pixel` (pixel art), `stainedglass` (stained glass) or `silent` (1920s silent film). The whole person is replaced, whatever `replace` says, unless it is `none`. Not available at `quality: high` past `video_mid_max_seconds`.","type":"string","enum":["cel","felt","yarn","sketch","toy","grotesque","painterly","graphic","gouache","sculptural","lowpoly","toon","cinematic","flat","neon","editorial","comic","pixel","plush","embroidery","mosaic","stainedglass","chalk","silent","thermal","hologram"],"nullable":true},"aspect_ratio":{"default":"9:16","type":"string","enum":["9:16","4:5","1:1","16:9"]},"credits_charged":{"description":"Credits debited for this photo. Refunded automatically when it fails.","type":"number"},"image_url":{"description":"Signed URL of the JPEG, valid for one hour. Set once `ready`.","type":"string","nullable":true},"expected_seconds":{"description":"Typical seconds from `created_at` until a photo is ready. Only while `processing`.","type":"number","nullable":true},"error_code":{"default":"MEDIA_REJECTED","description":"Why the last generation failed, `null` otherwise: `COPYRIGHT_BLOCKED` (the scene looks like copyrighted material), `REAL_FACES_BLOCKED` (a real face is too prominent), `SAFETY_BLOCKED` (the provider's content rules) and `MEDIA_REJECTED` (refused for another reason); for any refusal change the traits, the photos or the video. `MEDIA_FAILED` and `MEDIA_UNAVAILABLE` (generation broke, retry), `INSUFFICIENT_CREDITS`, `TIMEOUT`, `OUTPUT_CHECK_FAILED` (the video did not keep the persona on the right person even after one free redo; try another video or pick the person). Credits of a failed generation are refunded automatically.","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"feedback":{"description":"`up` liked, `down` disliked, `null` not rated.","nullable":true,"type":"string","enum":["up","down"]},"created_at":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["SHOT_NOT_FOUND"]}}}}}}}}},"/generations/models":{"get":{"tags":["Generations"],"operationId":"listGenerationModels","summary":"List image and video models and their prices","description":"Every image and video model CutPro generates with right now (Veo, Kling, Seedance, Wan, Nano Banana, GPT Image and more), with the modes, resolutions, durations and aspect ratios each one accepts and its price in credits. Prices follow what the models cost and can change at any time, so read them from here before `POST /generations`. When the user names no model, use `presets`: the recommended model for each quality level.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["models","presets","prompt_max","max_running"],"properties":{"models":{"type":"array","items":{"type":"object","required":["id","name","kind","modes","resolutions","seconds","aspect_ratios","audio","max_images","refuses","prices"],"properties":{"id":{"description":"Value for `model`.","type":"string"},"name":{"type":"string"},"kind":{"default":"image","type":"string","enum":["image","video"]},"modes":{"type":"array","items":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]}},"resolutions":{"type":"array","items":{"type":"string"}},"seconds":{"description":"Durations a video accepts; empty for an image.","type":"array","items":{"type":"number"}},"aspect_ratios":{"description":"Empty when the model takes any of them.","type":"array","items":{"default":"21:9","type":"string","enum":["21:9","16:9","3:2","4:3","5:4","1:1","4:5","3:4","2:3","9:16"]}},"audio":{"description":"`always`: the video always has sound. `optional`: `audio: false` leaves it out, usually for less. Null: silent.","nullable":true,"type":"string","enum":["always","optional"]},"max_images":{"description":"Most images one request takes.","type":"number"},"refuses":{"description":"What the model refuses to show.","type":"array","items":{"default":"real_faces","type":"string","enum":["real_faces","minors","public_figures"]}},"prices":{"type":"array","items":{"type":"object","required":["mode","resolution","credits","silent_credits"],"properties":{"mode":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]},"resolution":{"type":"string"},"credits":{"description":"Per second of video, or per image.","type":"number"},"silent_credits":{"type":"number","description":"Per second without sound; null where sound cannot be left out.","nullable":true}}}}}}},"presets":{"type":"object","required":["video","image"],"properties":{"video":{"type":"array","items":{"type":"object","required":["id","model","resolution"],"properties":{"id":{"default":"fast","type":"string","enum":["fast","balanced","best"]},"model":{"type":"string"},"resolution":{"type":"string"}}}},"image":{"type":"array","items":{"type":"object","required":["id","model","resolution"],"properties":{"id":{"default":"fast","type":"string","enum":["fast","balanced","best"]},"model":{"type":"string"},"resolution":{"type":"string"}}}}}},"prompt_max":{"description":"Longest `prompt`, in characters.","type":"number"},"max_running":{"description":"Generations one workspace may have running at once.","type":"number"}},"additionalProperties":false}}}}}}},"/generations/images":{"post":{"x-mcp":{"localFiles":true},"tags":["Generations"],"operationId":"uploadGenerationImage","summary":"Upload a reference image","description":"Sends one image as `multipart/form-data`, to animate it, use it as a first or last frame, or borrow a person, product or style from it. It goes to the workspace library and counts toward its storage. Pass the returned `id` in `image_ids` of `POST /generations`. An image CutPro generated needs no upload: its `output.image_id` works the same.","security":[{"apiKey":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","required":["image"],"properties":{"image":{"description":"The image file.","type":"string","format":"binary"}}}}},"required":true},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"description":"Image id, for `image_ids`.","type":"string"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["INVALID_IMAGE"]}}}}}},"406":{"description":"Response for status 406","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["STORAGE_LIMIT_EXCEEDED"]}}}}}}}}},"/generations":{"post":{"x-mcp":{"ui":true,"annotations":{"destructiveHint":true}},"tags":["Generations"],"operationId":"createGeneration","summary":"Generate an image or a video","description":"Generates one image or video with the chosen model from `GET /generations/models`, from a prompt alone or from images. Charges the credits at once; poll `GET /generations/{id}` every 10 seconds until it is `ready` or `failed`, which gives them back.\n\n`credits` is the total price the user agreed to: the model's `credits` for the mode and resolution, times `seconds` for a video (`silent_credits` with `audio: false`). A different current price answers `PRICE_CHANGED` with the new total and charges nothing. Always tell the user the model and the price and wait for their yes before calling this.\n\n`image_ids` come from `POST /generations/images` or from the `output.image_id` of a ready image: none for `text`, one for `image`, two (first, last) for `frames`, and up to the model's `max_images` for `references`.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","model","mode","prompt","aspect_ratio","credits"],"properties":{"kind":{"default":"image","type":"string","enum":["image","video"]},"model":{"maxLength":64,"description":"`id` from `GET /generations/models`.","type":"string"},"mode":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]},"resolution":{"maxLength":8,"description":"One of the model's `resolutions`; the model's default when left out.","type":"string"},"prompt":{"minLength":3,"maxLength":2000,"description":"What to show, in any language.","type":"string"},"seconds":{"minimum":1,"maximum":60,"description":"Required for a video: one of the model's `seconds`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":60,"description":"Required for a video: one of the model's `seconds`.","type":"integer"}]},"aspect_ratio":{"default":"21:9","type":"string","enum":["21:9","16:9","3:2","4:3","5:4","1:1","4:5","3:4","2:3","9:16"]},"audio":{"description":"`false` leaves the sound out of a video whose model has `audio: optional`.","type":"boolean"},"image_ids":{"maxItems":30,"type":"array","items":{"maxLength":24,"type":"string"}},"credits":{"minimum":0,"description":"Total price the user agreed to.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"Total price the user agreed to.","type":"integer"}]}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["kind","model","mode","prompt","aspect_ratio","credits"],"properties":{"kind":{"default":"image","type":"string","enum":["image","video"]},"model":{"maxLength":64,"description":"`id` from `GET /generations/models`.","type":"string"},"mode":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]},"resolution":{"maxLength":8,"description":"One of the model's `resolutions`; the model's default when left out.","type":"string"},"prompt":{"minLength":3,"maxLength":2000,"description":"What to show, in any language.","type":"string"},"seconds":{"minimum":1,"maximum":60,"description":"Required for a video: one of the model's `seconds`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":60,"description":"Required for a video: one of the model's `seconds`.","type":"integer"}]},"aspect_ratio":{"default":"21:9","type":"string","enum":["21:9","16:9","3:2","4:3","5:4","1:1","4:5","3:4","2:3","9:16"]},"audio":{"description":"`false` leaves the sound out of a video whose model has `audio: optional`.","type":"boolean"},"image_ids":{"maxItems":30,"type":"array","items":{"maxLength":24,"type":"string"}},"credits":{"minimum":0,"description":"Total price the user agreed to.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"Total price the user agreed to.","type":"integer"}]}}}},"multipart/form-data":{"schema":{"type":"object","required":["kind","model","mode","prompt","aspect_ratio","credits"],"properties":{"kind":{"default":"image","type":"string","enum":["image","video"]},"model":{"maxLength":64,"description":"`id` from `GET /generations/models`.","type":"string"},"mode":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]},"resolution":{"maxLength":8,"description":"One of the model's `resolutions`; the model's default when left out.","type":"string"},"prompt":{"minLength":3,"maxLength":2000,"description":"What to show, in any language.","type":"string"},"seconds":{"minimum":1,"maximum":60,"description":"Required for a video: one of the model's `seconds`.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"maximum":60,"description":"Required for a video: one of the model's `seconds`.","type":"integer"}]},"aspect_ratio":{"default":"21:9","type":"string","enum":["21:9","16:9","3:2","4:3","5:4","1:1","4:5","3:4","2:3","9:16"]},"audio":{"description":"`false` leaves the sound out of a video whose model has `audio: optional`.","type":"boolean"},"image_ids":{"maxItems":30,"type":"array","items":{"maxLength":24,"type":"string"}},"credits":{"minimum":0,"description":"Total price the user agreed to.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":0,"description":"Total price the user agreed to.","type":"integer"}]}}}}}},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"type":"object","required":["id","status","credits_charged"],"properties":{"id":{"type":"string"},"status":{"type":"string","enum":["processing"]},"credits_charged":{"description":"`0` when the charge was waived.","type":"number"}}}}}},"400":{"description":"Response for status 400","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"default":"MODEL_UNAVAILABLE","type":"string","enum":["MODEL_UNAVAILABLE","MODE_UNSUPPORTED","RESOLUTION_INVALID","SECONDS_INVALID","RATIO_INVALID","IMAGES_INVALID"]}}}}}},"402":{"description":"Response for status 402","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["INSUFFICIENT_CREDITS"]},"extra":{"type":"object","required":["credits_needed","scope","is_owner","top_up_url"],"properties":{"credits_needed":{"type":"number"},"scope":{"type":"string","enum":["workspace","personal"]},"is_owner":{"description":"`true` if the key's user can buy credits for this workspace; otherwise ask its owner.","type":"boolean"},"top_up_url":{"description":"Page where credits are bought, for the workspace selected in the app.","type":"string"}}}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["IMAGE_NOT_FOUND"]}}}}}},"409":{"description":"Response for status 409","content":{"application/json":{"schema":{"type":"object","required":["code","extra"],"properties":{"code":{"type":"string","enum":["PRICE_CHANGED"]},"extra":{"type":"object","required":["credits"],"properties":{"credits":{"description":"Current total price.","type":"number"}}}}}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["TOO_MANY_RUNNING"]}}}}}},"502":{"description":"Response for status 502","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["MEDIA_UNAVAILABLE"]}}}}}}}},"get":{"x-mcp":{"ui":true},"tags":["Generations"],"operationId":"listGenerations","summary":"List generations","description":"The workspace's images and videos generated with `POST /generations`, newest first.","security":[{"apiKey":[]}],"parameters":[{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["image","video"]}},{"name":"page","in":"query","required":false,"schema":{"minimum":1,"description":"Page number (default: 1)","type":"number"}},{"name":"limit","in":"query","required":false,"schema":{"minimum":1,"maximum":100,"description":"Items per page (default: 20, max: 100)","type":"number"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["generations","pagination"],"properties":{"generations":{"type":"array","items":{"type":"object","required":["id","kind","status","model","model_name","mode","resolution","seconds","aspect_ratio","prompt","image_ids","credits_charged","error_code","edit_id","output","expected_seconds","created_at"],"properties":{"id":{"type":"string"},"kind":{"default":"image","type":"string","enum":["image","video"]},"status":{"default":"processing","description":"`processing` until it ends `ready` or `failed`; a failed one gives the credits back.","type":"string","enum":["processing","ready","failed"]},"model":{"type":"string"},"model_name":{"type":"string"},"mode":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]},"resolution":{"type":"string","nullable":true},"seconds":{"type":"number","nullable":true},"aspect_ratio":{"default":"21:9","type":"string","enum":["21:9","16:9","3:2","4:3","5:4","1:1","4:5","3:4","2:3","9:16"]},"prompt":{"type":"string","nullable":true},"image_ids":{"type":"array","items":{"type":"string"}},"credits_charged":{"type":"number"},"error_code":{"default":"MEDIA_REJECTED","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"edit_id":{"type":"string","description":"Set on a ready video: pass it to `POST /posts` to publish or schedule it.","nullable":true},"output":{"type":"object","required":["image_id","url","thumbnail_url"],"properties":{"image_id":{"type":"string","description":"Set on an image: pass it in `image_ids` of `POST /generations` to animate or edit it.","nullable":true},"url":{"description":"Signed preview link, valid for 6 hours.","type":"string"},"thumbnail_url":{"type":"string","nullable":true}},"description":"Set once `ready`, unless the file was deleted from the library.","nullable":true},"expected_seconds":{"type":"number","description":"How long this model usually takes, while `processing`.","nullable":true},"created_at":{"type":"string"}}}},"pagination":{"type":"object","required":["current_page","total_pages","total_count","has_next_page","has_previous_page","limit"],"properties":{"current_page":{"description":"Current page number (1-based)","type":"number"},"total_pages":{"description":"Total number of pages","type":"number"},"total_count":{"description":"Total number of items across all pages","type":"number"},"has_next_page":{"type":"boolean"},"has_previous_page":{"type":"boolean"},"limit":{"description":"Items per page used for this response","type":"number"}}}}}}}}}}},"/generations/{id}":{"get":{"x-mcp":{"ui":true},"tags":["Generations"],"operationId":"getGeneration","summary":"Get a generation","description":"Returns one generation. Poll it every 10 seconds while `status` is `processing`; `output.url` is set once `ready`.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["id","kind","status","model","model_name","mode","resolution","seconds","aspect_ratio","prompt","image_ids","credits_charged","error_code","edit_id","output","expected_seconds","created_at"],"properties":{"id":{"type":"string"},"kind":{"default":"image","type":"string","enum":["image","video"]},"status":{"default":"processing","description":"`processing` until it ends `ready` or `failed`; a failed one gives the credits back.","type":"string","enum":["processing","ready","failed"]},"model":{"type":"string"},"model_name":{"type":"string"},"mode":{"default":"text","description":"`text`: from the prompt alone. `image`: animates one image, the first frame (video only). `frames`: goes from a first to a last image (video only). `references`: borrows a person, product or style from the images, or edits them (image).","type":"string","enum":["text","image","frames","references"]},"resolution":{"type":"string","nullable":true},"seconds":{"type":"number","nullable":true},"aspect_ratio":{"default":"21:9","type":"string","enum":["21:9","16:9","3:2","4:3","5:4","1:1","4:5","3:4","2:3","9:16"]},"prompt":{"type":"string","nullable":true},"image_ids":{"type":"array","items":{"type":"string"}},"credits_charged":{"type":"number"},"error_code":{"default":"MEDIA_REJECTED","type":"string","enum":["MEDIA_REJECTED","COPYRIGHT_BLOCKED","REAL_FACES_BLOCKED","SAFETY_BLOCKED","MEDIA_FAILED","MEDIA_UNAVAILABLE","INSUFFICIENT_CREDITS","TIMEOUT","OUTPUT_CHECK_FAILED"],"nullable":true},"edit_id":{"type":"string","description":"Set on a ready video: pass it to `POST /posts` to publish or schedule it.","nullable":true},"output":{"type":"object","required":["image_id","url","thumbnail_url"],"properties":{"image_id":{"type":"string","description":"Set on an image: pass it in `image_ids` of `POST /generations` to animate or edit it.","nullable":true},"url":{"description":"Signed preview link, valid for 6 hours.","type":"string"},"thumbnail_url":{"type":"string","nullable":true}},"description":"Set once `ready`, unless the file was deleted from the library.","nullable":true},"expected_seconds":{"type":"number","description":"How long this model usually takes, while `processing`.","nullable":true},"created_at":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["GENERATION_NOT_FOUND"]}}}}}}}},"delete":{"tags":["Generations"],"operationId":"deleteGeneration","summary":"Delete a generation","description":"Removes it from the list and its file from the library. One still `processing` cannot be deleted.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Response for status 204"},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["GENERATION_NOT_FOUND"]}}}}}}}}},"/generations/{id}/download":{"get":{"tags":["Generations"],"operationId":"downloadGeneration","summary":"Get the download link of a generation","description":"Signed link that saves the full-quality file, valid for 6 hours. Only for a `ready` generation. Once downloaded, its credits can no longer be asked back.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"404":{"description":"Response for status 404","content":{"application/json":{"schema":{"type":"object","required":["code"],"properties":{"code":{"type":"string","enum":["GENERATION_NOT_FOUND"]}}}}}}}}}},"components":{"schemas":{},"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-Api-Key"}}}}