API Reference · v2
Generate, save, and listen
Create speech in your existing Crikk library. Submit text, poll for a saved recording’s URL, and browse your projects and audio whenever you need them.
Authentication
Get your API key and numeric user ID from API Tokens. API and MCP generation share your account’s API character allowance.
POST /generate-audio/v2: include api_token and numeric user_id in the JSON body, with Content-Type: application/json.
GET status and library requests: include both headers below. The voice list is public and needs no authentication.
Authorization: Bearer YOUR_API_TOKEN
X-Crikk-User-Id: YOUR_NUMERIC_USER_IDMCP clients connect to /mcp using OAuth and your usual Crikk sign-in. The API-key headers above apply to direct API requests. See MCP setup for connection instructions.
Submit a speech job
POST https://crikk.com/generate-audio/v2
Returns HTTP 202 immediately. When generation finishes, the audio is automatically saved to your existing library and its characters are charged once, even if you never poll. Omit project_id or send home to save in Home. Choose another project using its ID from the library projects endpoint.
| Field | Type | Required | Description |
|---|---|---|---|
| api_token | string | Yes | Your existing Crikk API key. |
| user_id | number | Yes | Your positive integer user ID. Send a JSON number. |
| text | string | Yes | 1–12,000 spoken characters. Pause markers do not count toward usage. |
| voice_name | string | Yes | Exact name from /generate-audio/voice-list, for example en-US-AriaNeural. |
| project_id | string | No | Defaults to home. Use home or an ID returned by the projects endpoint. |
| speaking_style | string | No | A style from the selected voice’s styles array. Defaults to general. |
| speed | number | No | 0.5–2. Default 1 (normal speed). |
| pitch | number | No | Percentage change from −50 to 50. Default 0. |
{
"api_token": "YOUR_API_TOKEN",
"user_id": 42,
"text": "Hello, world! [1s] Welcome to Crikk.",
"voice_name": "en-US-AriaNeural",
"project_id": "home",
"speaking_style": "cheerful",
"speed": 1.1,
"pitch": 5
}{
"job_id": "api_v2_42_550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"characters": 32,
"project_id": "PROJECT_ID",
"settings": {
"speaking_style": "cheerful",
"speed": 1.1,
"pitch": 5
},
"message": "Audio will be saved to your library. Poll /generate-audio/v2/status/:job_id for the result using your API credentials."
}The response returns the resolved project ID, including when Home was selected. Treat the returned job_id as an opaque value and use it unchanged for polling.
Check status and get the audio URL
GET https://crikk.com/generate-audio/v2/status/:job_id
Send the API-key headers for the account that started the job. Pending jobs return HTTP 200 with job_id and status: "pending". Completed jobs return JSON with the saved recording below. Use audio_url for playback or downloading the file.
{
"job_id": "api_v2_42_550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"id": 123,
"project_id": "PROJECT_ID",
"title": "Hello, world! Welcome to Crikk.",
"text": "Hello, world! Welcome to Crikk.",
"voice": "en-US-AriaNeural",
"audio_url": "https://files.crikk.com/EXAMPLE.mp3",
"mime_type": "audio/mpeg"
}Checking a result again does not remove the recording or charge again. Polling records last ten minutes from submission and are kept in server memory, so a restart can also remove them. Saved audio follows normal library retention rules. If the job is unavailable, browse the library before submitting the same text again.
A failed job returns HTTP 500 with status: "failed" and an error. An unavailable or expired job returns HTTP 404.
Browse existing projects and audio
These endpoints read the same library used by the dashboard and mobile app. Both require the API-key headers. Listing projects or saved recordings does not use speech characters.
List projects
GET https://crikk.com/generate-audio/library/projects
No body or query parameters. Home is returned as project_id: "home". Use returned IDs rather than project names.
{
"projects": [
{
"project_id": "home",
"name": "Home"
},
{
"project_id": "PROJECT_ID_FROM_YOUR_ACCOUNT",
"name": "My voiceovers"
}
]
}List saved audio
GET https://crikk.com/generate-audio/library/audio?project_id=home&page=1
project_id: optional string; defaults tohome. Use an ID from the projects endpoint for another folder.page: optional integer from 1 to 1,000,000; defaults to 1. Returns up to 20 recordings per page, newest first.- Increment
pagewhilehas_next_pageis true. Deleted entries and entries without audio are excluded. - Each recording includes
id,title,audio_url,voice(which may be null), andcreated_at.
curl 'https://crikk.com/generate-audio/library/audio?project_id=home&page=1' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'X-Crikk-User-Id: YOUR_NUMERIC_USER_ID'{
"project_id": "home",
"files": [
{
"id": 123,
"title": "My saved recording",
"audio_url": "https://files.crikk.com/EXAMPLE.mp3",
"voice": "en-US-AriaNeural",
"created_at": "2026-11-01T08:00:00.000Z"
}
],
"page": 1,
"has_next_page": false
}Use the returned audio_url directly to listen or download; there is no separate download endpoint. These recordings use normal library retention rules, replacing the former one-hour temporary MCP download flow.
List available voices
GET https://crikk.com/generate-audio/voice-list
Public endpoint, cached for 24 hours. Returns count and a voices array. Each voice includes name, display_name, locale, locale_name, gender, and styles. Send its exact name as voice_name, and choose a speaking style from its styles array.
API and MCP support only the free voice catalog. Premium voices are unavailable through these integrations. An empty styles array means the voice supports general speech only.
curl https://crikk.com/generate-audio/voice-listShared generation rules
Audio: API and MCP voices use MP3 at 48 kHz, 192 kbps, mono.
Pauses: put [2s], [1.5s], [500ms], or an SSML break tag such as <break time="2s"/> in your text. Each pause is capped at 10 seconds. Pause markers are not spoken or billed.
Timeout: the shared Microsoft synthesis request timeout is 50 minutes. This is separate from the ten-minute polling record lifetime.
Output format, timeout, and maximum pause are managed by the server. Do not send outputFormat, timeout, or maxPauseMs in API requests or MCP tool arguments.
Error reference
HTTP errors return JSON with an error field. Check the HTTP status before using the result.
| Status | Meaning |
|---|---|
| 400 | Invalid JSON, required fields, text length, voice, voice controls, or query parameters. |
| 401 | Invalid API credentials. Check both the API key and user ID. |
| 404 | Project not found, or the job is unavailable or expired. Saved recordings remain in the library. |
| 429 | Monthly API character limit exceeded when submitting a job. |
| 500 | Generation, saving, or retrieval failed. A failed status response includes an error message. |
Quick start · JavaScript
Replace the API key and user ID with your own values. This example submits to v2, polls authenticated JSON status, and returns the saved audio URL. Keep API credentials in your own trusted application or server.
const API_TOKEN = 'YOUR_API_TOKEN';
const USER_ID = 42; // Replace with your numeric user ID
const BASE = 'https://crikk.com';
const headers = {
Authorization: 'Bearer ' + API_TOKEN,
'X-Crikk-User-Id': String(USER_ID)
};
async function readJson(response) {
const data = await response.json();
if (!response.ok) throw new Error(data.error || 'Request failed');
return data;
}
async function textToSpeech(text, voiceName, projectId = 'home') {
const job = await readJson(await fetch(BASE + '/generate-audio/v2', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_token: API_TOKEN, user_id: USER_ID,
text, voice_name: voiceName, project_id: projectId
})
}));
// Poll the same job. Do not submit the script again while pending.
const pollingDeadline = Date.now() + 10 * 60 * 1000;
while (Date.now() < pollingDeadline) {
await new Promise(resolve => setTimeout(resolve, 1500));
const result = await readJson(await fetch(
BASE + '/generate-audio/v2/status/' + encodeURIComponent(job.job_id),
{ headers }
));
if (result.status === 'completed') return result;
}
throw new Error('Polling window ended. Check your library for saved audio.');
}
const result = await textToSpeech('Hello from Crikk! [1s] Welcome.', 'en-US-AriaNeural');
console.log(result.id, result.project_id, result.audio_url);
// Use result.audio_url as an audio player source or open it to download.
// Find existing recordings later, without generating or using characters:
const library = await readJson(await fetch(
BASE + '/generate-audio/library/audio?project_id=home&page=1',
{ headers }
));
console.log(library.files, library.has_next_page);Legacy API
Existing integrations can still use POST /generate-audio and GET /generate-audio/status/:job_id. The original endpoint returns MP3 binary when ready, removes the job after retrieval, and does not save to the library. Its polling record lasts ten minutes. It uses a separate job ID from v2.
For saved recordings, switch submission to /generate-audio/v2, poll /generate-audio/v2/status/:job_id with API-key headers, and read JSON audio_url from completed responses. MCP already uses the saved-library generation flow.