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.

Authenticated GET request headers
Authorization: Bearer YOUR_API_TOKEN
X-Crikk-User-Id: YOUR_NUMERIC_USER_ID

MCP 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.

FieldTypeRequiredDescription
api_tokenstringYesYour existing Crikk API key.
user_idnumberYesYour positive integer user ID. Send a JSON number.
textstringYes1–12,000 spoken characters. Pause markers do not count toward usage.
voice_namestringYesExact name from /generate-audio/voice-list, for example en-US-AriaNeural.
project_idstringNoDefaults to home. Use home or an ID returned by the projects endpoint.
speaking_stylestringNoA style from the selected voice’s styles array. Defaults to general.
speednumberNo0.5–2. Default 1 (normal speed).
pitchnumberNoPercentage change from −50 to 50. Default 0.
JSON request body
{
  "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
}
202 · Accepted (illustrative IDs)
{
  "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.

200 · Completed (illustrative recording and URL)
{
  "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.

200 · Projects (illustrative)
{
  "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 to home. 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 page while has_next_page is true. Deleted entries and entries without audio are excluded.
  • Each recording includes id, title, audio_url, voice (which may be null), and created_at.
List Home audio with curl
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'
200 · Saved recordings (illustrative)
{
  "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.

List voices with curl
curl https://crikk.com/generate-audio/voice-list

Shared 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.

StatusMeaning
400Invalid JSON, required fields, text length, voice, voice controls, or query parameters.
401Invalid API credentials. Check both the API key and user ID.
404Project not found, or the job is unavailable or expired. Saved recordings remain in the library.
429Monthly API character limit exceeded when submitting a job.
500Generation, 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.

JavaScript · Generate and browse saved recordings
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.