{"openapi":"3.1.0","info":{"title":"Word Timing API","description":"Word-level speech timings with render-ready subtitle exports. See GET /v1/render-profile for the timing rules our own player uses.","version":"1.0.0"},"paths":{"/health":{"get":{"summary":"Health","description":"Liveness check. Returns status and the available tiers. No key required.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/llms.txt":{"get":{"summary":"Llms Txt","description":"Integration guide written for an automated agent, at the conventional path.\n\nCustomers increasingly point an agent at an API rather than reading the docs\nthemselves, and an agent that has to infer the contract gets it wrong in\npredictable ways. This encodes what three independent evaluations each had to\nlearn the hard way — set a client timeout, handle the 202 hand-off, retry a 503\nonce, never assert an exact word count, upload PCM for the tightest timings —\nalongside the endpoint reference and an explicit action per error code.\n\nUnauthenticated on purpose: an agent evaluating whether to integrate should be\nable to read it before a key exists. It describes the contract only, never how\nany of it is implemented.","operationId":"llms_txt_llms_txt_get","responses":{"200":{"description":"Successful Response"}}}},"/guide.md":{"get":{"summary":"Guide Md","description":"The full integration guide as raw Markdown. No key required.","operationId":"guide_md_guide_md_get","responses":{"200":{"description":"Successful Response"}}}},"/guide":{"get":{"summary":"Guide","description":"Rendered human integration guide. The URL to put in a handover email.","operationId":"guide_guide_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/render-demo/sample.mp4":{"get":{"summary":"Render Demo Sample","description":"A 7-second synthetic clip so the demo works with nothing prepared.\n\nSynthesised speech over a flat background, ~96KB. Deliberately not a real\nrecording: this ships inside the image and is served to anyone, so it must carry\nno rights and no customer's content. It also makes the page reachable by\nautomated checks, which cannot drive a file picker.","operationId":"render_demo_sample_render_demo_sample_mp4_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/render-demo":{"get":{"summary":"Render Demo","description":"Side-by-side proof that the render rules matter.\n\n\"Accurate timings rendered naively still look wrong\" is the least believable\nthing we tell customers, and the hardest to demonstrate in prose. This drives a\nnaive renderer and a rule-following one from the same video clock on the same\npayload, with each rule switchable, so a customer can see the difference on\ntheir own footage instead of taking it on trust.\n\nUnauthenticated to load, like the dashboard: it is a static page and the key is\nentered in the browser, so no key ever reaches a URL or our logs.","operationId":"render_demo_render_demo_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/dashboard":{"get":{"summary":"Dashboard","description":"Self-serve dashboard: usage, recent requests, and a try-it upload.\n\nThe static shell is public, but every customer-data request requires the\nHttpOnly dashboard session. The API key never enters the browser.","operationId":"dashboard_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/v1/render-profile":{"get":{"summary":"Render Profile","description":"The timing rules our own player uses, plus a reference implementation.\n\nDeliberately unauthenticated: it is documentation, contains no customer data,\nand someone evaluating the API should be able to read it before signing.","operationId":"render_profile_v1_render_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/render-profile.js":{"get":{"summary":"Render Profile Module","description":"The reference renderer as an importable ES module.\n\nServed so the dashboard can `import` it instead of carrying its own copy:\nour demo then runs the exact code a customer is handed, which is the only\nway to be sure the published snippet actually works.","operationId":"render_profile_module_v1_render_profile_js_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/transcribe":{"post":{"summary":"Transcribe","description":"**Field notes.** `start_ms` is the load-bearing number: `end_ms` carries a\n`min_word_duration_ms` floor and may therefore overrun the next word's start, so\nbuild highlight windows with `[word.start_ms, next_word.start_ms)` as\n`/v1/render-profile` describes. `boundaries_estimated: true` means word boundaries\nfor this request are approximate; it is only ever returned for space-separated\nlanguages, and a request that cannot be given reliable boundaries fails with a\nretryable 503 rather than returning poor ones. Subtitle exports are always\ngenerated from the unshifted timeline, even when `bake_lead` shifts `words` and\n`segments`, because a burned-in or `<track>`-rendered caption has no decode\nlatency to compensate for.","operationId":"transcribe_v1_transcribe_post","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_transcribe_v1_transcribe_post"}}}},"responses":{"200":{"description":"Word timings, caption segments, render constants, and any requested subtitle exports.","content":{"application/json":{"schema":{},"example":{"request_id":"9f1c8b2e-3a4d-4e5f-8a9b-0c1d2e3f4a5b","status":"completed","tier":"accurate","timing_engine":"precision-v1","language":"ja","language_confidence":0.9912,"duration_ms":42500,"audio_seconds":42.5,"processing_ms":11840,"word_count":132,"boundaries_estimated":false,"text":"これは本です。","words":[{"index":0,"text":"これ","start_ms":259,"end_ms":640,"speaker":"speaker_1","segment":0}],"segments":[{"index":0,"text":"これは本です。","start_ms":259,"end_ms":3279,"speaker":"speaker_1","first_word":0,"last_word":4}],"render":{"lead_ms_applied":0,"recommended_lead_ms":300,"remaining_lead_ms":300,"highlight_rule":"until_next_word_start","min_word_duration_ms":120,"extrapolation_cap_ms":200,"player_poll_interval_ms":150,"segment_hysteresis_ms":90,"hold_last_segment":true,"profile_url":"/v1/render-profile"},"exports":{"srt":"1\n00:00:00,259 --> 00:00:03,279\n…"}}}}},"202":{"description":"Accepted but not finished. Poll `poll_url`; the completed body is identical to a 200 here. Returned when `background=true` or when the work outlasts the inline window.","content":{"application/json":{"example":{"request_id":"9f1c8b2e-3a4d-4e5f-8a9b-0c1d2e3f4a5b","status":"processing","poll_url":"/v1/jobs/9f1c8b2e-3a4d-4e5f-8a9b-0c1d2e3f4a5b"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/jobs/{request_id}":{"get":{"summary":"Get Job","operationId":"get_job_v1_jobs__request_id__get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/requests/{request_id}":{"get":{"summary":"Get Job","operationId":"get_job_v1_requests__request_id__get","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","title":"Request Id"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/requests":{"get":{"summary":"List Requests","description":"Recent requests for the calling key, newest first, without transcripts. Use `limit` and `offset` to page back through history when reconciling usage.","operationId":"list_requests_v1_requests_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/usage":{"get":{"summary":"Get Usage","description":"Month-to-date usage for the calling key.","operationId":"get_usage_v1_usage_get","parameters":[{"name":"X-API-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_transcribe_v1_transcribe_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"Audio or video file (any container ffmpeg reads)"},"tier":{"type":"string","title":"Tier","description":"'accurate' (word-level boundaries and sentence segments; required for languages written without spaces) or 'fast' (cheaper and quicker; equivalent word timings on space-separated languages, character-level units on unspaced ones)","default":"accurate"},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","description":"Optional ISO language hint (fast tier only)"},"preprocess":{"type":"boolean","title":"Preprocess","description":"Denoise + normalize before transcription","default":true},"bake_lead":{"type":"boolean","title":"Bake Lead","description":"Pre-shift timings by our recommended lead","default":false},"lead_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lead Ms","description":"Explicit lead to pre-shift by (implies bake_lead)"},"formats":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Formats","description":"Comma-separated subtitle exports: srt,vtt,ass"},"fresh":{"type":"boolean","title":"Fresh","description":"Force reprocessing instead of replaying an identical recent upload","default":false},"background":{"type":"boolean","title":"Background","description":"Return 202 + request_id immediately instead of waiting for the result","default":false},"translate_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Translate To","description":"Optional target language for sentence-level translation of each segment: 'en'. Word timings stay in the source language"}},"type":"object","required":["file"],"title":"Body_transcribe_v1_transcribe_post"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}