# 文字おこしくん (mojiokoshi-kun) Developer Docs > Real-time, per-speaker transcription for Discord voice channels (and any audio you send). Public WebSocket API: Subscribe (`/v1/subscribe`, receive live utterances) and Ingest (`/v1/ingest`, send audio). HTTP API (base URL `https://moji.kaitoranma.com`, OpenAPI 3.1) for session lookup, short-lived session-token minting, transcript export (JSON / text / CSV), shareable transcript download links and usage, authenticated with per-Discord-server API keys (`mjk_live_…`). Outgoing webhooks (`session.started` / `session.ended`, Standard Webhooks signatures) tell your server when transcription starts and ends. Docs are written in Japanese; identifiers, specs and code are English. Discord のボイスチャンネルの会話を話者ごとにリアルタイムで文字にするサービスの開発者向けドキュメント。 Every HTML page under /docs/ has a Markdown twin at the same path with `.md` (linked below). Machine-readable specs: OpenAPI 3.1 (HTTP), AsyncAPI 3.1 and JSON Schema 2020-12 (WebSocket), generated from the same code the server uses and contract-tested against the real server. **Instructions for agents / エージェントへの指示** - Use the reference client (docs/examples/mojiokoshi-subscribe.js or mojiokoshi_subscribe.py) instead of hand-rolling the protocol (the TypeScript SDK is not on npm). 参照実装を使う。 - Never ship an API key (`mjk_live_…`) to browsers, OBS pages, apps, logs or repos. Browsers get only short-lived session tokens (`transcript:read` / `ingest:write`), sent in the first `hello` message and never in the WebSocket URL. API キーをブラウザに置かない。 - Utterance revisions replace by `utteranceId` (keep the highest `revision`; `partial` → `final` → `refined`); never append. On `welcome`, replace the whole state. 発話は utteranceId で置き換える。追記しない。 - Reconnect with exponential backoff + jitter (0.5 s doubling, max 30 s). Stop on `unauthorized`, `protocol_version_unsupported`, `session_ended`, `superseded`, `quota_exceeded`, fatal `invalid_message`, or a `session_ended` message. Accept unknown error codes and follow `error.fatal`. Do not branch on close codes. `unauthorized` などのエラーでは、クライアントは再接続せずに終える。 - Send `{"type":"ping"}` every 15 s after `welcome`; treat ~10 s of silence after a ping as a dead connection. - HTTP: call from server-side code only (no CORS). `Authorization: Bearer mjk_live_…`. Branch on the problem+json `code` (RFC 9457), not on `title`/`detail`. On `429 rate_limited` wait `Retry-After` seconds; `quota_exceeded` (only on deployments with a daily limit; the official service has none) resets at 00:00 UTC; `402 credits_exhausted` is deprecated and no longer returned (since 2026-10-14; transcription, export and the API are free). Send an `Idempotency-Key` (UUID) on `POST /v1/sessions`, `POST /v1/sessions/{sessionId}/tokens` and `POST /v1/sessions/{sessionId}/downloads` and reuse it when retrying. Follow `nextCursor` for pagination. クライアントは、HTTP のエラーを code で分岐し、429 では Retry-After の秒数だけ待つ。 - Validate messages against the JSON Schemas in your tests; ignore unknown fields; render `displayName` / `text` as text, never HTML. - Webhooks: verify `webhook-signature` (Standard Webhooks: `v1,` + base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, key = base64-decoded part after `whsec_`) on the raw body before parsing JSON, compare in constant time, accept if any space-separated `v1` signature matches, and reject a `webhook-timestamp` more than 5 minutes off. Deduplicate by `webhook-id` (delivery is at-least-once and unordered). Return 2xx quickly and do slow work afterwards; ignore unknown event types and fields (still return 2xx); return `410` only to stop deliveries. Events that happen while the endpoint is paused or stopped are never sent later; reconcile with `GET /v1/sessions` when you must not miss a session. Keep the `whsec_…` secret server-side. Webhook の受け取る側は、生の本文で署名を確かめ、webhook-id で重複を捨てる。 ## Docs - [はじめに / Overview](https://moji.kaitoranma.com/docs/index.md): what you can build, what you need to start (API key vs session token, who issues them, where each may live), spec files and reference clients - [クイックスタート / Quickstart](https://moji.kaitoranma.com/docs/quickstart.md): get a token (from the Discord overlay link or with an API key), subscribe with the JS reference client or Python, export with curl - [発話の改訂モデル / Revision model](https://moji.kaitoranma.com/docs/revisions.md): partial → final → refined, replace by utteranceId, ordering, speakers - [再接続とエラーの扱い / Reconnection and errors](https://moji.kaitoranma.com/docs/reconnection.md): backoff, stop codes, liveness, token expiry ## Guides - [オーバーレイ / OBS and custom overlays](https://moji.kaitoranma.com/docs/guides/overlay.md): single-file caption overlay - [ボットへの中継 / Relay bots](https://moji.kaitoranma.com/docs/guides/bot-relay.md): forward final utterances, edit on refined - [記録と書き出し / Archive and export](https://moji.kaitoranma.com/docs/guides/archive.md): HTTP export (JSON / text / CSV), download links (`disposition=inline` to display instead of download, `chatgptUrl` to open the transcript in ChatGPT), idempotent upsert by revision - [分析 / Analytics](https://moji.kaitoranma.com/docs/guides/analytics.md): per-speaker statistics - [音声を送る / Ingest guide](https://moji.kaitoranma.com/docs/ingest.md): handshake, state_synced, audio formats, 7-byte binary frame header, sequence numbers ## Reference - [WebSocket API リファレンス](https://moji.kaitoranma.com/docs/reference.md): every message, field table and example (generated from the schemas) - [HTTP API リファレンス / HTTP API reference](https://moji.kaitoranma.com/docs/http.md): every endpoint with auth/scopes, parameters, fields, errors and examples (generated from openapi.yaml); TypeScript / Python examples at the end: list your sessions, export a transcript, mint a transcript:read token and subscribe live, check usage - [Webhook リファレンス / Webhook reference](https://moji.kaitoranma.com/docs/webhooks.md): outgoing webhooks registered by the Discord server's admin in the dashboard (`session.started`, `session.ended`, `webhook.test`), payload fields and examples (generated from the `webhooks` of openapi.yaml), Standard Webhooks signature verification with a test vector, 2xx / 410 handling, retry schedule (8 attempts over about 27.6 hours), at-least-once and unordered delivery, and the "do not store transcripts" flow (on `session.started` mint a transcript:read token with your API key and subscribe) - [エラーコード / Error codes](https://moji.kaitoranma.com/docs/errors/index.md): WebSocket and HTTP codes, what to do, whether the connection stays open - [レート制限と上限 / Limits](https://moji.kaitoranma.com/docs/limits.md): WebSocket limits (64 tracks and 256 speakers per Ingest connection; 20 open tracks at once in total across all sessions created with API keys, including other users' keys, refused with track_limit_exceeded), per-Discord-server limits (no credits, no daily limit and no per-server concurrent-track limit on the official service; retention 30/90/180/365 days by Discord server level, and records not yet deleted are kept longer when the level goes up; 25 active API keys), HTTP rate limits (120 req/min), token TTLs - [表示ページの URL パラメータと CSS / Viewer URL parameters and CSS](https://moji.kaitoranma.com/docs/viewer.md): URL parameters of the official viewer page and OBS overlay (view: seats / captions / lanes / meeting / flow, plus telop and youtube with `overlay=1`; theme, scale, lines, fadeSeconds, hideNames…; the stage and timeline views were removed and open as seats and lanes), custom CSS variables for the OBS browser source, the YouTube-chat DOM of `view=youtube` (paste YouTube live-chat CSS into OBS custom CSS), demo mode (`?demo=1`) - [変更履歴 / Changelog](https://moji.kaitoranma.com/docs/changelog.md) ## Specs - [openapi.yaml](https://moji.kaitoranma.com/docs/openapi.yaml): OpenAPI 3.1 for the HTTP API (security schemes, problem details, RateLimit / Retry-After / Idempotency-Key headers, examples for every operation) - [asyncapi.yaml](https://moji.kaitoranma.com/docs/asyncapi.yaml): AsyncAPI 3.1 for /v1/ingest and /v1/subscribe - [schemas/common.json](https://moji.kaitoranma.com/docs/schemas/common.json): JSON Schema 2020-12, shared definitions - [schemas/ingest-client-message.json](https://moji.kaitoranma.com/docs/schemas/ingest-client-message.json) - [schemas/ingest-server-message.json](https://moji.kaitoranma.com/docs/schemas/ingest-server-message.json) - [schemas/subscribe-client-message.json](https://moji.kaitoranma.com/docs/schemas/subscribe-client-message.json) - [schemas/subscribe-server-message.json](https://moji.kaitoranma.com/docs/schemas/subscribe-server-message.json) - [errors.json](https://moji.kaitoranma.com/docs/errors.json): machine-readable error catalog (WebSocket and HTTP codes) ## Examples - [mojiokoshi-subscribe.js](https://moji.kaitoranma.com/docs/examples/mojiokoshi-subscribe.js): dependency-free Subscribe client for browsers, Node 22+, Deno, Bun - [mojiokoshi_subscribe.py](https://moji.kaitoranma.com/docs/examples/mojiokoshi_subscribe.py): Python 3.10+ Subscribe client (websockets) - [mojiokoshi-http.ts](https://moji.kaitoranma.com/docs/examples/mojiokoshi-http.ts): dependency-free HTTP API client (TypeScript; Node 22.18+, Deno, Bun; server-side only) - [mojiokoshi_http.py](https://moji.kaitoranma.com/docs/examples/mojiokoshi_http.py): HTTP API client + CLI (Python 3.10+, standard library only; server-side only) - [mojiokoshi-webhook.ts](https://moji.kaitoranma.com/docs/examples/mojiokoshi-webhook.ts): dependency-free webhook signature verifier (TypeScript, Web Crypto; Node 22.18+, Deno, Bun, Cloudflare Workers) - [mojiokoshi_webhook.py](https://moji.kaitoranma.com/docs/examples/mojiokoshi_webhook.py): webhook signature verifier + test receiver (Python 3.10+, standard library only) - [Agent Skill (SKILL.md)](https://moji.kaitoranma.com/docs/skill/SKILL.md): installable skill for coding agents ## Optional - [llms-full.txt](https://moji.kaitoranma.com/docs/llms-full.txt): all developer docs concatenated - [利用規約 / Terms](https://moji.kaitoranma.com/legal/terms.html): free transcription, export and API; monthly support for a Discord server (the only paid item); Discord server levels and retention; refunds and chargebacks; supporter display and role; webhooks (the Discord server's admin registers only URLs they may use and is responsible for the receiving system; delivery, timing and order are not guaranteed); prohibited acts (including using webhooks against URLs the admin has no right to use) - [プライバシーポリシー / Privacy](https://moji.kaitoranma.com/legal/privacy.html): what is collected (transcripts, Discord IDs, dashboard login, monthly support, webhook endpoint settings and delivery log), recipients (Google LLC in the US for speech recognition, audio only, with participants' consent; the bot announces this in the voice channel's chat when transcription starts; OpenRouter only for opted-in AI-refine tester Discord servers; Stripe; Discord; Cloudflare R2/D1 and Workers; on the Discord server admin's instruction, webhook endpoints the admin registers receive session start/end details only: no transcript text, speaker names or user IDs, or audio), who can see what (members see records of voice channels they can view and connect to; anyone who can read the text channel an admin chose sees utterances posted there; supporters are shown to server members as each payer chose), retention and deletion - [データの流れと保存期間 / Data flow and retention](https://moji.kaitoranma.com/legal/data-flow.html): where audio and text travel, what is stored where and for how long (audio never stored; transcripts 30/90/180/365 days by Discord server level; webhook endpoint settings until the admin deletes them; webhook delivery log 7 days after each delivery finishes, and deleted with its session or endpoint; backups ≤ 7 days after deletion; webhooks are signed and sent from Cloudflare Workers, not from the operator's server), no model training by the operator, export/delete, security measures - [特定商取引法に基づく表記 / Commerce disclosure](https://moji.kaitoranma.com/legal/tokushoho.html): monthly support (¥50–30,000 per month) that extends a Discord server's transcript retention by server level (no credits, rates or expiry), card payment via Stripe, refunds, cancellation