{"info":{"name":"Kaitoi REST API","description":"Kaitoi's REST API exposes a stable integration surface for projects, editable\nproject documents, graph inspection, node discovery, files, runs, and future\nautomation workflows.\n\n**Authentication**\n\nSend a programmatic API key as `Authorization: Bearer <api_key>`. Keys can be\nscoped with endpoint-specific permissions such as `projects:read`,\n`projects:write`, `templates:read`, `templates:run`, `runs:execute`,\n`graphs:read`, `node_types:read`, `files:read`, and `files:write`.\nAccount credit balance reads require `account_credits:read`.\n\nKaitoi has two API key usage modes:\n\n- **Backend service keys** are the default for trusted code: your backend,\n  CLI tools, desktop apps, scripts, workers, and CI jobs. These keys are\n  bearer secrets and should not be shipped in browser JavaScript.\n- **Browser app keys** are for direct calls from frontend JavaScript. They\n  must be attached to a Developer App with explicit allowed origins. The\n  origin check lets browsers call the public REST API only from those\n  registered origins, but it is not a substitute for keeping sensitive secrets\n  on a trusted server. Browser keys are visible to end users, so prefer\n  read-only or narrowly scoped permissions.\n\nFor production web apps, the safest pattern is usually: browser frontend calls\nyour backend, and your backend calls Kaitoi with a Backend service key. Use\nBrowser app keys only when you intentionally want direct browser-to-Kaitoi\ncalls and have chosen scopes and quotas accordingly.\n\n**Base URL**\n\nAll REST API endpoints are served under `/api/v1`. The global FastAPI\ndocumentation endpoints remain disabled in production; this OpenAPI document is\nfiltered to REST API routes only.\n\n**API Artifacts**\n\nThe OpenAPI schema is available at `/api/v1/openapi.json`. A generated Postman\ncollection is available at `/api/v1/postman.json` and stays in sync with this\nschema as the REST API grows.\n\nLLM-friendly documentation is available at `/api/v1/llms.txt`, with a fuller\nMarkdown reference at `/api/v1/llms-full.txt`.\n\n**Rate Limits**\n\nRequests are rate limited per client IP before authentication and per API key\nafter authentication. `429 RATE_LIMITED` responses include a `Retry-After`\nheader and a JSON error body. Production/staging deployments enforce these\nlimits through the shared Redis-backed limiter so quotas apply across backend\ninstances. The default production behavior is fail-closed: if the shared\nlimiter is unavailable, requests return `503 RATE_LIMIT_UNAVAILABLE` with a\nshort `Retry-After` hint so clients back off instead of bypassing quotas.\nOperators can explicitly configure a per-instance local degradation mode for\nenvironments that prefer temporary availability over globally strict quotas.\nLocal development uses an in-process fallback unless Redis rate limiting is\nexplicitly enabled.\n\n**Errors**\n\nErrors use a consistent shape: `{ \"error\": { \"code\", \"message\", \"details\" } }`.\nWhen clients send `X-Request-Id`, the same identifier is echoed as\n`error.requestId` to simplify support and audit correlation.\n\n**Pagination**\n\nList endpoints use opaque keyset cursors. Treat `nextCursor` as an opaque token;\ndo not parse or construct it client-side.\n\n**Project Documents**\n\nUse `/projects/{projectId}/document` as the canonical editable project surface.\n`GET /projects/{projectId}/graph` is a read-oriented view and is not intended\nto be round-tripped back into document writes. Document writes require\n`expectedVersion` for optimistic concurrency and support idempotent retries.\n\n**Lifecycle Deletes**\n\nProject deletion is version-gated and archives the project from the public REST\nsurface. Completed file deletion is blocked while active projects reference the\nfile, and fails closed when a project's public file-reference index is unknown.","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json","version":"1.0.0"},"auth":{"type":"bearer","bearer":[{"key":"token","value":"{{KAITOI_API_KEY}}","type":"string"}]},"variable":[{"key":"KAITOI_BASE_URL","value":"https://api.studio.kaitoi.io"},{"key":"KAITOI_API_KEY","value":"paste-your-api-key-here"}],"item":[{"name":"Account","item":[{"name":"Get account credits","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/account/credits","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","account","credits"],"variable":[],"query":[]},"description":"Returns the authenticated user's current spendable account credit balance and PAYG/subscription breakdown. Requires the `account_credits:read` scope."},"response":[]}]},{"name":"Files","item":[{"name":"Create file upload session","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files/uploads","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files","uploads"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"contentType\": \"image/png\",\n  \"externalId\": \"asset_123\",\n  \"externalUserId\": \"user_789\",\n  \"externalWorkspaceId\": \"team_456\",\n  \"filename\": \"input.png\",\n  \"sha256\": \"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\",\n  \"sizeBytes\": 12345\n}","options":{"raw":{"language":"json"}}},"description":"Creates a direct-to-storage upload session. This endpoint does not upload the file bytes. Use the returned instructions as follows:\n\n1. Send a separate PUT request to `upload.url` using `upload.method` and every header in `upload.headers`. Do not send the API Bearer token to that URL; the signed URL is the temporary upload credential.\n2. After the PUT succeeds, call `POST /files/uploads/{upload_id}/complete` with this response's `uploadId`.\n3. Use the completed response's `fileId` as a file input in later API calls.\n\nFor large files, `storageMethod` may be `multipart`; in that case, PUT each item in `parts` and pass the returned ETags to the complete endpoint. If the session was created with `sha256`, the API verifies the stored object checksum before completion; multipart completions must include `actualSha256`. Use Idempotency-Key so retries return the same reservation and signed URL."},"event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (pm.response.code >= 200 && pm.response.code < 300) {","  const body = pm.response.json();","  if (body.uploadId) pm.collectionVariables.set('KAITOI_UPLOAD_ID', body.uploadId);","  if (body.fileId) pm.collectionVariables.set('KAITOI_FILE_ID', body.fileId);","  if (body.upload && body.upload.url) pm.collectionVariables.set('KAITOI_UPLOAD_URL', body.upload.url);","}"]}}],"response":[]},{"name":"Upload file bytes to signed URL (helper)","request":{"method":"PUT","auth":{"type":"noauth"},"header":[{"key":"Content-Type","value":"paste-content-type-from-upload-headers","description":"Use the exact Content-Type returned in upload.headers."},{"key":"x-amz-checksum-sha256","value":"paste-checksum-header-if-returned","description":"Only enable this header if upload.headers includes x-amz-checksum-sha256.","disabled":true}],"url":{"raw":"paste-upload-url-from-create-upload-session","host":["paste-upload-url-from-create-upload-session"]},"body":{"mode":"file","file":{"src":""}},"description":"Convenience helper for the signed upload URL returned by 'Create file upload session'. Paste the full upload.url into this request URL, set Auth to No Auth, copy every returned upload.headers value exactly, then choose the file under Body > file. This is not a stable Kaitoi endpoint; it targets the per-session signed storage URL."},"response":[]},{"name":"Complete file upload","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files/uploads/:upload_id/complete","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files","uploads",":upload_id","complete"],"variable":[{"key":"upload_id","value":"{{KAITOI_UPLOAD_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"actualSha256\": \"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\",\n  \"actualSizeBytes\": 12345\n}","options":{"raw":{"language":"json"}}},"description":"Verifies that the bytes were uploaded to the signed URL returned by `Create file upload session`, then promotes the object to a durable REST API file record. This call is idempotent by `upload_id`; retrying after a successful completion returns the same file metadata. When the session was created with `sha256`, the API verifies the stored object's SHA-256 before completing it."},"event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (pm.response.code >= 200 && pm.response.code < 300) {","  const body = pm.response.json();","  if (body.fileId) pm.collectionVariables.set('KAITOI_FILE_ID', body.fileId);","}"]}}],"response":[]},{"name":"Abort file upload","request":{"method":"DELETE","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files/uploads/:upload_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files","uploads",":upload_id"],"variable":[{"key":"upload_id","value":"{{KAITOI_UPLOAD_ID}}","description":""}],"query":[]},"description":"Aborts a pending upload session and releases its storage reservation."},"response":[]},{"name":"Get file","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files/:file_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files",":file_id"],"variable":[{"key":"file_id","value":"{{KAITOI_FILE_ID}}","description":""}],"query":[{"key":"externalUserId","value":"","description":"Optional developer-user guard. When provided, the file is returned only if its stored externalUserId matches this value.","disabled":true}]},"description":"Returns metadata for a REST API uploaded file owned by the authenticated account."},"response":[]},{"name":"Get file download URL","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files/:file_id/download-url","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files",":file_id","download-url"],"variable":[{"key":"file_id","value":"{{KAITOI_FILE_ID}}","description":""}],"query":[{"key":"expiresInSeconds","value":"3600","description":"Signed URL lifetime in seconds. Defaults to 3600 and is capped at 86400.","disabled":true},{"key":"externalUserId","value":"","description":"Optional developer-user guard. When provided, a download URL is issued only if the file's stored externalUserId matches this value.","disabled":true}]},"description":"Returns a short-lived signed URL for downloading a REST API uploaded file. The URL is time-limited and should not be stored permanently."},"response":[]},{"name":"Upload small file","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files"],"variable":[],"query":[]},"body":{"mode":"formdata","formdata":[{"key":"file","type":"file","src":""},{"key":"externalId","type":"text","value":""},{"key":"externalUserId","type":"text","value":""},{"key":"externalWorkspaceId","type":"text","value":""}]},"description":"Small-file convenience upload. This route is capped at 25 MB and is deprecated for developer-platform use; prefer POST /files/uploads."},"event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (pm.response.code >= 200 && pm.response.code < 300) {","  const body = pm.response.json();","  if (body.fileId) pm.collectionVariables.set('KAITOI_FILE_ID', body.fileId);","}"]}}],"response":[]},{"name":"Delete file","request":{"method":"DELETE","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/files/:file_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","files",":file_id"],"variable":[{"key":"file_id","value":"{{KAITOI_FILE_ID}}","description":""}],"query":[{"key":"externalUserId","value":"","description":"Optional developer-user guard. When provided, the file is deleted only if its stored externalUserId matches this value.","disabled":true}]},"description":"Deletes a completed REST API file owned by the authenticated account. Deletion is blocked while active saved projects reference the file, and fails closed when any plausible active project has not indexed file references yet."},"response":[]}]},{"name":"Node Types","item":[{"name":"Get node type thumbnail","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/node-type-thumbnails/:node_type","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","node-type-thumbnails",":node_type"],"variable":[{"key":"node_type","value":"","description":""}],"query":[{"key":"token","value":"","description":"Signed thumbnail token returned by nodeTypes.list or nodeTypes.get.","disabled":false},{"key":"index","value":"1","description":"Thumbnail index. 1 is primary; 2 is secondary when available.","disabled":true}]},"description":"Serves a short-lived signed node type thumbnail URL returned by the node type list and detail endpoints. The token in the URL authorizes only this thumbnail; do not send the REST API bearer token to this URL."},"response":[]},{"name":"List node types","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/node-types","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","node-types"],"variable":[],"query":[{"key":"limit","value":"","description":"Maximum number of node types to return. Defaults to 50; capped at 200.","disabled":true},{"key":"cursor","value":"","description":"Opaque cursor returned from the previous page.","disabled":true},{"key":"search","value":"","description":"Smart search over node type, title, category, description, and tags using the shared node catalog ranking.","disabled":true},{"key":"fields","value":"","description":"Optional comma-separated response projection. `type` is always returned. Omit for the existing full summary response.","disabled":true}]},"description":"Returns node types available to the authenticated user. Use this endpoint to discover compatible node identifiers before building automation against a graph."},"response":[]},{"name":"Get node type","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/node-types/:node_type","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","node-types",":node_type"],"variable":[{"key":"node_type","value":"","description":""}],"query":[]},"description":"Returns the public schema for one node type, including its exposed input and output pins. Node type paths are validated before lookup so user-node paths cannot traverse storage boundaries."},"response":[]}]},{"name":"Projects","item":[{"name":"Create project","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"externalId\": \"workspace_123\",\n  \"externalUserId\": \"user_789\",\n  \"externalWorkspaceId\": \"team_456\",\n  \"metadata\": {\n    \"plan\": \"pro\"\n  },\n  \"name\": \"Jane's Workspace\"\n}","options":{"raw":{"language":"json"}}},"description":"Creates an empty saved project for the authenticated API key owner. Use Idempotency-Key so retries do not create duplicate projects."},"response":[]},{"name":"List projects","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects"],"variable":[],"query":[{"key":"limit","value":"","description":"Maximum number of projects to return. Defaults to 50; capped at 200.","disabled":true},{"key":"cursor","value":"","description":"Opaque cursor returned from the previous page.","disabled":true},{"key":"externalId","value":"","description":"Filter by developer-provided external project identifier.","disabled":true},{"key":"externalUserId","value":"","description":"Filter by developer-provided end-user identifier.","disabled":true},{"key":"externalWorkspaceId","value":"","description":"Filter by developer-provided workspace/team identifier.","disabled":true},{"key":"search","value":"","description":"Case-insensitive project-name search.","disabled":true}]},"description":"Returns projects visible to the authenticated API key owner. Results are ordered by most recently updated project first and paginated with opaque keyset cursors."},"response":[]},{"name":"Get project","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Returns public metadata for a single project, including the current project version used by future write endpoints for optimistic concurrency."},"response":[]},{"name":"Update project","request":{"method":"PATCH","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"expectedVersion\": 1,\n  \"externalUserId\": \"user_789\",\n  \"metadata\": {\n    \"plan\": \"enterprise\"\n  },\n  \"name\": \"Jane's Renamed Workspace\"\n}","options":{"raw":{"language":"json"}}},"description":"Updates project display metadata and developer-provided external identifiers using optimistic concurrency."},"response":[]},{"name":"Delete project","request":{"method":"DELETE","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[{"key":"expectedVersion","value":"0","description":"Last project version observed by the client.","disabled":false}]},"description":"Deletes a project from the public REST API surface using optimistic concurrency. The project bundle and metadata are removed from project storage so the project no longer appears in Studio or public REST project lists."},"response":[]},{"name":"Get project document","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/document","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","document"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Returns the canonical editable project document. This shape is designed for developer round trips and uses input maps plus from/to connection tuples, unlike the read-only /graph inspection shape."},"response":[]},{"name":"Replace project document","request":{"method":"PUT","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/document","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","document"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"document\": {\n    \"graph\": {\n      \"connections\": [\n        {\n          \"from\": [\n            \"node_123\",\n            \"text\"\n          ],\n          \"to\": [\n            \"node_456\",\n            \"prompt\"\n          ]\n        }\n      ],\n      \"nodes\": [\n        {\n          \"id\": \"node_123\",\n          \"inputs\": {\n            \"inputPrompt\": {\n              \"type\": \"string\",\n              \"value\": \"A cinematic wide shot\"\n            }\n          },\n          \"position\": {\n            \"x\": 120.0,\n            \"y\": 240.0\n          },\n          \"title\": \"Text Prompt\",\n          \"type\": \"builtin/utils/text_prompt\"\n        }\n      ]\n    }\n  },\n  \"expectedVersion\": 7,\n  \"metadata\": {\n    \"plan\": \"pro\"\n  },\n  \"name\": \"Machine\"\n}","options":{"raw":{"language":"json"}}},"description":"Replaces the editable project document using optimistic concurrency. The public document graph is validated, translated into Studio's internal bundle shape, and saved as a normal project. Use Idempotency-Key so network retries can replay the saved response."},"response":[]},{"name":"Patch project document","request":{"method":"PATCH","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/document","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","document"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"expectedVersion\": 7,\n  \"operations\": [\n    {\n      \"node\": {\n        \"id\": \"node_123\",\n        \"inputs\": {\n          \"inputPrompt\": {\n            \"type\": \"string\",\n            \"value\": \"A cinematic wide shot\"\n          }\n        },\n        \"position\": {\n          \"x\": 120.0,\n          \"y\": 240.0\n        },\n        \"title\": \"Text Prompt\",\n        \"type\": \"builtin/utils/text_prompt\"\n      },\n      \"op\": \"addNode\"\n    },\n    {\n      \"from\": [\n        \"node_123\",\n        \"outputPrompt\"\n      ],\n      \"op\": \"connect\",\n      \"to\": [\n        \"node_456\",\n        \"inputPrompt\"\n      ]\n    }\n  ]\n}","options":{"raw":{"language":"json"}}},"description":"Applies ordered semantic document operations atomically using optimistic concurrency. The resulting document is validated and saved through the same path as PUT /document. Use Idempotency-Key so network retries can replay the saved response."},"response":[]},{"name":"Get project graph","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/graph","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","graph"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Returns a sanitized graph snapshot for a project. Internal metadata, execution history, and private storage paths are intentionally omitted."},"response":[]},{"name":"Get project graph node","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/graph/nodes/:node_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","graph","nodes",":node_id"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""},{"key":"node_id","value":"","description":""}],"query":[{"key":"fields","value":"","description":"Optional comma-separated pins projection: inputs, outputs. Omit for the full sanitized node response.","disabled":true}]},"description":"Returns one sanitized placed node from a project graph. Use fields=inputs,outputs for compact connection-pin discovery. Omit fields for the existing sanitized full graph-node shape."},"response":[]},{"name":"Update project metadata","request":{"method":"PATCH","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/metadata","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","metadata"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"expectedVersion\": 1,\n  \"externalUserId\": \"user_789\",\n  \"metadata\": {\n    \"plan\": \"enterprise\"\n  },\n  \"name\": \"Jane's Renamed Workspace\"\n}","options":{"raw":{"language":"json"}}},"description":"Updates project display metadata and developer-provided external identifiers using optimistic concurrency. Prefer this explicit route for metadata-only updates; PATCH /projects/{project_id} is kept as a compatibility alias."},"response":[]},{"name":"Get project spend","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/spend","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","spend"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Returns actual billed credits from project-attributed ledger transactions. The response does not expose account balances, payment methods, or dollar amounts."},"response":[]}]},{"name":"Runs","item":[{"name":"Create run","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"externalUserId\": \"user_789\",\n  \"inputOverrides\": {\n    \"node_456\": {\n      \"inputImage\": {\n        \"fileId\": \"2f8f8c5df80e4f76a5b7d1bbd6fae0ab.png\",\n        \"type\": \"file\"\n      },\n      \"prompt\": {\n        \"type\": \"string\",\n        \"value\": \"Describe this image\"\n      }\n    }\n  },\n  \"projectId\": \"project_123\",\n  \"targetNodeIds\": [\n    \"node_456\"\n  ]\n}","options":{"raw":{"language":"json"}}},"description":"Accepts a run request for either a saved project (`projectId`) or an inline transient graph (`graph`). The server validates file input references, target nodes, node types, and input pins; snapshots the selected graph source; creates an accepted run record; and dispatches execution asynchronously through the same run lifecycle."},"response":[]},{"name":"Create inline graph run","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs"]},"body":{"mode":"raw","raw":"{\n  \"graph\": {\n    \"nodes\": [\n      {\n        \"id\": \"prompt\",\n        \"type\": \"builtin/utils/text_prompt\",\n        \"inputs\": {\n          \"inputPrompt\": {\n            \"type\": \"string\",\n            \"value\": \"Write a short caption\"\n          }\n        }\n      },\n      {\n        \"id\": \"echo\",\n        \"type\": \"builtin/utils/text\",\n        \"inputs\": {}\n      }\n    ],\n    \"connections\": [\n      {\n        \"from\": [\"prompt\", \"outputPrompt\"],\n        \"to\": [\"echo\", \"inputText\"]\n      }\n    ]\n  },\n  \"targetNodeIds\": [\"echo\"]\n}","options":{"raw":{"language":"json"}}},"description":"Creates a transient inline graph run. Replace node type ids and pin names with values from GET /api/v1/node-types. API keys need node_types:read and runs:execute for this flow."},"response":[]},{"name":"Get run","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs/:run_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs",":run_id"],"variable":[{"key":"run_id","value":"","description":""}],"query":[]},"description":"Returns a REST API run record owned by the authenticated API key owner."},"response":[]},{"name":"Apply run outputs to project","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs/:run_id/apply-to-project","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs",":run_id","apply-to-project"],"variable":[{"key":"run_id","value":"","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"expectedVersion\": 0,\n  \"outputKeys\": \"\"\n}","options":{"raw":{"language":"json"}}},"description":"Persists outputs from a succeeded saved-project run back into that saved project. This is the public API equivalent of saving the server-owned run result state after execution; it does not accept client-supplied output values. The request uses optimistic concurrency and fails if the project changed after the run was created."},"response":[]},{"name":"Cancel run","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs/:run_id/cancel","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs",":run_id","cancel"],"variable":[{"key":"run_id","value":"","description":""}],"query":[]},"description":"Requests cancellation for a REST API run. Accepted or queued runs become terminal canceled immediately; running runs are marked cancelRequested for the execution layer to stop at the next safe point."},"response":[]},{"name":"List run events","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs/:run_id/events","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs",":run_id","events"],"variable":[{"key":"run_id","value":"","description":""}],"query":[{"key":"limit","value":"","description":"Maximum number of events to return. Defaults to 50; capped at 200.","disabled":true},{"key":"cursor","value":"","description":"Opaque cursor returned from the previous page.","disabled":true}]},"description":"Returns persisted lifecycle, progress, and log events for a REST API run. Cursors are opaque and are only valid for the same run and API key owner that issued them."},"response":[]},{"name":"Stream run events","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/runs/:run_id/events/stream","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","runs",":run_id","events","stream"],"variable":[{"key":"run_id","value":"","description":""}],"query":[{"key":"cursor","value":"","description":"Opaque cursor returned by a previous poll page or SSE id.","disabled":true}]},"description":"Streams the same persisted lifecycle, progress, and log events returned by the polling endpoint using Server-Sent Events. The SSE id is an opaque cursor and can be sent back as Last-Event-ID or as the cursor query parameter to resume the stream."},"response":[]}]},{"name":"Storyboards","item":[{"name":"Get project storyboard","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/storyboard","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","storyboard"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Returns the project's current storyboard as a Kaitoi Storyboard Document v1. This is a read-only export of storyboard state."},"response":[]},{"name":"Update project storyboard","request":{"method":"PUT","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/storyboard","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","storyboard"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"document\": {\n    \"kaitoiType\": \"storyboard\",\n    \"name\": \"Storyboard\",\n    \"sequences\": [\n      {\n        \"id\": \"scene-1\",\n        \"name\": \"Scene 1\",\n        \"order\": 0,\n        \"shots\": [\n          {\n            \"description\": \"A quiet establishing shot.\",\n            \"durationSeconds\": 3,\n            \"id\": \"frame-1\",\n            \"order\": 0,\n            \"transition\": \"cut\"\n          }\n        ]\n      }\n    ],\n    \"settings\": {\n      \"aspectRatio\": \"16:9\",\n      \"defaultFrameDuration\": 3\n    },\n    \"version\": 1\n  },\n  \"expectedVersion\": 7,\n  \"mode\": \"replace\"\n}","options":{"raw":{"language":"json"}}},"description":"Applies a Kaitoi Storyboard Document v1 to a saved project using optimistic concurrency. Supports replacing the current storyboard or appending imported scenes. Use Idempotency-Key so network retries can replay the saved response."},"response":[]},{"name":"Get storyboard document schema","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/storyboards/schema/kaitoi-storyboard-document.v1","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","storyboards","schema","kaitoi-storyboard-document.v1"],"variable":[],"query":[]},"description":"Returns the canonical Kaitoi Storyboard Document v1 JSON Schema. This route is unauthenticated so public API clients can validate documents before sending them."},"response":[]},{"name":"Convert storyboard document to timeline document","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/storyboards/to-timeline","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","storyboards","to-timeline"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"defaultDuration\": 3,\n  \"document\": {\n    \"kaitoiType\": \"storyboard\",\n    \"name\": \"Storyboard\",\n    \"sequences\": [\n      {\n        \"id\": \"scene-1\",\n        \"name\": \"Scene 1\",\n        \"order\": 0,\n        \"shots\": [\n          {\n            \"description\": \"A quiet establishing shot.\",\n            \"durationSeconds\": 3,\n            \"id\": \"frame-1\",\n            \"order\": 0,\n            \"transition\": \"cut\"\n          }\n        ]\n      }\n    ],\n    \"settings\": {\n      \"aspectRatio\": \"16:9\",\n      \"defaultFrameDuration\": 3\n    },\n    \"version\": 1\n  },\n  \"frameRate\": 30,\n  \"name\": \"Storyboard Timeline\"\n}","options":{"raw":{"language":"json"}}},"description":"Converts a Kaitoi Storyboard Document v1 into a Kaitoi Timeline Document v1 without mutating any project. Storyboard shots become sequential timeline clips; URL, document, unresolved, and unsupported media references are skipped with warnings instead of being fetched."},"response":[]},{"name":"Validate storyboard document","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/storyboards/validate","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","storyboards","validate"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"document\": {\n    \"kaitoiType\": \"storyboard\",\n    \"name\": \"Storyboard\",\n    \"sequences\": [\n      {\n        \"id\": \"scene-1\",\n        \"name\": \"Scene 1\",\n        \"order\": 0,\n        \"shots\": [\n          {\n            \"description\": \"A quiet establishing shot.\",\n            \"durationSeconds\": 3,\n            \"id\": \"frame-1\",\n            \"order\": 0,\n            \"transition\": \"cut\"\n          }\n        ]\n      }\n    ],\n    \"settings\": {\n      \"aspectRatio\": \"16:9\",\n      \"defaultFrameDuration\": 3\n    },\n    \"version\": 1\n  }\n}","options":{"raw":{"language":"json"}}},"description":"Validates a Kaitoi Storyboard Document v1 against the same schema enforced by the backend."},"response":[]}]},{"name":"Templates","item":[{"name":"List templates","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates"],"variable":[],"query":[{"key":"limit","value":"","description":"Maximum number of templates to return. Defaults to 50; capped at 200.","disabled":true},{"key":"cursor","value":"","description":"Opaque cursor returned from the previous page.","disabled":true},{"key":"hasEndpoint","value":"","description":"Filter by whether a template has at least one active endpoint.","disabled":true},{"key":"search","value":"","description":"Case-insensitive search over template name, description, category, and tags.","disabled":true}]},"description":"Returns user-owned templates visible to the authenticated API key owner. Use `hasEndpoint=true` to discover app-ready templates that already have at least one active endpoint. Use endpoint docs to inspect the external endpoint contract and the owner-authenticated Public API run path."},"response":[]},{"name":"Get template","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates/:template_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates",":template_id"],"variable":[{"key":"template_id","value":"{{KAITOI_TEMPLATE_ID}}","description":""}],"query":[]},"description":"Returns public metadata for one user-owned template, including active endpoint summaries when the template has app-ready endpoints."},"response":[]},{"name":"List template endpoints","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates/:template_id/endpoints","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates",":template_id","endpoints"],"variable":[{"key":"template_id","value":"{{KAITOI_TEMPLATE_ID}}","description":""}],"query":[]},"description":"Returns active external endpoints for a user-owned template. Endpoint API secrets are never returned; use the endpoint docs response to learn the required Authorization header shape."},"response":[]},{"name":"Get template endpoint docs","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates/:template_id/endpoints/:endpoint_id/docs","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates",":template_id","endpoints",":endpoint_id","docs"],"variable":[{"key":"template_id","value":"{{KAITOI_TEMPLATE_ID}}","description":""},{"key":"endpoint_id","value":"{{KAITOI_TEMPLATE_ENDPOINT_ID}}","description":""}],"query":[]},"description":"Returns docs for an active external endpoint on a user-owned template: authentication header shape, submit/status paths, and exposed input and output fields. This does not return endpoint API keys and does not run the endpoint."},"response":[]},{"name":"Run template endpoint","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates/:template_id/endpoints/:endpoint_id/runs","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates",":template_id","endpoints",":endpoint_id","runs"],"variable":[{"key":"template_id","value":"{{KAITOI_TEMPLATE_ID}}","description":""},{"key":"endpoint_id","value":"{{KAITOI_TEMPLATE_ENDPOINT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"externalUserId\": \"user_789\",\n  \"inputs\": {\n    \"image\": {\n      \"fileId\": \"2f8f8c5df80e4f76a5b7d1bbd6fae0ab.png\",\n      \"type\": \"file\"\n    },\n    \"prompt\": {\n      \"type\": \"string\",\n      \"value\": \"A cinematic robot portrait\"\n    }\n  }\n}","options":{"raw":{"language":"json"}}},"description":"Submits an owner-authenticated run for an active endpoint on a user-owned template. The API key user must own the template and endpoint, the key must have `templates:run`, file inputs must reference Public API fileIds, and execution may spend the owner's credits. Use `Idempotency-Key` so network retries do not submit duplicate jobs."},"response":[]},{"name":"Get template endpoint run","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates/:template_id/endpoints/:endpoint_id/runs/:task_id","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates",":template_id","endpoints",":endpoint_id","runs",":task_id"],"variable":[{"key":"template_id","value":"{{KAITOI_TEMPLATE_ID}}","description":""},{"key":"endpoint_id","value":"{{KAITOI_TEMPLATE_ENDPOINT_ID}}","description":""},{"key":"task_id","value":"","description":""}],"query":[]},"description":"Returns a template endpoint run owned by the authenticated API key owner. Polling requires `templates:run` because completed results are part of the execution contract."},"response":[]},{"name":"Stream template endpoint run events","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/templates/:template_id/endpoints/:endpoint_id/runs/:task_id/events/stream","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","templates",":template_id","endpoints",":endpoint_id","runs",":task_id","events","stream"],"variable":[{"key":"template_id","value":"{{KAITOI_TEMPLATE_ID}}","description":""},{"key":"endpoint_id","value":"{{KAITOI_TEMPLATE_ENDPOINT_ID}}","description":""},{"key":"task_id","value":"","description":""}],"query":[]},"description":"Streams compact lifecycle and progress events for an owner-authenticated template endpoint run using Server-Sent Events. This endpoint requires `templates:run` because progress and completed results are part of the execution contract."},"response":[]}]},{"name":"Timelines","item":[{"name":"Get project timeline","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/timeline","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","timeline"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Returns the project's current active timeline as a Kaitoi Timeline Document v1. This is a read-only export of timeline state."},"response":[]},{"name":"Update project timeline","request":{"method":"PUT","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/timeline","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","timeline"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"body":{"mode":"raw","raw":"{\n  \"document\": {\n    \"kaitoiType\": \"timeline\",\n    \"name\": \"Timeline\",\n    \"timeline\": {\n      \"clips\": [\n        {\n          \"duration\": 3,\n          \"filename\": \"hero.png\",\n          \"id\": \"clip-1\",\n          \"name\": \"Hero\",\n          \"opacity\": 100,\n          \"startTime\": 0,\n          \"storageType\": \"data\",\n          \"trackId\": \"track-1\",\n          \"transform\": {\n            \"rotation\": 0,\n            \"scale\": 100,\n            \"x\": 0,\n            \"y\": 0\n          },\n          \"trimEnd\": 0,\n          \"trimStart\": 0,\n          \"type\": \"image\",\n          \"volume\": 100\n        }\n      ],\n      \"currentTime\": 0,\n      \"frameRate\": 30,\n      \"playheadPosition\": 0,\n      \"projectDuration\": 60,\n      \"projectResolution\": {\n        \"height\": 1080,\n        \"isAutoDetected\": true,\n        \"width\": 1920\n      },\n      \"selectedClipIds\": [],\n      \"selectedTrackId\": \"track-1\",\n      \"tracks\": [\n        {\n          \"height\": 60,\n          \"id\": \"track-1\",\n          \"locked\": false,\n          \"mutedAudio\": false,\n          \"mutedVideo\": false,\n          \"name\": \"Track 1\",\n          \"volume\": 1\n        }\n      ],\n      \"zoom\": 100\n    },\n    \"version\": 1\n  },\n  \"expectedVersion\": 7\n}","options":{"raw":{"language":"json"}}},"description":"Replaces a saved project's active timeline with a Kaitoi Timeline Document v1 using optimistic concurrency. Use Idempotency-Key so network retries can replay the saved response. This replaces the whole project timeline; if the project currently has multiple timeline scenes, they are collapsed to the single timeline contained in the document."},"response":[]},{"name":"Export project timeline as OTIO","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/projects/:project_id/timeline/export/otio","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","projects",":project_id","timeline","export","otio"],"variable":[{"key":"project_id","value":"{{KAITOI_PROJECT_ID}}","description":""}],"query":[]},"description":"Exports a saved project's current active timeline as an OpenTimelineIO ZIP bundle. Media references in the OTIO file are portable filenames, not server paths, storage roots, private bucket keys, or signed URLs."},"response":[]},{"name":"Export timeline document as OTIO","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/timelines/export/otio","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","timelines","export","otio"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"document\": {\n    \"kaitoiType\": \"timeline\",\n    \"name\": \"Timeline\",\n    \"timeline\": {\n      \"clips\": [\n        {\n          \"duration\": 3,\n          \"filename\": \"hero.png\",\n          \"id\": \"clip-1\",\n          \"name\": \"Hero\",\n          \"opacity\": 100,\n          \"startTime\": 0,\n          \"storageType\": \"data\",\n          \"trackId\": \"track-1\",\n          \"transform\": {\n            \"rotation\": 0,\n            \"scale\": 100,\n            \"x\": 0,\n            \"y\": 0\n          },\n          \"trimEnd\": 0,\n          \"trimStart\": 0,\n          \"type\": \"image\",\n          \"volume\": 100\n        }\n      ],\n      \"currentTime\": 0,\n      \"frameRate\": 30,\n      \"playheadPosition\": 0,\n      \"projectDuration\": 60,\n      \"projectResolution\": {\n        \"height\": 1080,\n        \"isAutoDetected\": true,\n        \"width\": 1920\n      },\n      \"selectedClipIds\": [],\n      \"selectedTrackId\": \"track-1\",\n      \"tracks\": [\n        {\n          \"height\": 60,\n          \"id\": \"track-1\",\n          \"locked\": false,\n          \"mutedAudio\": false,\n          \"mutedVideo\": false,\n          \"name\": \"Track 1\",\n          \"volume\": 1\n        }\n      ],\n      \"zoom\": 100\n    },\n    \"version\": 1\n  }\n}","options":{"raw":{"language":"json"}}},"description":"Converts a Kaitoi Timeline Document v1 to an OpenTimelineIO ZIP bundle. The ZIP contains `timeline.otio` and any media files the API can resolve from the authenticated account. OTIO media references are portable filenames, never server paths, storage roots, private bucket keys, or signed URLs."},"response":[]},{"name":"Import OTIO to timeline document","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/timelines/import/otio","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","timelines","import","otio"],"variable":[],"query":[]},"body":{"mode":"formdata","formdata":[{"key":"file","type":"file","src":""}]},"description":"Imports an `.otio` file or ZIP bundle into a Kaitoi Timeline Document v1. When media files are present in the ZIP, they are persisted to the authenticated account's library and the returned document references those library filenames. Missing media produces warnings instead of server path leaks."},"response":[]},{"name":"Parse OTIO to timeline document","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/timelines/import/otio/parse","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","timelines","import","otio","parse"],"variable":[],"query":[]},"body":{"mode":"formdata","formdata":[{"key":"file","type":"file","src":""}]},"description":"Parses an `.otio` file or ZIP bundle into a Kaitoi Timeline Document v1 without persisting uploaded media. Returned media references are portable filenames and warnings explain that media was not stored."},"response":[]},{"name":"Get timeline document schema","request":{"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/timelines/schema/kaitoi-timeline-document.v1","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","timelines","schema","kaitoi-timeline-document.v1"],"variable":[],"query":[]},"description":"Returns the canonical Kaitoi Timeline Document v1 JSON Schema. This route is unauthenticated so public API clients can validate documents before sending them."},"response":[]},{"name":"Validate timeline document","request":{"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"url":{"raw":"{{KAITOI_BASE_URL}}/api/v1/timelines/validate","host":["{{KAITOI_BASE_URL}}"],"path":["api","v1","timelines","validate"],"variable":[],"query":[]},"body":{"mode":"raw","raw":"{\n  \"document\": {\n    \"kaitoiType\": \"timeline\",\n    \"name\": \"Timeline\",\n    \"timeline\": {\n      \"clips\": [\n        {\n          \"duration\": 3,\n          \"filename\": \"hero.png\",\n          \"id\": \"clip-1\",\n          \"name\": \"Hero\",\n          \"opacity\": 100,\n          \"startTime\": 0,\n          \"storageType\": \"data\",\n          \"trackId\": \"track-1\",\n          \"transform\": {\n            \"rotation\": 0,\n            \"scale\": 100,\n            \"x\": 0,\n            \"y\": 0\n          },\n          \"trimEnd\": 0,\n          \"trimStart\": 0,\n          \"type\": \"image\",\n          \"volume\": 100\n        }\n      ],\n      \"currentTime\": 0,\n      \"frameRate\": 30,\n      \"playheadPosition\": 0,\n      \"projectDuration\": 60,\n      \"projectResolution\": {\n        \"height\": 1080,\n        \"isAutoDetected\": true,\n        \"width\": 1920\n      },\n      \"selectedClipIds\": [],\n      \"selectedTrackId\": \"track-1\",\n      \"tracks\": [\n        {\n          \"height\": 60,\n          \"id\": \"track-1\",\n          \"locked\": false,\n          \"mutedAudio\": false,\n          \"mutedVideo\": false,\n          \"name\": \"Track 1\",\n          \"volume\": 1\n        }\n      ],\n      \"zoom\": 100\n    },\n    \"version\": 1\n  }\n}","options":{"raw":{"language":"json"}}},"description":"Validates a Kaitoi Timeline Document v1 against the same schema enforced by the backend."},"response":[]}]}]}