Agent Workflow
- Read this HTML document, then use /openapi.json as the canonical request and response contract.
- If you do not already have a credential, follow /auth.md to claim a WorkOS API key.
- If the source is video or non-MP3 audio, extract speech audio locally as MP3 before upload.
- Upload the extracted MP3 with
PUT /audio/:keyand the WorkOS API key as bearer auth. - Start
POST /workflows/captioner?wait=resultwith a JSON payload. Usewait=resultwhen you need the completed captions in the response. - Save the returned JSON and SRT near the source media unless the user asks for another destination.
Authentication
Bearer auth with a WorkOS API Key is required for PUT /audio/:key and POST /workflows/captioner?wait=result.
Required scopes: captioner:audio:upload, captioner:caption:run.
Use an existing stored Captioner credential first. If none exists, use /auth.md to claim a WorkOS organization-scoped API key. Store durably only with user consent; never print it or persist it in logs.
macOS Keychain convention: service captioner.chan.dev, account equal to the verified email. After a successful claim, ask once: Store this Captioner API key in macOS Keychain for future runs?
# Store after user consent. Keep the key in CAPTIONER_API_KEY and never echo it.
CAPTIONER_EMAIL="user@example.com"
security add-generic-password -s captioner.chan.dev -a "$CAPTIONER_EMAIL" -U -w "$CAPTIONER_API_KEY"
# Reuse when the verified email is known.
CAPTIONER_API_KEY="$(security find-generic-password -s captioner.chan.dev -a "$CAPTIONER_EMAIL" -w)"
# Remove a revoked or invalid key.
security delete-generic-password -s captioner.chan.dev -a "$CAPTIONER_EMAIL"
Resources
- GET /robots.txt advertises crawl policy and the sitemap.
- GET /sitemap.xml lists canonical public discovery URLs.
- GET /.well-known/api-catalog serves the RFC 9727 API catalog.
- GET /auth.md describes agent registration and credential use.
- GET /.well-known/oauth-protected-resource advertises the protected resource metadata.
- GET /.well-known/oauth-authorization-server advertises the authorization server metadata.
- GET /.well-known/mcp/server-card.json serves the MCP Server Card.
- GET /.well-known/agent-skills/index.json serves the agent skills discovery index.
- GET /openapi.json is the canonical request and response contract.
- GET /terminology/packs lists terminology pack metadata.
- GET /skills/captioner/SKILL.md serves the installable agent skill.
PUT /audio/:keyuploads audio with WorkOS bearer auth.POST /workflows/captioner?wait=resultruns the workflow with WorkOS bearer auth.
Media Policy
Accepted upload media types: audio/mpeg.
Upload keys must end in .mp3 and files must be no larger than 100 MiB. Non-MP3 uploads return 415 mp3_required; oversized uploads return 413 upload_too_large. Extract the first speech audio track locally as MP3 before upload.
Recommended extraction
ffmpeg -i input.mp4 -map 0:a:0 -vn -ac 1 -ar 16000 -c:a libmp3lame -b:a 32k output.mp3
Fallback for noisy or compressed sources
ffmpeg -i input.mp4 -map 0:a:0 -vn -ac 1 -ar 16000 -c:a libmp3lame -b:a 48k output.mp3
Requests
Upload MP3
curl -X PUT "https://caption.chan.dev/audio/uploads/demo.mp3" \
-H "Authorization: Bearer $CAPTIONER_API_KEY" \
-H "Content-Type: audio/mpeg" \
--data-binary @output.mp3
Run captioner
curl "https://caption.chan.dev/workflows/captioner?wait=result" \
-H "Authorization: Bearer $CAPTIONER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"audio":{"key":"uploads/demo.mp3","mediaType":"audio/mpeg"},"topic":"MCP Night","glossary":["MCP","Cloudflare","WorkOS"]}'
Minimal payload
{
"audio": {
"key": "uploads/demo.mp3",
"mediaType": "audio/mpeg"
},
"topic": "MCP Night",
"glossary": [
"MCP",
"Cloudflare",
"WorkOS"
]
}
Optional fields for terminology packs, provider selection, caption settings, and storage retention are documented in /openapi.json.
Terminology
Use payload.terminology.packs for explicit packs; otherwise packs are selected from topic, filename, glossary, and keyterms.
Available pack IDs:
events/mcp-nightprotocols/mcpdomains/ai-agentsdomains/b2b-saasvendors/cloudflarevendors/workosidentity-auth
Fetch /terminology/packs for pack titles, descriptions, triggers, related packs, and term counts.
Result
With wait=result, the workflow response is a JSON envelope. Read plain transcript text from result.transcript.text and the caption file from result.captions.srt.
Caption cues are generated from punctuated and capitalized transcript tokens, so cue text can differ from raw lowercase word fields. Read deterministic cue QC from result.quality.captions.
Useful result paths: result.transcript, result.audit, result.metadata.terminology.observations, and result.metadata.storage.sourceAudio.
Source audio is deleted as soon as transcription has consumed it by default, and deletion is retried if the workflow fails. Set payload.storage.retainSourceAudio=true only when a rerun or debug pass needs the uploaded audio to stay in R2.
Machine-Readable Contract
This HTML includes <script type="application/json" id="captioner-agent-contract"> with the same discovery data. The API schema remains at /openapi.json. When requested with Accept: text/markdown, this page returns Markdown with Content-Type: text/markdown.