Transcripts
Record meetings and calls on any device, get a diarized Romanian/English transcript with word timings, then a summary, key points, actions and ready-to-run agent prompts.
Transcripts turns a recording into searchable text and something you can act on. The desktop app, the phone and the watch record locally and upload in the background; the gateway transcribes with speaker labels and word timings (Romanian and English, mixed in one recording too), then writes the insights: a title, a summary, cited key points, actions, decisions, open questions and agent prompts you can launch.
Transcripts is enabled per account while it is in preview. When it is off for your key, every
endpoint below answers 404.
How a recording flows
- Create.
POST /v1/transcriptswith a client-generatedclient_id(a retry after a crash returns the same transcript) andstarted_at. Statusrecording. - Upload. Each track (
mic,systemloopback, or onemixedtrack) goes up with tus 1.0 at/v1/uploads: resumable, at most 8 MB perPATCH, so a dropped connection or a restart continues from the last byte the server holds (HEAD /v1/uploads/{id}). Upload ids belong to your account; another key cannot append to them. - Finalize.
POST /v1/transcripts/{id}/finalizewith the upload ids, the duration, bookmarks and (optionally) the live preview text. Statusqueued. - Transcribe. The worker cuts the audio into windows of up to 15 minutes (diarization limit) and sends them to Gemini 3.5 Transcribe. Speakers are matched across windows. Status
transcribing, thenanalyzing. - Insights. A model writes the insights from the transcript (prompt caching on). Status
ready. A failure after 5 attempts ends infailedwitherror;POST …/retranscribeand…/reanalyzere-run a step.
While a step retries, status does not change; GET /v1/transcripts/{id} returns processing with attempts, max_attempts, last_error and next_attempt_at, so a client can say "retrying" instead of looking stuck. GET /v1/transcripts/stream (server-sent events) sends a transcript event on every status change.
Live view. While recording, the device can POST /v1/transcripts/{id}/live with its rolling caption (finals, partial, level, device, elapsed_ms, paused) about once a second. Every viewer of the stream (the hub detail page, desktop, phone, watch) receives it as op: live; nothing is stored, and frames closer than 250 ms are dropped.
import { readFile } from 'node:fs/promises';
import { Codai } from 'codai-sdk';
const codai = new Codai({ apiKey: process.env.CODAI_API_KEY! });
const t = await codai.transcripts.create({
client_id: crypto.randomUUID(),
source: 'desktop',
started_at: new Date().toISOString(),
});
const uploadId = await codai.transcripts.uploadAudio(await readFile('meeting.ogg'), {
transcriptId: t.id,
onProgress: (sent, total) => console.log(`${sent}/${total}`),
});
await codai.transcripts.finalize(t.id, {
duration_ms: 1_800_000,
uploads: [{ track: 'mic', upload_id: uploadId }],
});
for await (const e of codai.transcripts.stream()) if (e.id === t.id && e.status === 'ready') break;
const done = await codai.transcripts.get(t.id);
console.log(done.insights?.summary);from codai import Codai
codai = Codai(api_key="codai_...")
t = codai.transcripts.create({"client_id": "rec-2026-10-06-1", "source": "desktop", "started_at": "2026-10-06T09:00:00Z"})
upload_id = codai.transcripts.upload_audio(open("meeting.ogg", "rb").read(), transcript_id=t["id"])
codai.transcripts.finalize(t["id"], {"duration_ms": 1_800_000, "uploads": [{"track": "mic", "upload_id": upload_id}]})
srt = codai.transcripts.export(t["id"], "srt")["text"]Working with a transcript
- Read.
GET /v1/transcripts/{id}: speakers (rename one, or mark yourself, withPATCH …/speakers/{label}), utterances with word timings (correct one withPATCH …/utterances/{seq}), bookmarks and the latest insights. - Search and ask.
GET /v1/transcripts/searchis full-text plus semantic (mode=hybrid, the default).POST /v1/transcripts/askanswers a question across your recordings with[n]citations to the transcript, speaker and time. - Act. Insights carry suggested agent
prompts;POST …/prompts/{index}/acceptturns one into a pending prompt withsource: transcript, ready to launch on a device. - Export and play.
GET …/export?format=md|txt|srt|vtt|json|pdf|docx(see below);GET …/audioreturns short-lived signed playback URLs per track. - Organise. Folders (
/v1/transcript-folders), tags and pins; a personal vocabulary (PUT /v1/transcript-vocabulary) for names and jargon the transcriber should spell right.
Export as PDF or Word
GET /v1/transcripts/{id}/export?format=pdf and format=docx return a binary attachment named after the title (an ASCII filename plus the exact title in filename*). The document holds the title, date, duration and speakers, then the summary, key points and actions when the insights exist, then the speaker-labelled transcript with [hh:mm:ss] timestamps. The PDF embeds a Unicode font, so Romanian diacritics (ș, ț, ă, î, â) print correctly. Labels follow the transcript language (Romanian or English).
import { writeFile } from 'node:fs/promises';
const pdf = await codai.transcripts.export(t.id, 'pdf'); // { bytes, filename, contentType }
await writeFile(pdf.filename ?? 'transcript.pdf', pdf.bytes);docx = codai.transcripts.export(t["id"], "docx") # {"bytes", "filename", "content_type"}
open(docx["filename"] or "transcript.docx", "wb").write(docx["bytes"])Share a read-only link
POST /v1/transcripts/{id}/shares with an optional expiresInDays (1–365; omit it for a link that never expires) returns { id, token, url, expiresAt }, where url is https://hub.codai.ro/t/<token>. Anyone with the link can read the title, speakers, transcript, summary, key points and actions, never the audio, and nothing that identifies your account. Decisions, open questions and suggested agent prompts stay private.
- The token is 32 random bytes and is shown once: only its SHA-256 is stored, so
GET …/shareslists the active links withurl: null. DELETE …/shares/{shareId}revokes a link immediately; deleting the transcript removes all its links.- The page behind the link reads
GET /v1/public/transcripts/{token}, which needs no API key, is rate-limited per visitor and answers404for an unknown, expired or revoked link.
const link = await codai.transcripts.shares.create(t.id, { expiresInDays: 30 });
console.log(link.url); // copy it now; it cannot be shown again
const active = await codai.transcripts.shares.list(t.id);
await codai.transcripts.shares.revoke(t.id, active[0]!.id);Privacy, retention and limits
- Audio lives in an EU bucket encrypted with a dedicated key and is deleted after 30 days; the transcript text and insights stay until you delete them. After the audio is gone,
audio_purged_atis set and playback and re-transcription are no longer offered. DELETE /v1/transcripts/{id}removes the transcript and its audio. Account deletion removes all recordings; the account export includes every transcript table (not the audio).- Up to 3 hours per recording and 20 hours a month per account (
GET /v1/transcripts/usage).
MCP tools
The MCP server exposes list_transcripts, get_transcript, search_transcripts, ask_transcripts, export_transcript (text formats only; PDF and Word are binary files), accept_transcript_prompt and transcript_share_create, called with your API key (OAuth tokens are refused). Deleting, revoking links, re-running and editing stay in the apps.
bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
status?stringOnly transcripts in this status.
"recording""uploading""queued""transcribing""analyzing""ready""failed"folder_id?stringOnly transcripts in this folder.
uuidpinned?booleanFilter by pinned state: true/1 only pinned, false/0 only unpinned.
tag?stringOnly transcripts carrying this tag.
length <= 40cursor?stringnext_cursor of the previous page (an ISO datetime); returns older transcripts.
length <= 200limit?integerPage size (1–100).
1 <= value <= 10030x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128One page of transcripts.
application/json- response
transcripts*array<>next_cursor*|Cursor for the next page; null on the last page.
curl -X GET 'https://ai.codai.ro/v1/transcripts'{ "transcripts": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ], "next_cursor": "string"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
title?stringlength <= 200source*string"desktop""phone""wear""web""vscode""tv""api"template?TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint?string2 <= length <= 12"auto"tracks?array<>1 <= items <= 2folder_id?|uuidclient_id*stringClient-generated id; a create retried after a crash returns the same transcript.
8 <= length <= 64started_at*stringdate-timefeed_memory?booleanfalseThe transcript (new, or the existing one for this client_id).
application/json- response
id*stringuuidclient_id*stringtitle*stringstatus*TranscriptStatusLifecycle: recording → uploading → queued → transcribing → analyzing → ready, or failed.
"recording""uploading""queued""transcribing""analyzing""ready""failed"source*string"desktop""phone""wear""web""vscode""tv""api"template*TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint*stringauto, ro, en or another BCP-47 tag passed to the recognizer.
language*|Detected language, once transcribed.
folder_id*|uuidpinned*booleantags*array<string>feed_memory*booleanOpt-in for extracted facts to feed codai memory.
started_at*stringdate-timeduration_ms*integer0 <= valueerror*string|nullaudio_available*booleanfalse once the 30-day retention deleted the audio.
ready_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X POST 'https://ai.codai.ro/v1/transcripts' \ -H 'Content-Type: application/json' \ -d '{ "source": "desktop", "client_id": "stringst", "started_at": "2019-08-24T14:15:22Z"}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Allowance used and remaining.
application/json- response
used_ms*integer0 <= valuecap_ms*integer0 <= valueremaining_ms*integer0 <= valueperiod_start*stringdate-timecurl -X GET 'https://ai.codai.ro/v1/transcripts/usage'{ "used_ms": 0, "cap_ms": 0, "remaining_ms": 0, "period_start": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128SSE stream (text/event-stream, cache-control: no-cache).
response?stringtext/event-streamcurl -X GET 'https://ai.codai.ro/v1/transcripts/stream'"string"bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
q*stringSearch query.
1 <= length <= 500mode?stringSearch mode.
"hybrid""hybrid""text""semantic"limit?integerMaximum utterance hits (1–50).
1 <= value <= 5020x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Utterance hits and title hits.
application/json- response
hits*array<>titles*array<>curl -X GET 'https://ai.codai.ro/v1/transcripts/search?q=string'{ "hits": [ { "transcript_id": "215670dc-b708-4c27-9393-0b9ca7d8935d", "title": "string", "start_ms": 0, "end_ms": 0, "speaker": "string", "snippet": "string" } ], "titles": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "title": "string" } ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
question*string3 <= length <= 2000transcript_ids?array<>Restrict retrieval to these transcripts.
items <= 50The answer and its numbered sources.
application/json- response
answer*stringsources*array<>curl -X POST 'https://ai.codai.ro/v1/transcripts/ask' \ -H 'Content-Type: application/json' \ -d '{ "question": "string"}'{ "answer": "string", "sources": [ { "n": 1, "transcript_id": "215670dc-b708-4c27-9393-0b9ca7d8935d", "title": "string", "start_ms": 0, "end_ms": 0, "text": "string" } ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128The transcript detail.
application/json- response
id*stringuuidclient_id*stringtitle*stringstatus*TranscriptStatusLifecycle: recording → uploading → queued → transcribing → analyzing → ready, or failed.
"recording""uploading""queued""transcribing""analyzing""ready""failed"source*string"desktop""phone""wear""web""vscode""tv""api"template*TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint*stringauto, ro, en or another BCP-47 tag passed to the recognizer.
language*|Detected language, once transcribed.
folder_id*|uuidpinned*booleantags*array<string>feed_memory*booleanOpt-in for extracted facts to feed codai memory.
started_at*stringdate-timeduration_ms*integer0 <= valueerror*string|nullaudio_available*booleanfalse once the 30-day retention deleted the audio.
ready_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timelive_preview*|On-device live text, kept as a fallback until the final transcript lands.
processing*|The pending background job, or null when none is pending. While a job retries, status stays transcribing / analyzing; last_error and next_attempt_at say why and when it runs again. After max_attempts the transcript becomes failed.
tracks*array<>speakers*array<>utterances*array<>bookmarks*array<>insights*|nullcurl -X GET 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "live_preview": "string", "processing": { "kind": "transcribe", "attempts": 0, "max_attempts": 1, "last_error": "string", "next_attempt_at": "2019-08-24T14:15:22Z" }, "tracks": [ { "kind": "mic", "bytes": 0 } ], "speakers": [ { "label": "string", "name": "string", "is_owner": true, "talk_ms": 0 } ], "utterances": [ { "seq": 0, "speaker": "string", "start_ms": 0, "end_ms": 0, "text": "string", "language": "string", "words": [ { "w": "string", "s": 0, "e": 0, "c": 0 } ], "edited": true } ], "bookmarks": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "at_ms": 0, "label": "string" } ], "insights": { "version": 0, "model": "string", "created_at": "2019-08-24T14:15:22Z", "accepted_prompts": { "property1": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "property2": "497f6eca-6276-4993-bfeb-53cbbbba6f08" }, "title": "string", "summary": "string", "template": "auto", "language": "string", "keyPoints": [ { "text": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "actions": [ { "text": "string", "owner": "string", "due": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "decisions": [ { "text": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "openQuestions": [ { "text": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "tags": [ "string" ], "project": "string", "prompts": [ { "title": "string", "prompt": "string", "repo": "string", "cite": { "startMs": 0, "endMs": 0 } } ] }}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
1 <= propertiestitle?string1 <= length <= 200folder_id?|uuidpinned?booleantags?array<>items <= 30template?TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"feed_memory?booleanThe updated transcript.
application/json- response
id*stringuuidclient_id*stringtitle*stringstatus*TranscriptStatusLifecycle: recording → uploading → queued → transcribing → analyzing → ready, or failed.
"recording""uploading""queued""transcribing""analyzing""ready""failed"source*string"desktop""phone""wear""web""vscode""tv""api"template*TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint*stringauto, ro, en or another BCP-47 tag passed to the recognizer.
language*|Detected language, once transcribed.
folder_id*|uuidpinned*booleantags*array<string>feed_memory*booleanOpt-in for extracted facts to feed codai memory.
started_at*stringdate-timeduration_ms*integer0 <= valueerror*string|nullaudio_available*booleanfalse once the 30-day retention deleted the audio.
ready_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X PATCH 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Deleted.
curl -X DELETE 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08'bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
duration_ms*integer1 <= value <= 10860000uploads*array<>1 <= items <= 2bookmarks?array<>items <= 500live_preview?stringlength <= 400000Already finalized; the transcript as it is.
application/json- response
id*stringuuidclient_id*stringtitle*stringstatus*TranscriptStatusLifecycle: recording → uploading → queued → transcribing → analyzing → ready, or failed.
"recording""uploading""queued""transcribing""analyzing""ready""failed"source*string"desktop""phone""wear""web""vscode""tv""api"template*TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint*stringauto, ro, en or another BCP-47 tag passed to the recognizer.
language*|Detected language, once transcribed.
folder_id*|uuidpinned*booleantags*array<string>feed_memory*booleanOpt-in for extracted facts to feed codai memory.
started_at*stringdate-timeduration_ms*integer0 <= valueerror*string|nullaudio_available*booleanfalse once the 30-day retention deleted the audio.
ready_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/finalize' \ -H 'Content-Type: application/json' \ -d '{ "duration_ms": 1, "uploads": [ { "track": "mic", "upload_id": "stringst" } ]}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Queued for transcription.
application/json- response
id*stringuuidclient_id*stringtitle*stringstatus*TranscriptStatusLifecycle: recording → uploading → queued → transcribing → analyzing → ready, or failed.
"recording""uploading""queued""transcribing""analyzing""ready""failed"source*string"desktop""phone""wear""web""vscode""tv""api"template*TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint*stringauto, ro, en or another BCP-47 tag passed to the recognizer.
language*|Detected language, once transcribed.
folder_id*|uuidpinned*booleantags*array<string>feed_memory*booleanOpt-in for extracted facts to feed codai memory.
started_at*stringdate-timeduration_ms*integer0 <= valueerror*string|nullaudio_available*booleanfalse once the 30-day retention deleted the audio.
ready_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/retranscribe'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Queued for analysis.
application/json- response
id*stringuuidclient_id*stringtitle*stringstatus*TranscriptStatusLifecycle: recording → uploading → queued → transcribing → analyzing → ready, or failed.
"recording""uploading""queued""transcribing""analyzing""ready""failed"source*string"desktop""phone""wear""web""vscode""tv""api"template*TranscriptTemplateShapes the insights; auto lets the model choose.
"auto""meeting""brainstorm""journal""interview""lecture"language_hint*stringauto, ro, en or another BCP-47 tag passed to the recognizer.
language*|Detected language, once transcribed.
folder_id*|uuidpinned*booleantags*array<string>feed_memory*booleanOpt-in for extracted facts to feed codai memory.
started_at*stringdate-timeduration_ms*integer0 <= valueerror*string|nullaudio_available*booleanfalse once the 30-day retention deleted the audio.
ready_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/reanalyze'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
finals?stringlength <= 4000partial?stringlength <= 1000level?number0 <= value <= 1device*string"phone""wear""desktop"elapsed_ms*integer0 <= valuepaused?booleanAccepted (or dropped by the rate limit).
curl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/live' \ -H 'Content-Type: application/json' \ -d '{ "device": "phone", "elapsed_ms": 0}'bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
at_ms*integer0 <= value <= 10860000label?stringlength <= 120The bookmark.
application/json- response
id*stringuuidat_ms*integer0 <= valuelabel*string|nullcurl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/bookmarks' \ -H 'Content-Type: application/json' \ -d '{ "at_ms": 0}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "at_ms": 0, "label": "string"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidlabel*stringDiarization label of the speaker (for example A).
length <= 40x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
name*string1 <= length <= 80is_owner?booleanThe renamed speaker.
application/json- response
label*stringname*stringis_owner*booleancurl -X PATCH 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/speakers/string' \ -H 'Content-Type: application/json' \ -d '{ "name": "string"}'{ "label": "string", "name": "string", "is_owner": true}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidseq*integerPosition of the utterance in the transcript (0-based).
0 <= valuex-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
text*string1 <= length <= 20000The corrected utterance.
application/json- response
seq*integertext*stringedited*booleancurl -X PATCH 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/utterances/0' \ -H 'Content-Type: application/json' \ -d '{ "text": "string"}'{ "seq": 0, "text": "string", "edited": true}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Signed URLs (cache-control: private, no-store).
application/json- response
tracks*array<>expires_in?integerSeconds the URLs stay valid; absent when tracks is empty.
curl -X GET 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/audio'{ "tracks": [ { "kind": "mic", "mime": "string", "url": "http://example.com" } ], "expires_in": 0}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidformat?stringFile format.
"md""md""txt""srt""vtt""json""pdf""docx"x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128The exported file (UTF-8 text, or binary for pdf / docx).
response?stringcurl -X GET 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/export'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "client_id": "string", "title": "string", "status": "recording", "source": "desktop", "template": "auto", "language_hint": "string", "language": "string", "folder_id": "7695bac3-9397-4ec2-9335-45a2a16f1901", "pinned": true, "tags": [ "string" ], "feed_memory": true, "started_at": "2019-08-24T14:15:22Z", "duration_ms": 0, "error": "string", "audio_available": true, "ready_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z", "live_preview": "string", "processing": { "kind": "transcribe", "attempts": 0, "max_attempts": 1, "last_error": "string", "next_attempt_at": "2019-08-24T14:15:22Z" }, "tracks": [ { "kind": "mic", "bytes": 0 } ], "speakers": [ { "label": "string", "name": "string", "is_owner": true, "talk_ms": 0 } ], "utterances": [ { "seq": 0, "speaker": "string", "start_ms": 0, "end_ms": 0, "text": "string", "language": "string", "words": [ { "w": "string", "s": 0, "e": 0, "c": 0 } ], "edited": true } ], "bookmarks": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "at_ms": 0, "label": "string" } ], "insights": { "version": 0, "model": "string", "created_at": "2019-08-24T14:15:22Z", "accepted_prompts": { "property1": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "property2": "497f6eca-6276-4993-bfeb-53cbbbba6f08" }, "title": "string", "summary": "string", "template": "auto", "language": "string", "keyPoints": [ { "text": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "actions": [ { "text": "string", "owner": "string", "due": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "decisions": [ { "text": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "openQuestions": [ { "text": "string", "cite": { "startMs": 0, "endMs": 0 } } ], "tags": [ "string" ], "project": "string", "prompts": [ { "title": "string", "prompt": "string", "repo": "string", "cite": { "startMs": 0, "endMs": 0 } } ] }}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidindex*integerIndex into insights.prompts (0–20).
0 <= value <= 20x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Already accepted; the existing prompt.
application/json- response
prompt_id*stringuuidcreated*booleancurl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/prompts/0/accept'{ "prompt_id": "24783230-27c2-455c-9de9-95bbdbb78c3d", "created": true}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
expiresInDays?integerLink lifetime in days; omit for a link that never expires.
1 <= value <= 365Link created; keep the token/url, it is not recoverable.
application/json- response
id*stringuuidtoken*string32 random bytes, base64url. Shown only in this response.
url*stringPublic read-only page, https://hub.codai.ro/t/<token>.
uriexpiresAt*|date-timecurl -X POST 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/shares' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "token": "string", "url": "http://example.com", "expiresAt": "2019-08-24T14:15:22Z"}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128The active links.
application/json- response
data*array<>curl -X GET 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/shares'{ "data": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "url": null, "createdAt": "2019-08-24T14:15:22Z", "expiresAt": "2019-08-24T14:15:22Z" } ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringTranscript id (uuid). A foreign or malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Revoked.
curl -X DELETE 'https://ai.codai.ro/v1/transcripts/497f6eca-6276-4993-bfeb-53cbbbba6f08/shares/497f6eca-6276-4993-bfeb-53cbbbba6f08'token*stringThe share token (43 base64url characters).
^[A-Za-z0-9_-]{43}$The shared transcript.
application/json- response
title*stringcreatedAt*stringdate-timedurationMs*integer0 <= valuespeakers*array<>utterances*array<>insights*null|curl -X GET 'https://ai.codai.ro/v1/public/transcripts/string'{ "title": "string", "createdAt": "2019-08-24T14:15:22Z", "durationMs": 0, "speakers": [ { "label": "string", "name": "string" } ], "utterances": [ { "speaker": "string", "startMs": 0, "endMs": 0, "text": "string" } ], "insights": null}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128The folders.
application/json- response
folders*array<>curl -X GET 'https://ai.codai.ro/v1/transcript-folders'{ "folders": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", "color": "string", "position": 0 } ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
name*string1 <= length <= 80color?string^[a-z]{3,16}$The folder.
application/json- response
id*stringuuidname*stringcolor*string|nullposition*integercurl -X POST 'https://ai.codai.ro/v1/transcript-folders' \ -H 'Content-Type: application/json' \ -d '{ "name": "string"}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", "color": "string", "position": 0}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringFolder id (uuid). A malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
name?string1 <= length <= 80color?string^[a-z]{3,16}$position?integer0 <= value <= 10000The updated folder.
application/json- response
id*stringuuidname*stringcolor*string|nullposition*integercurl -X PATCH 'https://ai.codai.ro/v1/transcript-folders/497f6eca-6276-4993-bfeb-53cbbbba6f08' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", "color": "string", "position": 0}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringFolder id (uuid). A malformed id is 404.
uuidx-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Deleted.
curl -X DELETE 'https://ai.codai.ro/v1/transcript-folders/497f6eca-6276-4993-bfeb-53cbbbba6f08'bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128Your terms.
application/json- response
terms*array<>items <= 1000curl -X GET 'https://ai.codai.ro/v1/transcript-vocabulary'{ "terms": [ "string" ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
x-request-id?stringClient correlation id; echoed back as x-codai-trace-id and persisted on the usage row.
length <= 128application/json- body
terms*array<>items <= 1000The stored terms.
application/json- response
terms*array<>items <= 1000curl -X PUT 'https://ai.codai.ro/v1/transcript-vocabulary' \ -H 'Content-Type: application/json' \ -d '{ "terms": [ "string" ]}'{ "terms": [ "string" ]}bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
tus-resumable*"1.0.0"Protocol version.
"1.0.0"upload-length?integerTotal size in bytes, when known.
0 <= value <= 209715200upload-defer-length?11 when the size is not known yet.
1upload-metadata?stringComma-separated key base64value pairs (transcript, track, durationMs; or purpose=list with mime).
Upload created.
curl -X POST 'https://ai.codai.ro/v1/uploads' \ -H 'tus-resumable: 1.0.0'Capabilities in the response headers.
curl -X OPTIONS 'https://ai.codai.ro/v1/uploads'bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringtus upload id from Location (bound to your account). A foreign or malformed id is 404.
tus-resumable*"1.0.0"Protocol version.
"1.0.0"Current offset (cache-control: no-store), no body.
curl -X GET 'https://ai.codai.ro/v1/uploads/string' \ -H 'tus-resumable: 1.0.0'bearerAuthAuthorizationBearer <codai_…>A codai API key (codai_ prefix). Ephemeral tokens from POST /v1/tokens are accepted only by the media surfaces matching their scope (/v1/realtime, /v1/audio/*, /v1/embeddings).
id*stringtus upload id from Location (bound to your account). A foreign or malformed id is 404.
tus-resumable*"1.0.0"Protocol version.
"1.0.0"upload-offset*integerOffset this chunk starts at.
0 <= valuebody*fileapplication/offset+octet-streambinarylength <= 8388608Chunk stored.
curl -X PATCH 'https://ai.codai.ro/v1/uploads/string' \ -H 'tus-resumable: 1.0.0' \ -H 'upload-offset: 0' \ -H 'Content-Type: application/offset+octet-stream' \ -d 'string'Scheduler
Scheduled agent tasks, terminal commands, webhooks and chains that run on any of your PCs, phones, watch or cloud VMs — cron or plain words, approvals, retries, failover and live run status.
Usage & keys
Your own usage split by day, key, device, app, platform, model, client or tag, and your API keys with device attribution and tags.