{"openapi":"3.0.3","info":{"title":"narrador API","version":"1.0.0","description":"Public REST API for **narrador files** (document → audio) and **narrador X** (X/Twitter post → audio).\n\n## Authentication\n\nSend a user API key on every `/v1` request using either header:\n\n- `Authorization: Bearer <key>`\n- `x-api-key: <key>` (`x-api-key` wins when both are set)\n\nKeys are created in the narrador web app and are scoped by product prefix:\n\n| Product | Key prefix | Scopes |\n| --- | --- | --- |\n| narrador files | `nrd_files_` | `files:read`, `files:write` |\n| narrador X | `nrd_x_` | `x:read`, `x:write` |\n\n`GET /v1/me` accepts any narrador user key. Product routes require the matching prefix.\n\nBrowser sign-in (Google, magic link, Polar checkout) uses Better Auth at `/api/auth` and is **not** part of this reference. Integrators only need user API keys for `/v1`.\n\n## Rate limits\n\nEach API key is limited to **60 verification requests per 60 seconds** (Better Auth API key plugin). Excess traffic returns **429**.\n\nIP-based Express rate limits apply to `/api/auth`, `/admin`, and `/api/trpc` only — not to `/v1`.\n\n## MCP (Model Context Protocol)\n\nA remote MCP server is available at **`POST /mcp`** (Streamable HTTP).\n\n**OAuth (recommended):** add only the server URL in Cursor or Claude Desktop. The client discovers OAuth metadata, opens narrador in your browser, and attaches a Bearer access token after you sign in.\n\n```json\n{\n  \"mcpServers\": {\n    \"narrador\": {\n      \"url\": \"https://api.narrador.io/mcp\"\n    }\n  }\n}\n```\n\nAuthorization server metadata: `/.well-known/oauth-authorization-server` on the narrador web app. Protected resource metadata: `/.well-known/oauth-protected-resource` on this API host.\n\n**Tools:** `get_account`, `list_voices`, `create_files_job`, `get_files_job`, `get_files_result`, `generate_x_audio`, `get_x_generation`.\n\nOAuth tokens are scoped to products you are entitled to (`narrador:files` requires a paid files credit pack; `narrador:x` requires an active narrador X subscription). API keys remain supported via `Authorization: Bearer nrd_files_…` / `nrd_x_…` or `x-api-key`.\n\n### API key (optional)\n\n```json\n{\n  \"mcpServers\": {\n    \"narrador\": {\n      \"url\": \"https://api.narrador.io/mcp\",\n      \"headers\": {\n        \"Authorization\": \"Bearer nrd_files_YOUR_SECRET_KEY\"\n      }\n    }\n  }\n}\n```"},"servers":[{"url":"https://api.narrador.io","description":"narrador API"}],"tags":[{"name":"Account","description":"Identity and credits"},{"name":"narrador files","description":"Voices, uploads, and audio jobs"},{"name":"narrador X","description":"Post audio generations"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"User API key (`nrd_files_…` or `nrd_x_…`)."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"Same user API key as Bearer auth."}},"schemas":{"ApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false},"WordTiming":{"type":"object","required":["word","startTime","endTime"],"properties":{"word":{"type":"string"},"startTime":{"type":"number","format":"float"},"endTime":{"type":"number","format":"float"}}},"PublicApiMe":{"type":"object","required":["user","app","credits"],"properties":{"user":{"type":"object","required":["id","email","name"],"properties":{"id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true}}},"app":{"type":"string","enum":["files","x"]},"credits":{"type":"object","required":["totalAvailable","balances"],"properties":{"totalAvailable":{"type":"number"},"balances":{"type":"array","items":{"type":"object","required":["id","balance","expiresAt"],"properties":{"id":{"type":"string"},"balance":{"type":"number"},"expiresAt":{"type":"string","format":"date-time","nullable":true}}}}}}}},"FilesVoice":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"provider":{"type":"string"},"defaultAccent":{"type":"string"},"isPublic":{"type":"boolean"},"description":{"type":"string","nullable":true},"sampleUrl":{"type":"string","nullable":true}}},"FilesUploadUrl":{"type":"object","properties":{"signedUrl":{"type":"string","format":"uri"},"token":{"type":"string"},"path":{"type":"string"},"fileId":{"type":"string","format":"uuid"}}},"FilesJobCreated":{"type":"object","properties":{"jobId":{"type":"string","format":"uuid"},"projectId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["idle","processing","processed","failed_file_processing","generating","failed_audio_generation","completed"]}}},"FilesJobStatus":{"type":"object","properties":{"jobId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["idle","processing","processed","failed_file_processing","generating","failed_audio_generation","completed"]},"progressPercentage":{"type":"number"},"audioId":{"type":"string","format":"uuid","nullable":true}}},"FilesJobResult":{"type":"object","properties":{"jobId":{"type":"string","format":"uuid"},"audioUrl":{"type":"string","format":"uri"},"audioId":{"type":"string","format":"uuid"},"duration":{"type":"number","nullable":true},"wordTimings":{"type":"array","items":{"$ref":"#/components/schemas/WordTiming"}}}},"FilesJobFromUpload":{"type":"object","required":["fileId","fileName","voiceId","accent"],"properties":{"fileId":{"type":"string","format":"uuid"},"fileName":{"type":"string"},"voiceId":{"type":"string","format":"uuid"},"accent":{"type":"string","enum":["af-za","am-et","ar-ae","ar-eg","ar-iq","ar-kw","ar-ma","ar-qa","ar-sa","az-az","bn-bd","bn-in","cmn-cn","ja-jp","jv-id","kk-kz","km-kh","ko-kr","mn-mn","my-mm","ne-np","ps-af","si-lk","so-so","th-th","vi-vn","zh-cn","zh-hk","zh-tw","yue-cn","bg-bg","bs-ba","ca-es","cs-cz","da-dk","de-de","el-gr","et-ee","eu-es","fi-fi","fr-be","fr-ca","fr-ch","fr-fr","ga-ie","hr-hr","hu-hu","hy-am","is-is","it-it","lt-lt","lv-lv","nb-no","nl-be","nl-nl","pl-pl","pt-br","pt-pt","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-rs","sv-se","tr-tr","uk-ua","en-au","en-ca","en-gb","en-hk","en-ie","en-in","en-ke","en-nz","en-sg","en-us","en-za","es-ar","es-cl","es-co","es-cr","es-cu","es-do","es-ec","es-es","es-mx","es-pe","es-pr","es-py","es-us","es-ve","gu-in","hi-in","kn-in","ml-in","mr-in","pa-in","ta-in","ta-lk","ta-my","te-in","fa-ir","fil-ph","he-il","id-id","ms-my","mt-mt","sw-ke","ur-pk","zu-za"]}}},"FilesJobFromText":{"type":"object","required":["text","voiceId","accent"],"properties":{"text":{"type":"string","maxLength":500000},"fileName":{"type":"string","maxLength":200},"voiceId":{"type":"string","format":"uuid"},"accent":{"type":"string","enum":["af-za","am-et","ar-ae","ar-eg","ar-iq","ar-kw","ar-ma","ar-qa","ar-sa","az-az","bn-bd","bn-in","cmn-cn","ja-jp","jv-id","kk-kz","km-kh","ko-kr","mn-mn","my-mm","ne-np","ps-af","si-lk","so-so","th-th","vi-vn","zh-cn","zh-hk","zh-tw","yue-cn","bg-bg","bs-ba","ca-es","cs-cz","da-dk","de-de","el-gr","et-ee","eu-es","fi-fi","fr-be","fr-ca","fr-ch","fr-fr","ga-ie","hr-hr","hu-hu","hy-am","is-is","it-it","lt-lt","lv-lv","nb-no","nl-be","nl-nl","pl-pl","pt-br","pt-pt","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-rs","sv-se","tr-tr","uk-ua","en-au","en-ca","en-gb","en-hk","en-ie","en-in","en-ke","en-nz","en-sg","en-us","en-za","es-ar","es-cl","es-co","es-cr","es-cu","es-do","es-ec","es-es","es-mx","es-pe","es-pr","es-py","es-us","es-ve","gu-in","hi-in","kn-in","ml-in","mr-in","pa-in","ta-in","ta-lk","ta-my","te-in","fa-ir","fil-ph","he-il","id-id","ms-my","mt-mt","sw-ke","ur-pk","zu-za"]}}},"XGenerationCreate":{"oneOf":[{"type":"object","required":["voiceId","postId"],"properties":{"voiceId":{"type":"string","format":"uuid"},"accent":{"type":"string","enum":["af-za","am-et","ar-ae","ar-eg","ar-iq","ar-kw","ar-ma","ar-qa","ar-sa","az-az","bn-bd","bn-in","cmn-cn","ja-jp","jv-id","kk-kz","km-kh","ko-kr","mn-mn","my-mm","ne-np","ps-af","si-lk","so-so","th-th","vi-vn","zh-cn","zh-hk","zh-tw","yue-cn","bg-bg","bs-ba","ca-es","cs-cz","da-dk","de-de","el-gr","et-ee","eu-es","fi-fi","fr-be","fr-ca","fr-ch","fr-fr","ga-ie","hr-hr","hu-hu","hy-am","is-is","it-it","lt-lt","lv-lv","nb-no","nl-be","nl-nl","pl-pl","pt-br","pt-pt","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-rs","sv-se","tr-tr","uk-ua","en-au","en-ca","en-gb","en-hk","en-ie","en-in","en-ke","en-nz","en-sg","en-us","en-za","es-ar","es-cl","es-co","es-cr","es-cu","es-do","es-ec","es-es","es-mx","es-pe","es-pr","es-py","es-us","es-ve","gu-in","hi-in","kn-in","ml-in","mr-in","pa-in","ta-in","ta-lk","ta-my","te-in","fa-ir","fil-ph","he-il","id-id","ms-my","mt-mt","sw-ke","ur-pk","zu-za"],"default":"en-us"},"postId":{"type":"string"}}},{"type":"object","required":["voiceId","postUrl"],"properties":{"voiceId":{"type":"string","format":"uuid"},"accent":{"type":"string","enum":["af-za","am-et","ar-ae","ar-eg","ar-iq","ar-kw","ar-ma","ar-qa","ar-sa","az-az","bn-bd","bn-in","cmn-cn","ja-jp","jv-id","kk-kz","km-kh","ko-kr","mn-mn","my-mm","ne-np","ps-af","si-lk","so-so","th-th","vi-vn","zh-cn","zh-hk","zh-tw","yue-cn","bg-bg","bs-ba","ca-es","cs-cz","da-dk","de-de","el-gr","et-ee","eu-es","fi-fi","fr-be","fr-ca","fr-ch","fr-fr","ga-ie","hr-hr","hu-hu","hy-am","is-is","it-it","lt-lt","lv-lv","nb-no","nl-be","nl-nl","pl-pl","pt-br","pt-pt","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-rs","sv-se","tr-tr","uk-ua","en-au","en-ca","en-gb","en-hk","en-ie","en-in","en-ke","en-nz","en-sg","en-us","en-za","es-ar","es-cl","es-co","es-cr","es-cu","es-do","es-ec","es-es","es-mx","es-pe","es-pr","es-py","es-us","es-ve","gu-in","hi-in","kn-in","ml-in","mr-in","pa-in","ta-in","ta-lk","ta-my","te-in","fa-ir","fil-ph","he-il","id-id","ms-my","mt-mt","sw-ke","ur-pk","zu-za"],"default":"en-us"},"postUrl":{"type":"string"}}}]},"XGenerationResult":{"type":"object","properties":{"generationId":{"type":"string","format":"uuid"},"audioUrl":{"type":"string","format":"uri"},"duration":{"type":"number","nullable":true},"wordTimings":{"type":"array","items":{"$ref":"#/components/schemas/WordTiming"}}}}}},"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"paths":{"/v1/me":{"get":{"tags":["Account"],"summary":"Current user and credits","description":"Returns the authenticated user, which product the API key belongs to (`files` or `x`), and credit balances.","operationId":"getMe","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiMe"}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X GET 'https://api.narrador.io/v1/me' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'"},{"lang":"curl","label":"curl","source":"curl -sS -X GET 'https://api.narrador.io/v1/me' \\\n  -H 'Authorization: Bearer nrd_x_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'"}]}},"/v1/voices":{"get":{"tags":["narrador files"],"summary":"List voices","description":"Catalog of narrador files voices (Resemble and Soprano; Fish Audio voices are excluded from this list). Requires a `nrd_files_` key.","operationId":"listFilesVoices","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["voices"],"properties":{"voices":{"type":"array","items":{"$ref":"#/components/schemas/FilesVoice"}}}}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X GET 'https://api.narrador.io/v1/voices' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'"}]}},"/v1/files/uploads":{"post":{"tags":["narrador files"],"summary":"Create upload URL","description":"Creates a storage file record and returns a signed URL to `PUT` the document bytes. Requires a `nrd_files_` key.","operationId":"createFilesUpload","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fileName","fileSizeBytes"],"properties":{"fileName":{"type":"string","example":"chapter-one.pdf"},"fileSizeBytes":{"type":"integer","minimum":0,"maximum":52428800,"description":"Size of the file you will PUT to the signed URL, in bytes (max 50 MB).","example":1024000}}}}}},"responses":{"201":{"description":"Upload URL created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilesUploadUrl"}}}},"400":{"description":"Missing `fileName` or `fileSizeBytes`, or file too large","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X POST 'https://api.narrador.io/v1/files/uploads' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'\n  -d '{\"fileName\":\"chapter-one.pdf\",\"fileSizeBytes\":1048576}'"}]}},"/v1/files/jobs":{"post":{"tags":["narrador files"],"summary":"Start an audio job","description":"Starts narrador files processing from an uploaded file or inline text. Returns a `jobId` (snapshot id) to poll. Requires a `nrd_files_` key.","operationId":"createFilesJob","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/FilesJobFromUpload"},{"$ref":"#/components/schemas/FilesJobFromText"}]},"examples":{"fromUpload":{"summary":"From prior upload","value":{"fileId":"550e8400-e29b-41d4-a716-446655440000","fileName":"chapter-one.pdf","voiceId":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","accent":"en-us"}},"fromText":{"summary":"From plain text","value":{"text":"Hello world.","fileName":"note.txt","voiceId":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","accent":"en-us"}}}}}},"responses":{"201":{"description":"Job created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilesJobCreated"}}}},"400":{"description":"Invalid JSON body","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X POST 'https://api.narrador.io/v1/files/jobs' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'\n  -d '{\"fileId\":\"550e8400-e29b-41d4-a716-446655440000\",\"fileName\":\"chapter-one.pdf\",\"voiceId\":\"6ba7b810-9dad-11d1-80b4-00c04fd430c8\",\"accent\":\"en-us\"}'"},{"lang":"curl","label":"curl","source":"curl -sS -X POST 'https://api.narrador.io/v1/files/jobs' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'\n  -d '{\"text\":\"Hello world.\",\"voiceId\":\"6ba7b810-9dad-11d1-80b4-00c04fd430c8\",\"accent\":\"en-us\"}'"}]}},"/v1/files/jobs/{jobId}":{"get":{"tags":["narrador files"],"summary":"Job status","operationId":"getFilesJobStatus","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilesJobStatus"}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X GET 'https://api.narrador.io/v1/files/jobs/550e8400-e29b-41d4-a716-446655440000' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'"}]}},"/v1/files/jobs/{jobId}/result":{"get":{"tags":["narrador files"],"summary":"Job result","description":"Returns signed audio URL and word timings when `status` is `completed`. Otherwise **409** with message `Job audio is not ready yet.`","operationId":"getFilesJobResult","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Audio ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilesJobResult"}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"404":{"description":"Job not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"409":{"description":"Audio not ready","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X GET 'https://api.narrador.io/v1/files/jobs/550e8400-e29b-41d4-a716-446655440000/result' \\\n  -H 'Authorization: Bearer nrd_files_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'"}]}},"/v1/x/generations":{"post":{"tags":["narrador X"],"summary":"Generate post audio","description":"Resolves an X post by id or URL, generates TTS audio, and returns timings. Requires an active narrador X subscription and a `nrd_x_` key.","operationId":"createXGeneration","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/XGenerationCreate"},"examples":{"byPostId":{"value":{"postId":"1234567890123456789","voiceId":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","accent":"en-us"}},"byUrl":{"value":{"postUrl":"https://x.com/narrador/status/1234567890123456789","voiceId":"6ba7b810-9dad-11d1-80b4-00c04fd430c8"}}}}}},"responses":{"201":{"description":"Generation created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/XGenerationResult"}}}},"400":{"description":"Invalid JSON body","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X POST 'https://api.narrador.io/v1/x/generations' \\\n  -H 'Authorization: Bearer nrd_x_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'\n  -d '{\"postId\":\"1234567890123456789\",\"voiceId\":\"6ba7b810-9dad-11d1-80b4-00c04fd430c8\",\"accent\":\"en-us\"}'"}]}},"/v1/x/generations/{generationId}":{"get":{"tags":["narrador X"],"summary":"Get generation result","operationId":"getXGeneration","security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"parameters":[{"name":"generationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/XGenerationResult"}}}},"401":{"description":"Unauthorized — missing or invalid API key (wrong prefix, revoked, or expired).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"402":{"description":"Payment required — insufficient narrador files credits for a billable operation. Some files work is asynchronous; check job status and warnings when audio generation fails for billing reasons.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"403":{"description":"Forbidden — API key scope does not match the endpoint (e.g. `nrd_x_` key on a narrador files route), or narrador X subscription is not active.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"404":{"description":"Generation not found","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}},"429":{"description":"Too many requests — API key verification rate limit exceeded (60 requests per 60 seconds per key).","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}},"additionalProperties":false}}}}},"x-codeSamples":[{"lang":"curl","label":"curl","source":"curl -sS -X GET 'https://api.narrador.io/v1/x/generations/550e8400-e29b-41d4-a716-446655440000' \\\n  -H 'Authorization: Bearer nrd_x_YOUR_SECRET_KEY' \\\n  -H 'Content-Type: application/json'"}]}}}}