{"openapi":"3.0.3","info":{"title":"LogTalk API","version":"1.4.0","description":"The LogTalk API enables programmatic audio generation for CI/CD pipeline integration.\nConvert changelogs to audio, or convert any document to audio — both through the\nunified `/conversions` endpoint (set `source_type` to `changelog` or `document`).\n\n## Authentication\n\nAll API requests require authentication using a Bearer token. API keys can be created in your\n[LogTalk Dashboard](https://logtalk.io/settings/api-keys).\n\n```\nAuthorization: Bearer lt_live_xxxxxxxxxxxx\n```\n\nAPI keys use the prefix `lt_live_` for production or `lt_test_` for sandbox environments.\n\n## Rate Limiting\n\nAPI requests are rate limited based on your subscription tier:\n\n| Tier   | Daily Limit | Per-Minute Limit | Concurrent Jobs |\n|--------|-------------|------------------|-----------------|\n| Growth | 100         | 20               | 3               |\n| Pro    | 500         | 60               | 10              |\n| Team   | 2000        | 200              | 25              |\n\nRate limit headers are included in all responses:\n- `X-RateLimit-Limit`: Daily limit\n- `X-RateLimit-Remaining`: Remaining requests today\n- `X-RateLimit-Reset`: Unix timestamp when daily limit resets\n- `X-RateLimit-Limit-Minute`: Per-minute limit\n- `X-RateLimit-Remaining-Minute`: Remaining requests this minute\n\n## Quotas\n\nAudio generation consumes quotas from your subscription. Quota headers are included:\n- `X-Quota-Audio-Limit`: Monthly audio episode limit\n- `X-Quota-Audio-Remaining`: Remaining audio episodes\n- `X-Quota-Reset`: ISO 8601 timestamp for quota reset\n- `X-Quota-Credits-Available`: Available credit balance\n\n## Idempotency\n\nFor POST requests, include an `Idempotency-Key` header to prevent duplicate operations:\n\n```\nIdempotency-Key: unique-request-identifier-123\n```\n\nKeys are valid for 24 hours. Requests with the same idempotency key return the cached response.\n\n## Webhooks\n\nReceive notifications when conversions complete by providing a `webhook_url` in your request\nor by configuring persistent webhooks in your dashboard.\n\nWebhook payloads are signed with HMAC-SHA256. Verify using the `X-LogTalk-Signature` header.\n","contact":{"name":"LogTalk Support","email":"support@logtalk.io","url":"https://logtalk.io/support"},"license":{"name":"Proprietary","url":"https://logtalk.io/terms"},"x-logo":{"url":"https://logtalk.io/logo.png"}},"servers":[{"url":"https://logtalk.io/api/v1","description":"Production server"}],"tags":[{"name":"Conversions","description":"Unified API for changelog and document audio conversions"},{"name":"Episodes","description":"Changelog-to-audio episodes (deprecated — use /conversions with source_type: changelog)"},{"name":"Scripts","description":"Generate and convert scripts (preview/edit flow)"},{"name":"Organizations","description":"Access organization details and settings"},{"name":"Usage","description":"Monitor API usage and quotas"},{"name":"Changelogs","description":"List your organization's previously converted changelogs — history and context for generating new content"},{"name":"API Info","description":"API metadata and documentation"}],"security":[{"BearerAuth":[]}],"paths":{"/conversions":{"post":{"operationId":"createConversion","summary":"Create a conversion","description":"Creates a new audio conversion from a changelog or document.\n\nSet `source_type` to `\"changelog\"` for changelog-to-audio, or `\"document\"` for\ngeneral document-to-audio. Both share the same endpoint and response format.\n\nBy default the request returns immediately with status `processing` and a `poll_url`\n(202 Accepted). Set `wait: true` to block until completion (200 OK).\n","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionRequest"},"examples":{"changelog":{"summary":"Changelog conversion","value":{"source_type":"changelog","title":"MyApp v2.0.0 Release","content":"## v2.0.0 - New Features\n- Added dark mode support\n- Improved performance by 40%","additional_context":"This release focuses on performance improvements after customer feedback.","settings":{"product_name":"MyApp","version":"2.0.0","tone":"casual"},"use_history":true,"history_limit":5,"public_url":true}},"document":{"summary":"Document conversion","value":{"source_type":"document","title":"Q4 Engineering Update","content":"Our engineering team shipped 47 features this quarter...","settings":{"verbosity":"normal","speakers":2,"tone":"casual"}}},"with_voice":{"summary":"Custom ElevenLabs voice","value":{"source_type":"changelog","title":"MyApp v2.1.0","content":"## v2.1.0\n- Bug fixes","voice":{"provider":"elevenlabs","voice_id":"abc123","model":"v3","delivery_preset":"dynamic"}}}}}}},"responses":{"200":{"description":"Conversion completed synchronously (when wait=true)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConversionDetail"}}}]}}}},"202":{"description":"Conversion accepted for processing","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProcessingConversionResponse"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"403":{"$ref":"#/components/responses/Forbidden"},"408":{"$ref":"#/components/responses/Timeout"},"409":{"$ref":"#/components/responses/IdempotencyConflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"operationId":"listConversions","summary":"List conversions","description":"Returns a paginated list of conversions for your organization, newest first.","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"name":"source_type","in":"query","description":"Filter by source type","schema":{"type":"string","enum":["changelog","document"]}},{"name":"status","in":"query","description":"Filter by conversion status","schema":{"type":"string","enum":["pending","processing","generating","completed","failed"]}},{"name":"limit","in":"query","description":"Maximum number of results to return","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","description":"Pagination cursor from previous response","schema":{"type":"string"}}],"responses":{"200":{"description":"List of conversions","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ConversionListItem"}},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/conversions/{id}":{"get":{"operationId":"getConversion","summary":"Get conversion details","description":"Retrieves the current status and details of a conversion.\n\nUse this endpoint to poll for completion. The response includes different\nfields depending on the conversion status.\n","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Conversion details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConversionDetail"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"updateConversion","summary":"Update a conversion","description":"Update metadata fields on a conversion. Only a subset of fields can be modified after creation.","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"public_url":{"type":"boolean","description":"Enable or disable public listen/embed URLs"},"title":{"type":"string","maxLength":500,"description":"Update the conversion title"},"additional_context":{"type":"string","maxLength":10240,"description":"Update the additional context"}}},"example":{"public_url":true}}}},"responses":{"200":{"description":"Updated conversion","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConversionDetail"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"deleteConversion","summary":"Delete a conversion","description":"Permanently deletes a conversion and all associated media files from storage.\nThis action cannot be undone.\n","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Conversion deleted successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResource"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/conversions/{id}/retry":{"post":{"operationId":"retryConversion","summary":"Retry a failed conversion","description":"Re-queues a failed conversion for processing. Only conversions with\nstatus `failed` can be retried. Quota is consumed on retry.\n","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"202":{"description":"Retry accepted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProcessingConversionResponse"}}}]}}}},"400":{"$ref":"#/components/responses/InvalidRetryState"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/conversions/{id}/audio":{"get":{"operationId":"getConversionAudio","summary":"Get signed audio URL","description":"Returns a signed URL for the conversion audio file.\n\n**Content negotiation:**\n- `Accept: application/json` → Returns JSON with `audio_url` and expiry\n- Default → 302 redirect to the signed URL (follow the redirect to download)\n\nThe signed URL expires after 50 minutes. No quota is consumed — credits\nare used when the conversion is created, not when audio is downloaded.\n","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Audio URL (when Accept=application/json)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AudioUrlResponse"}}}]}}}},"302":{"description":"Redirect to signed audio URL"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/conversions/{id}/embed-token":{"post":{"operationId":"createEmbedToken","summary":"Create an embed token","description":"Creates a non-expiring embed token scoped to this conversion. Embed tokens\nallow the audio player to be embedded on external sites without requiring\npublic access or API key authentication.\n\nRate limit: 100 tokens per organization per day. Requires paid tier.\n","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"201":{"description":"Embed token created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EmbedToken"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"get":{"operationId":"listEmbedTokens","summary":"List embed tokens","description":"Returns all active embed tokens for a conversion.","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"List of embed tokens","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmbedToken"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/conversions/{id}/embed-token/{token}":{"delete":{"operationId":"revokeEmbedToken","summary":"Revoke an embed token","description":"Permanently revokes an embed token. The token will no longer work for playback.","tags":["Conversions"],"parameters":[{"$ref":"#/components/parameters/ConversionId"},{"name":"token","in":"path","required":true,"description":"The embed token to revoke","schema":{"type":"string"}},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Token revoked","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"token":{"type":"string"},"revoked":{"type":"boolean","const":true},"revoked_at":{"type":"string","format":"date-time"}}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/episodes":{"post":{"operationId":"createEpisode","deprecated":true,"summary":"Create a new episode (deprecated)","description":"**Deprecated.** Use `POST /conversions` with `source_type: \"changelog\"` instead.\n\nCreates a changelog-to-audio episode. Always processes synchronously and returns\nthe completed result (200 OK).\n","tags":["Episodes"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEpisodeRequest"},"examples":{"audio":{"summary":"Audio episode","value":{"content":"## v2.0.0 - New Features\n- Added dark mode support\n- Improved performance by 40%","mode":"changelog","output_format":"audio","settings":{"product_name":"MyApp","version":"2.0.0","tone":"casual"},"additional_context":"This release focuses on performance improvements after customer feedback.","use_history":true,"history_limit":5}}}}}},"responses":{"200":{"description":"Episode completed successfully","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompletedEpisode"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"403":{"$ref":"#/components/responses/Forbidden"},"408":{"$ref":"#/components/responses/Timeout"},"409":{"$ref":"#/components/responses/IdempotencyConflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"operationId":"listEpisodes","deprecated":true,"summary":"List episodes (deprecated)","description":"**Deprecated.** Use `GET /conversions?source_type=changelog` instead.\n\nReturns a paginated list of episodes for your organization.\n","tags":["Episodes"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","processing","generating","completed","failed"]}},{"name":"mode","in":"query","schema":{"type":"string","enum":["changelog","product-feature"]}},{"name":"output_format","in":"query","schema":{"type":"string","enum":["audio","video"]}},{"name":"created_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"created_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of episodes","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EpisodeListItem"}},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/episodes/{id}":{"get":{"operationId":"getEpisode","deprecated":true,"summary":"Get episode details (deprecated)","description":"**Deprecated.** Use `GET /conversions/{id}` instead.\n\nRetrieves the current status and details of an episode.\n","tags":["Episodes"],"parameters":[{"$ref":"#/components/parameters/EpisodeId"},{"$ref":"#/components/parameters/OrganizationIdHeader"},{"name":"expand","in":"query","required":false,"schema":{"type":"string"},"example":"organization"}],"responses":{"200":{"description":"Episode details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"oneOf":[{"$ref":"#/components/schemas/ProcessingEpisodeDetail"},{"$ref":"#/components/schemas/CompletedEpisode"},{"$ref":"#/components/schemas/FailedEpisode"}]}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"deleteEpisode","deprecated":true,"summary":"Delete an episode (deprecated)","description":"**Deprecated.** Use `DELETE /conversions/{id}` instead.\n\nPermanently deletes an episode and its associated media files.\n","tags":["Episodes"],"parameters":[{"$ref":"#/components/parameters/EpisodeId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Episode deleted successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedResource"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/episodes/{id}/retry":{"post":{"operationId":"retryEpisode","deprecated":true,"summary":"Retry a failed episode (deprecated)","description":"**Deprecated.** Use `POST /conversions/{id}/retry` instead.\n\nRetries a previously failed episode. Only failed episodes can be retried.\n","tags":["Episodes"],"parameters":[{"$ref":"#/components/parameters/EpisodeId"},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"override_settings":{"$ref":"#/components/schemas/EpisodeSettings"},"webhook_url":{"type":"string","format":"uri"}}}}}},"responses":{"202":{"description":"Retry accepted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProcessingConversionResponse"}}}]}}}},"400":{"$ref":"#/components/responses/InvalidRetryState"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/scripts":{"post":{"operationId":"generateScript","summary":"Generate a script","description":"Generates a script from changelog content without creating audio.\n\nUse this endpoint to preview and edit the script before conversion.\nScripts expire after 2 hours.\n","tags":["Scripts"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateScriptRequest"},"example":{"content":"## v2.0.0 Release\n- New feature A\n- Bug fix B","mode":"changelog","settings":{"product_name":"MyApp","tone":"casual"},"additional_context":"Focus on developer experience improvements.","use_history":true,"history_limit":10}}}},"responses":{"200":{"description":"Script generated successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/GeneratedScript"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/scripts/{id}/convert":{"post":{"operationId":"convertScript","summary":"Convert a script to audio","description":"Converts a previously generated script to audio.\n\nThis skips the script generation step, useful when you have reviewed\nand optionally edited the script. The script must not be expired (2-hour limit).\n","tags":["Scripts"],"parameters":[{"name":"id","in":"path","required":true,"description":"Script ID in format script_xxxxxxxxxxxx","schema":{"type":"string","pattern":"^script_[a-f0-9]{24}$"}},{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertScriptRequest"},"example":{"output_format":"audio","edited_content":"Updated script content with edits..."}}}},"responses":{"200":{"description":"Conversion completed (audio sync)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CompletedEpisode"}}}]}}}},"202":{"description":"Conversion accepted (async when wait=false)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProcessingConversionResponse"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"410":{"description":"Script has expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organizations":{"get":{"operationId":"listOrganizations","summary":"List organizations","description":"Returns all organizations the authenticated user has access to.","tags":["Organizations"],"responses":{"200":{"description":"List of organizations","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationSummary"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/organizations/{id}":{"get":{"operationId":"getOrganization","summary":"Get organization details","description":"Retrieves detailed information about an organization including\nbranding configuration and subscription/usage details.\n","tags":["Organizations"],"parameters":[{"name":"id","in":"path","required":true,"description":"Organization UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Organization details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationDetail"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/usage":{"get":{"operationId":"getUsage","summary":"Get usage statistics","description":"Returns current billing period usage statistics including:\n- Audio quota and usage\n- Credit balance\n- API request statistics\n","tags":["Usage"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Usage statistics","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/UsageStats"}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/changelogs":{"get":{"operationId":"listChangelogs","summary":"List previous changelogs","description":"Returns a summary of previous changelogs that can be used for context\nwhen generating new content. Supports filtering and pagination.\n","tags":["Changelogs"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"name":"product_name","in":"query","description":"Filter by product name (case-insensitive)","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"List of changelogs","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChangelogSummary"}},"meta":{"$ref":"#/components/schemas/PaginationMeta"}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/changelog":{"get":{"operationId":"getApiChangelog","summary":"Get API version history","description":"Returns the API changelog including version history, breaking changes,\ndeprecations, and new features.\n","tags":["API Info"],"security":[],"responses":{"200":{"description":"API changelog","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApiChangelog"}}}]}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/openapi":{"get":{"operationId":"getOpenApiSpec","summary":"Get OpenAPI specification","description":"Returns the OpenAPI specification for the LogTalk API.","tags":["API Info"],"security":[],"parameters":[{"name":"format","in":"query","description":"Response format","schema":{"type":"string","enum":["json","yaml"],"default":"json"}}],"responses":{"200":{"description":"OpenAPI specification","content":{"application/json":{"schema":{"type":"object","description":"OpenAPI 3.0 specification"}},"application/yaml":{"schema":{"type":"string","description":"OpenAPI 3.0 specification in YAML format"}}}}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"lt_live_*","description":"API key authentication. Include your API key in the Authorization header:\n\n`Authorization: Bearer lt_live_xxxxxxxxxxxx`\n\nAPI keys can be created in your [LogTalk Dashboard](https://logtalk.io/settings/api-keys).\n"}},"parameters":{"ConversionId":{"name":"id","in":"path","required":true,"description":"Conversion UUID","schema":{"type":"string","format":"uuid"}},"EpisodeId":{"name":"id","in":"path","required":true,"description":"Episode UUID","schema":{"type":"string","format":"uuid"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key for idempotent requests. Keys must be 1-256 printable ASCII characters.\nIf the same key is sent within 24 hours, the cached response is returned.\n","schema":{"type":"string","minLength":1,"maxLength":256}},"OrganizationIdHeader":{"name":"X-Organization-ID","in":"header","required":false,"description":"Specify organization context for multi-org users. If omitted, uses default org for API key.","schema":{"type":"string","format":"uuid"}}},"headers":{"X-Request-ID":{"description":"Unique request identifier for debugging and support","schema":{"type":"string","example":"req_1kn5f2a_a3b4c5d6e7f8"}},"X-RateLimit-Limit":{"description":"Daily rate limit for your subscription tier","schema":{"type":"integer","example":100}},"X-RateLimit-Remaining":{"description":"Remaining requests for today","schema":{"type":"integer","example":95}},"X-RateLimit-Reset":{"description":"Unix timestamp when daily limit resets","schema":{"type":"integer","example":1705622400}},"Retry-After":{"description":"Seconds to wait before retrying (on 429 responses)","schema":{"type":"integer","example":60}},"X-RateLimit-Limit-Minute":{"description":"Per-minute rate limit for your subscription tier","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining-Minute":{"description":"Remaining requests for the current minute","schema":{"type":"integer","example":57}},"X-Quota-Audio-Limit":{"description":"Monthly audio episode limit","schema":{"type":"integer","example":10}},"X-Quota-Audio-Remaining":{"description":"Remaining audio episodes this billing period","schema":{"type":"integer","example":3}},"X-Quota-Reset":{"description":"ISO 8601 timestamp for quota reset","schema":{"type":"string","format":"date-time","example":"2026-02-01T00:00:00Z"}},"X-Quota-Credits-Available":{"description":"Available credit balance","schema":{"type":"integer","example":25}},"X-LogTalk-Signature":{"description":"HMAC-SHA256 signature for webhook payload verification","schema":{"type":"string","example":"sha256=abc123..."}}},"schemas":{"VoiceConfig":{"type":"object","description":"TTS voice configuration. Applies to ElevenLabs when provider is \"elevenlabs\".","properties":{"provider":{"type":"string","enum":["gemini","elevenlabs"],"default":"gemini","description":"Text-to-speech provider"},"delivery_preset":{"type":"string","enum":["measured","dynamic","theatrical"],"description":"Controls the pacing and energy of the narration"},"expression_settings":{"type":"object","description":"Fine-grained vocal expression controls (ElevenLabs only)","properties":{"emotional_range":{"type":"string","enum":["subtle","moderate","full"]},"allow_whispering":{"type":"boolean"},"allow_laughter":{"type":"boolean"},"emphasis_style":{"type":"string","enum":["pauses","both"]},"emotional_arc":{"type":"boolean"}}},"pronunciation_notes":{"type":"string","maxLength":500,"description":"Pronunciation guidance for product names, acronyms, etc.","example":"Nginx is pronounced engine-x, not en-jinks"},"voice_id":{"type":"string","description":"ElevenLabs voice ID for single-speaker mode"},"model":{"type":"string","enum":["v3","flash_v2"],"description":"ElevenLabs model to use"},"host_voice_ids":{"type":"object","description":"Voice IDs for multi-speaker dialogue","properties":{"host1":{"type":"string","description":"ElevenLabs voice ID for host 1"},"host2":{"type":"string","description":"ElevenLabs voice ID for host 2"}}}}},"ConversionSettings":{"type":"object","description":"Script generation and audio settings for conversions","properties":{"product_name":{"type":"string","description":"Product or company name to use in the script","example":"MyApp"},"version":{"type":"string","description":"Version number to emphasize","example":"2.0.0"},"tone":{"type":"string","enum":["casual","professional","enthusiastic","technical"],"default":"casual","description":"Voice tone for the script"},"audience":{"type":"string","description":"Target audience description","example":"developers"},"verbosity":{"type":"string","enum":["brief","normal","detailed"],"default":"normal","description":"Script length preference"},"cta":{"type":"string","description":"Optional call-to-action to include at the end"},"severity_aware_tone":{"type":"boolean","description":"Adjust tone based on severity of changes (e.g. more serious for breaking changes)"},"summary_threshold":{"type":"integer","description":"Minimum number of changes before switching to summary mode"},"use_history":{"type":"boolean","default":true,"description":"Whether to include previous changelogs as context"},"history_limit":{"type":"integer","minimum":1,"maximum":100,"default":10,"description":"Number of previous changelogs to include as context"},"speakers":{"type":"integer","enum":[1,2],"default":1,"description":"Number of speakers (1 = single narrator, 2 = dialogue)"}}},"ConversionRequest":{"type":"object","required":["source_type","title","content"],"properties":{"source_type":{"type":"string","enum":["changelog","document"],"description":"Type of content being converted"},"title":{"type":"string","maxLength":500,"description":"Title for this conversion"},"content":{"type":"string","maxLength":51200,"description":"Content to convert (max 50KB)"},"additional_context":{"type":"string","maxLength":10240,"description":"Additional context for the AI script generator (max 10KB)","example":"This release focuses on performance improvements after customer feedback."},"product_id":{"type":"string","format":"uuid","description":"Associate with a specific product"},"ignore_org":{"type":"boolean","description":"Skip organization-level context for this conversion"},"public_url":{"type":"boolean","default":false,"description":"If true, creates publicly shareable listen and embed URLs"},"webhook_url":{"type":"string","format":"uri","description":"HTTPS URL to receive completion webhook notification"},"wait":{"type":"boolean","default":false,"description":"Block until completion (returns 200 instead of 202). Maximum wait is 90 seconds."},"voice":{"$ref":"#/components/schemas/VoiceConfig"},"settings":{"$ref":"#/components/schemas/ConversionSettings"}}},"ConversionListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source_type":{"type":"string","enum":["changelog","document"]},"title":{"type":"string"},"status":{"type":"string","enum":["pending","processing","generating","completed","failed"]},"has_audio":{"type":"boolean"},"duration_seconds":{"type":"number","nullable":true},"product_id":{"type":"string","format":"uuid","nullable":true},"public_url":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time","nullable":true}}},"ConversionDetail":{"type":"object","description":"Full conversion object. Conditional fields appear based on status.","properties":{"id":{"type":"string","format":"uuid"},"source_type":{"type":"string","enum":["changelog","document"]},"title":{"type":"string"},"status":{"type":"string","enum":["pending","processing","generating","completed","failed"]},"has_audio":{"type":"boolean"},"poll_url":{"type":"string","format":"uri","description":"Present when status is processing or generating"},"estimated_completion_seconds":{"type":"integer","description":"Present when status is processing or generating"},"generated_script":{"type":"string","description":"Present when status is completed"},"duration_seconds":{"type":"number","nullable":true,"description":"Present when status is completed"},"audio_url":{"type":"string","format":"uri","description":"Signed URL to audio file (present when status is completed)"},"listen_url":{"type":"string","format":"uri","description":"Public listen page URL (present when public_url=true)"},"embed_url":{"type":"string","format":"uri","description":"Embeddable player URL (present when public_url=true)"},"error":{"type":"object","description":"Present when status is failed","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"public_url":{"type":"boolean"},"product_id":{"type":"string","format":"uuid","nullable":true},"additional_context":{"type":"string","nullable":true},"completed_at":{"type":"string","format":"date-time","nullable":true},"failed_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"ProcessingConversionResponse":{"type":"object","description":"Returned when a conversion is queued for async processing","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","processing"]},"source_type":{"type":"string","enum":["changelog","document"]},"poll_url":{"type":"string","format":"uri","description":"URL to poll for status updates"},"estimated_completion_seconds":{"type":"integer","description":"Estimated time until completion"},"created_at":{"type":"string","format":"date-time"}}},"AudioUrlResponse":{"type":"object","properties":{"audio_url":{"type":"string","format":"uri","description":"Signed URL to the audio file"},"content_type":{"type":"string","example":"audio/mpeg"},"duration_seconds":{"type":"number","nullable":true},"expires_at":{"type":"string","format":"date-time","description":"When the signed URL expires (approximately 50 minutes)"}}},"EmbedToken":{"type":"object","properties":{"token":{"type":"string","description":"The embed token value"},"conversion_id":{"type":"string","format":"uuid"},"embed_url":{"type":"string","format":"uri","description":"Full embed URL including the token"},"created_at":{"type":"string","format":"date-time"}}},"SuccessResponse":{"type":"object","required":["success","data","request_id","timestamp"],"properties":{"success":{"type":"boolean","const":true},"data":{"description":"Response payload (varies by endpoint)"},"meta":{"$ref":"#/components/schemas/ResponseMeta"},"request_id":{"type":"string","description":"Unique request identifier","example":"req_1kn5f2a_a3b4c5d6e7f8"},"timestamp":{"type":"string","format":"date-time","description":"Response timestamp in ISO 8601 format","example":"2026-01-18T12:00:00.000Z"}}},"ErrorResponse":{"type":"object","required":["success","error","request_id","timestamp"],"properties":{"success":{"type":"boolean","const":false},"error":{"type":"object","required":["code","message","documentation_url"],"properties":{"code":{"type":"string","description":"Machine-readable error code","example":"AUTHENTICATION_FAILED"},"message":{"type":"string","description":"Human-readable error message","example":"Invalid API key"},"details":{"type":"object","description":"Additional error context"},"documentation_url":{"type":"string","format":"uri","description":"Link to error documentation","example":"https://docs.logtalk.io/errors/authentication"}}},"request_id":{"type":"string","example":"req_1kn5f2a_a3b4c5d6e7f8"},"timestamp":{"type":"string","format":"date-time"}}},"ResponseMeta":{"type":"object","properties":{"total_count":{"type":"integer","description":"Total number of items matching the query"},"has_more":{"type":"boolean","description":"Whether more results are available"},"next_cursor":{"type":"string","description":"Cursor for fetching the next page"}}},"PaginationMeta":{"type":"object","properties":{"total_count":{"type":"integer","example":42},"has_more":{"type":"boolean","example":true},"next_cursor":{"type":"string","example":"eyJjcmVhdGVkX2F0IjoiMjAyNi0wMS0xN1QxMjowMDowMC4wMDBaIn0="}}},"CreateEpisodeRequest":{"deprecated":true,"type":"object","required":["content"],"properties":{"content":{"type":"string","description":"Changelog content (max 50KB)","maxLength":51200},"mode":{"type":"string","enum":["changelog","product-feature"],"default":"changelog"},"output_format":{"type":"string","enum":["audio","video"],"default":"audio"},"settings":{"$ref":"#/components/schemas/EpisodeSettings"},"screenshot_urls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":20},"webhook_url":{"type":"string","format":"uri"},"wait":{"type":"boolean","default":false},"additional_context":{"type":"string","description":"Additional context for the AI script generator (max 10KB)","maxLength":10240,"example":"This release focuses on performance improvements after customer feedback."},"further_details":{"type":"string","deprecated":true,"description":"Deprecated alias for additional_context. Use additional_context instead.","maxLength":10240},"use_history":{"type":"boolean","default":true},"history_limit":{"type":"integer","minimum":1,"maximum":100,"default":10},"public_url":{"type":"boolean","default":false},"voice":{"$ref":"#/components/schemas/VoiceConfig"}}},"EpisodeSettings":{"type":"object","properties":{"product_name":{"type":"string","example":"MyApp"},"version":{"type":"string","example":"2.0.0"},"tone":{"type":"string","enum":["casual","professional","enthusiastic","technical"],"default":"casual"},"audience":{"type":"string","example":"developers"},"verbosity":{"type":"string","enum":["brief","normal","detailed"],"default":"normal"},"duration":{"type":"string","enum":["brief","normal","detailed"],"default":"normal","description":"Alias for verbosity"}}},"CompletedEpisode":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"completed"},"mode":{"type":"string","enum":["changelog","product-feature"]},"source":{"type":"string","enum":["api","web"]},"audio_url":{"type":"string","format":"uri","nullable":true},"video_url":{"type":"string","format":"uri","nullable":true},"script":{"type":"string"},"duration_seconds":{"type":"number"},"listen_url":{"type":"string","format":"uri","nullable":true,"description":"Present when public_url=true"},"embed_url":{"type":"string","format":"uri","nullable":true,"description":"Present when public_url=true"},"completed_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"organization":{"$ref":"#/components/schemas/OrganizationSummary","description":"Expanded organization details (when expand=organization)"}}},"ProcessingEpisode":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"processing"},"output_format":{"type":"string","enum":["audio","video"]},"poll_url":{"type":"string","format":"uri"},"estimated_completion_seconds":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"ProcessingEpisodeDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","processing","generating"]},"mode":{"type":"string"},"source":{"type":"string"},"progress_percent":{"type":"integer","minimum":0,"maximum":100},"current_stage":{"type":"string","enum":["queued","script_generation","audio_generation","finalization"]},"stages":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"complete":{"type":"boolean"}}}},"estimated_completion_seconds":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"organization":{"$ref":"#/components/schemas/OrganizationSummary"}}},"FailedEpisode":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","const":"failed"},"mode":{"type":"string"},"source":{"type":"string"},"error":{"type":"object","properties":{"code":{"type":"string","example":"GENERATION_FAILED"},"message":{"type":"string"},"details":{"type":"object","nullable":true}}},"failed_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"organization":{"$ref":"#/components/schemas/OrganizationSummary"}}},"EpisodeListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","processing","generating","completed","failed"]},"mode":{"type":"string"},"source":{"type":"string"},"progress_percent":{"type":"integer"},"has_audio":{"type":"boolean"},"has_video":{"type":"boolean"},"duration_seconds":{"type":"number","nullable":true},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time","nullable":true}}},"DeletedResource":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","const":true},"deleted_at":{"type":"string","format":"date-time"}}},"GenerateScriptRequest":{"type":"object","required":["content"],"properties":{"content":{"type":"string","maxLength":51200},"mode":{"type":"string","enum":["changelog","product-feature"],"default":"changelog"},"settings":{"$ref":"#/components/schemas/EpisodeSettings"},"screenshot_urls":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":20},"additional_context":{"type":"string","maxLength":10240,"description":"Additional context for the AI script generator"},"further_details":{"type":"string","deprecated":true,"description":"Deprecated alias for additional_context","maxLength":10240},"use_history":{"type":"boolean","default":true},"history_limit":{"type":"integer","minimum":1,"maximum":100,"default":10}}},"GeneratedScript":{"type":"object","properties":{"id":{"type":"string","description":"Script ID (format script_xxxxxxxxxxxx)","example":"script_a1b2c3d4e5f6a1b2c3d4e5f6"},"content":{"type":"string"},"estimated_duration_seconds":{"type":"integer"},"word_count":{"type":"integer"},"context_used":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","description":"Script expiration time (2 hours from creation)"},"created_at":{"type":"string","format":"date-time"}}},"ConvertScriptRequest":{"type":"object","required":["output_format"],"properties":{"output_format":{"type":"string","enum":["audio","video"]},"edited_content":{"type":"string","description":"Optionally provide edited script content to use instead of the original"},"settings":{"type":"object","properties":{"tone":{"type":"string"},"audience":{"type":"string"},"verbosity":{"type":"string"}}},"webhook_url":{"type":"string","format":"uri"},"wait":{"type":"boolean","default":false},"voice":{"$ref":"#/components/schemas/VoiceConfig"}}},"OrganizationSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"logo_url":{"type":"string","format":"uri","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"OrganizationDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"logo_url":{"type":"string","format":"uri","nullable":true},"primary_color":{"type":"string","nullable":true},"secondary_color":{"type":"string","nullable":true},"design_template":{"type":"string","nullable":true},"subscription":{"$ref":"#/components/schemas/SubscriptionInfo"}}},"SubscriptionInfo":{"type":"object","properties":{"tier":{"type":"string","enum":["free","starter","growth","pro","team"]},"audio_quota":{"type":"integer"},"audio_used":{"type":"integer"},"video_quota":{"type":"integer"},"video_used":{"type":"integer"},"credits_available":{"type":"integer"},"period_ends_at":{"type":"string","format":"date-time","nullable":true}}},"UsageStats":{"type":"object","properties":{"period_start":{"type":"string","format":"date-time"},"period_end":{"type":"string","format":"date-time"},"audio":{"type":"object","properties":{"quota":{"type":"integer"},"used":{"type":"integer"},"remaining":{"type":"integer"}}},"video":{"type":"object","properties":{"quota":{"type":"integer"},"used":{"type":"integer"},"remaining":{"type":"integer"}}},"credits":{"type":"object","properties":{"available":{"type":"integer"},"audio_credits":{"type":"integer"},"video_credits":{"type":"integer"},"expiring_soon":{"type":"integer"}}},"api_requests":{"type":"object","properties":{"today":{"type":"integer"},"daily_limit":{"type":"integer"},"this_minute":{"type":"integer"},"minute_limit":{"type":"integer"}}}}},"ChangelogSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version":{"type":"string","nullable":true},"product_name":{"type":"string","nullable":true},"mode":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"content_preview":{"type":"string","description":"Truncated content preview (max 200 chars)"}}},"ApiChangelog":{"type":"object","properties":{"current_version":{"type":"string","example":"1.4.0"},"versions":{"type":"array","items":{"$ref":"#/components/schemas/ApiVersion"}}}},"ApiVersion":{"type":"object","properties":{"version":{"type":"string"},"release_date":{"type":"string","format":"date"},"status":{"type":"string","enum":["current","deprecated","sunset"]},"changes":{"type":"array","items":{"$ref":"#/components/schemas/ApiChange"}}}},"ApiChange":{"type":"object","properties":{"type":{"type":"string","enum":["breaking","deprecation","feature","fix","security"]},"description":{"type":"string"},"migration_guide":{"type":"string"}}}},"responses":{"BadRequest":{"description":"Invalid request parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"validation_error":{"summary":"Validation error","value":{"success":false,"error":{"code":"VALIDATION_ERROR","message":"Invalid field value","details":{"field":"content","reason":"Content is required"},"documentation_url":"https://docs.logtalk.io/errors/validation"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}},"content_too_large":{"summary":"Content too large","value":{"success":false,"error":{"code":"CONTENT_TOO_LARGE","message":"Content exceeds maximum size of 50KB","details":{"max_size_bytes":51200},"documentation_url":"https://docs.logtalk.io/errors/validation#content-size"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}}}},"Unauthorized":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_key":{"summary":"Missing API key","value":{"success":false,"error":{"code":"MISSING_API_KEY","message":"Authorization header is required","documentation_url":"https://docs.logtalk.io/errors/authentication#missing-key"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}},"invalid_key":{"summary":"Invalid API key","value":{"success":false,"error":{"code":"INVALID_API_KEY","message":"Invalid API key","documentation_url":"https://docs.logtalk.io/errors/authentication#invalid-key"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}},"expired_key":{"summary":"Expired API key","value":{"success":false,"error":{"code":"EXPIRED_API_KEY","message":"API key has expired","documentation_url":"https://docs.logtalk.io/errors/authentication#expired-key"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}}}},"Forbidden":{"description":"Access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"api_access_denied":{"summary":"API access denied (tier restriction)","value":{"success":false,"error":{"code":"API_ACCESS_DENIED","message":"API access requires Growth tier or higher","details":{"current_tier":"starter","upgrade_url":"https://logtalk.io/pricing"},"documentation_url":"https://docs.logtalk.io/errors/authorization#api-access"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}},"resource_access_denied":{"summary":"Resource access denied","value":{"success":false,"error":{"code":"RESOURCE_ACCESS_DENIED","message":"You do not have access to this resource","documentation_url":"https://docs.logtalk.io/errors/authorization#resource-access"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"CONVERSION_NOT_FOUND","message":"Conversion not found","details":{"id":"123e4567-e89b-12d3-a456-426614174000"},"documentation_url":"https://docs.logtalk.io/errors/resources#conversion"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}},"QuotaExceeded":{"description":"Quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"AUDIO_QUOTA_EXCEEDED","message":"Audio quota exceeded for this billing period","details":{"used":100,"limit":100,"upgrade_url":"https://logtalk.io/pricing","credits_url":"https://logtalk.io/settings/billing"},"documentation_url":"https://docs.logtalk.io/errors/quota#audio"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}},"Timeout":{"description":"Request timeout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"PROCESSING_TIMEOUT","message":"Request timed out waiting for conversion to complete. Use the poll_url to check status.","details":{"poll_url":"https://logtalk.io/api/v1/conversions/123e4567-e89b-12d3-a456-426614174000"},"documentation_url":"https://docs.logtalk.io/errors/timeouts#processing"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}},"IdempotencyConflict":{"description":"Idempotency key conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"IDEMPOTENCY_CONFLICT","message":"Idempotency key already used with different request parameters","documentation_url":"https://docs.logtalk.io/errors/idempotency"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}},"InvalidRetryState":{"description":"Conversion not in failed state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"INVALID_RETRY_STATE","message":"Conversion cannot be retried because it is not in a failed state","details":{"current_status":"completed"},"documentation_url":"https://docs.logtalk.io/errors/retry#invalid-state"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}},"RateLimited":{"description":"Rate limit exceeded","headers":{"Retry-After":{"$ref":"#/components/headers/Retry-After"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"daily_limit":{"summary":"Daily rate limit exceeded","value":{"success":false,"error":{"code":"DAILY_LIMIT_EXCEEDED","message":"Daily rate limit exceeded","details":{"retry_after_seconds":3600},"documentation_url":"https://docs.logtalk.io/errors/rate-limits#daily"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}},"minute_limit":{"summary":"Per-minute rate limit exceeded","value":{"success":false,"error":{"code":"MINUTE_LIMIT_EXCEEDED","message":"Per-minute rate limit exceeded","details":{"retry_after_seconds":30},"documentation_url":"https://docs.logtalk.io/errors/rate-limits#minute"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error":{"code":"INTERNAL_ERROR","message":"An internal error occurred","documentation_url":"https://docs.logtalk.io/errors/server-errors"},"request_id":"req_1kn5f2a_a3b4c5d6e7f8","timestamp":"2026-01-18T12:00:00.000Z"}}}}}}}