Browse the docs
Developers / Docs / AI tools
Transcribe audio or video
Transcribes an audio or video file (up to 30 minutes) into punctuated text, word timings, and SRT and WebVTT captions split at sentence ends. Spends caption minutes for the file's length. Finishes within the call: the job comes back completed with captions.words, captions.srt and captions.vtt.
Paste it into any AI assistant. The shortcuts open with the prompt typed in; nothing is sent until you press enter.
At a glance
- REST
POST https://api.clippie.ai/v1/ai/transcribe
- MCP tool
transcribe
- Scope
create
- Cost
- Spends credits or minutes, at the same prices as the app. Send
"dryRun": true(or call estimate_cost) first to see the exact cost without spending anything.
- Spends credits or minutes, at the same prices as the app. Send
- Limit bucket
transcribe(see Rate limits)
Parameters
fileId- In:
- body
- Type:
- string
- Required:
- No
- Description:
- An audio or video file id from POST /v1/files. 1-80 chars.
url- In:
- body
- Type:
- string
- Required:
- No
- Description:
- The audio or video to transcribe: a file id from POST /v1/files (file_…) or a public https URL (copied into Clippie first, up to 100 MB). 1-2048 chars.
language- In:
- body
- Type:
- string
- Required:
- No
- Description:
- Language code, e.g. "en". Detected when left out. 2-10 chars.
dryRun- In:
- body
- Type:
- boolean
- Required:
- No
- Description:
- Check the request and return { estimate } (credits and minutes) without spending anything.
webhookUrl- In:
- body
- Type:
- string (URL)
- Required:
- No
- Description:
- https URL that receives job.completed / job.failed, signed with your webhook secret. Up to 2048 chars.
Idempotency-Key- In:
- header
- Type:
- string
- Required:
- No
- Description:
- Retry-safe key: a retry with the same key and body within 24 hours returns the first job instead of starting (and charging) again. The same key with a different body is a 409. MCP clients pass it as the idempotencyKey argument. 1-255 chars. MCP:
idempotencyKey.
Example
# 1. Dry run: the exact cost, nothing is spent.
curl https://api.clippie.ai/v1/ai/transcribe \
-H "Authorization: Bearer $CLIPPIE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/clip.mp4",
"language": "en",
"dryRun": true
}'
# => { "dryRun": true, "estimate": { "credits": ..., "minutes": { ... }, "wouldSucceed": true } }
# 2. The real call. Keep the key and send the same one if you retry, so it is never charged twice.
KEY=$(uuidgen)
curl https://api.clippie.ai/v1/ai/transcribe \
-H "Authorization: Bearer $CLIPPIE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $KEY" \
-d '{
"url": "https://example.com/clip.mp4",
"language": "en"
}'
# => 202 { "job": { "id": "job_...", "status": "queued", ... } }import { randomUUID } from 'node:crypto';
const auth = { Authorization: `Bearer ${process.env.CLIPPIE_API_KEY}` };
const input = {
"url": "https://example.com/clip.mp4",
"language": "en"
};
async function call(body, headers = {}) {
const res = await fetch('https://api.clippie.ai/v1/ai/transcribe', {
method: 'POST',
headers: { ...auth, 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(body),
});
const json = await res.json();
if (!res.ok) throw new Error(`${json.error.type}: ${json.error.message}`);
return json;
}
// 1. Dry run: the exact cost, nothing is spent. Confirm it before going on.
const { estimate } = await call({ ...input, dryRun: true });
console.log(estimate); // { credits, minutes, wouldSucceed, reason }
// 2. Create. Keep the key and reuse it on retries, so a retry never charges twice.
let { job } = await call(input, { 'Idempotency-Key': randomUUID() });
// 3. Wait. Each call holds for up to 30 seconds until the job changes.
while (!['completed', 'failed', 'canceled'].includes(job.status)) {
const res = await fetch(`https://api.clippie.ai/v1/jobs/${job.id}?wait=30`, { headers: auth });
({ job } = await res.json());
}
console.log(job.status, job.output);Response
202 { job }: the job, straight away. Wait for it with Get job (?wait=30) or a webhookUrl; see Jobs and waiting. With "dryRun": true the answer is 200 { dryRun: true, estimate } and nothing is started.
{
"job": {
"id": "job_abc123",
"object": "job",
"kind": "transcribe",
"status": "queued",
"step": null,
"progress": null,
"input": {
"prompt": "The lost library of Alexandria"
},
"output": null,
"cost": {
"credits": 0,
"minutes": {
"voiceover": 1,
"captions": 1,
"export": 1
}
},
"error": null,
"source": "api",
"webhookUrl": null,
"createdAt": "2026-10-24T12:00:00.000Z",
"startedAt": null,
"completedAt": null
}
}{
"dryRun": true,
"estimate": {
"credits": 0,
"minutes": {
"voiceover": 0,
"captions": 0,
"export": 0
},
"wouldSucceed": true
}
}From an MCP client
Your AI calls transcribe with the same fields as JSON arguments, plus idempotencyKey instead of the header. See MCP server to connect one.
{
"name": "transcribe",
"arguments": {
"url": "https://example.com/clip.mp4",
"language": "en",
"idempotencyKey": "a-unique-key-per-thing-you-make"
}
}