{"openapi":"3.1.0","info":{"title":"Capshape API","version":"0.1.0","description":"A fully local caption/subtitle timing & readability calculator: recommended on-screen duration, characters-per-line checks and line-splitting, reading-pace verification, and script-level caption-count estimation, against reading-speed profiles sourced from published subtitle style guides.\n\nEvery operation is read-only or compute-only. The same tools are available over MCP (streamable HTTP) at https://capshape.connectorbay.com/mcp.","contact":{"name":"Unify Dynamics LLC","email":"hr@unifydynamics.com","url":"https://connectorbay.com/capshape/docs"},"termsOfService":"https://connectorbay.com/capshape/terms"},"servers":[{"url":"https://capshape.connectorbay.com"}],"externalDocs":{"url":"https://connectorbay.com/capshape/docs"},"security":[{},{"bearer":[]}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Optional. A Pro API key raises rate limits; no credentials are required."}},"schemas":{"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object"}}}}},"paths":{"/v1/tools/recommended_duration":{"post":{"operationId":"recommended_duration","summary":"Computes how long a caption should stay on screen, from its character count and a reading-speed profile,","description":"Computes how long a caption should stay on screen, from its character count and a reading-speed profile,\n    clamped to that profile's min/max duration. Use for \"how long should this caption stay on screen\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"text":{"description":"The caption/subtitle text.","examples":["This is a sample subtitle line."],"minLength":1,"title":"Text","type":"string"},"profile":{"default":"netflix_adult","description":"'netflix_adult', 'netflix_children', or 'bbc_general'.","title":"Profile","type":"string"}},"required":["text"],"title":"recommended_durationArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/characters_per_line_check":{"post":{"operationId":"characters_per_line_check","summary":"Checks each line of a caption against a profile's max characters-per-line and max-lines limits. Use for","description":"Checks each line of a caption against a profile's max characters-per-line and max-lines limits. Use for\n    \"does this line fit Netflix's character limit\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"text":{"description":"Caption text; use \\n to separate existing lines.","examples":["This line might be a bit too long for the limit"],"minLength":1,"title":"Text","type":"string"},"profile":{"default":"netflix_adult","description":"'netflix_adult', 'netflix_children', or 'bbc_general'.","title":"Profile","type":"string"}},"required":["text"],"title":"characters_per_line_checkArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/split_into_lines":{"post":{"operationId":"split_into_lines","summary":"Word-wraps a longer caption into balanced lines, each under a character-per-line limit, up to a max","description":"Word-wraps a longer caption into balanced lines, each under a character-per-line limit, up to a max\n    number of lines. Use for \"split this caption into two balanced lines under 42 characters\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"text":{"description":"A longer caption to word-wrap.","examples":["This is a longer caption that needs to be split into two balanced lines"],"minLength":1,"title":"Text","type":"string"},"max_cpl":{"default":42,"description":"Max characters per line.","minimum":5,"title":"Max Cpl","type":"integer"},"max_lines":{"default":2,"description":"Max lines allowed.","maximum":4,"minimum":1,"title":"Max Lines","type":"integer"}},"required":["text"],"title":"split_into_linesArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/pacing_check":{"post":{"operationId":"pacing_check","summary":"Given a caption and its assigned duration, computes the actual reading pace and verdicts whether it's","description":"Given a caption and its assigned duration, computes the actual reading pace and verdicts whether it's\n    too fast, too slow, comfortably loose, or well-paced. Use for \"is 3 seconds too fast for this caption\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"text":{"description":"The caption text.","minLength":1,"title":"Text","type":"string"},"duration_seconds":{"description":"The duration actually assigned to this caption.","examples":[2.5],"exclusiveMinimum":0,"title":"Duration Seconds","type":"number"},"profile":{"default":"netflix_adult","description":"'netflix_adult', 'netflix_children', or 'bbc_general'.","title":"Profile","type":"string"}},"required":["text","duration_seconds"],"title":"pacing_checkArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/estimate_script_caption_count":{"post":{"operationId":"estimate_script_caption_count","summary":"Estimates how many caption cards a full script/transcript will need and the total on-screen caption time.","description":"Estimates how many caption cards a full script/transcript will need and the total on-screen caption time.\n    Use for \"how many captions will a 500-word script need\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"script_text":{"description":"A full script or transcript.","minLength":1,"title":"Script Text","type":"string"},"profile":{"default":"netflix_adult","description":"'netflix_adult', 'netflix_children', or 'bbc_general'.","title":"Profile","type":"string"},"words_per_caption":{"default":8,"description":"Target average words per caption card.","maximum":30,"minimum":1,"title":"Words Per Caption","type":"integer"}},"required":["script_text"],"title":"estimate_script_caption_countArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/convert_reading_speed":{"post":{"operationId":"convert_reading_speed","summary":"Converts between words-per-minute and characters-per-second reading-speed units. Use for \"convert 170","description":"Converts between words-per-minute and characters-per-second reading-speed units. Use for \"convert 170\n    words per minute to characters per second\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"value":{"description":"The reading speed value to convert.","examples":[170],"exclusiveMinimum":0,"title":"Value","type":"number"},"from_unit":{"default":"wpm","description":"'wpm' or 'cps'.","title":"From Unit","type":"string"},"to_unit":{"default":"cps","description":"'wpm' or 'cps'.","title":"To Unit","type":"string"},"avg_word_length_chars":{"default":6.0,"description":"Assumed average characters per word, including the trailing space.","exclusiveMinimum":0,"title":"Avg Word Length Chars","type":"number"}},"required":["value"],"title":"convert_reading_speedArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/caption_profile_reference":{"post":{"operationId":"caption_profile_reference","summary":"Full detail for a named reading-speed/layout profile (netflix_adult, netflix_children, bbc_general), or","description":"Full detail for a named reading-speed/layout profile (netflix_adult, netflix_children, bbc_general), or\n    every profile if none given. Use for \"what's Netflix's character-per-line limit\", \"list your caption\n    profiles\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"profile":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"A profile name; omit to list all.","title":"Profile"}},"title":"caption_profile_referenceArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}},"/v1/tools/caption_glossary":{"post":{"operationId":"caption_glossary","summary":"Definitions of core captioning terms: CPS, CPL, lead-in/lead-out time, gap, shot-change sensitivity, SDH,","description":"Definitions of core captioning terms: CPS, CPL, lead-in/lead-out time, gap, shot-change sensitivity, SDH,\n    closed captions, burned-in captions, reading speed. Use for \"what does CPS mean\", \"what's SDH\".","tags":["tools"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"properties":{"term":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"A specific term to look up; omit to list all.","title":"Term"}},"title":"caption_glossaryArguments","type":"object"}}}},"responses":{"200":{"description":"Tool result. `ok: true` on success; `ok: false` with a structured `error` (provider_unavailable, upstream_error, bad_input) when the tool could not answer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"422":{"description":"Arguments failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (see Retry-After)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-read-only":true}}}}