All Documentation

API Keys & Scopes

Granular API keys with per-resource read/write permissions, modeled on Cloudflare API tokens

Overview

Every API key carries a set of scopes — permissions of the form resource:permission — and can only do what its scopes allow. A key for a soundboard app might get lines:read and sfx:read only; a build pipeline that generates dialogue might add tts:generate and lines:write. Grant only what each integration needs.

Keys authenticate the v1 REST API, the MCP server, and the Public TTS API.

Scope Catalog

write always includes read for the same resource.

ScopeGrants
organization:readRead the organization and its art direction for 3D models
organization:writeEdit the organization-wide art direction for 3D models
projects:readList projects
projects:writeCreate, edit, and delete projects
characters:readList and read characters
characters:writeCreate, edit, and delete characters
internal_voices:readList and read Voice Studio custom voices
internal_voices:writeManage Voice Studio custom voices
lines:readList, read, and download saved lines
lines:writeSave lines, add versions, set active version, delete
sfx:readList, read, and download saved sound effects
sfx:writeGenerate and save sound effects, add versions, delete
music:readList, read, and download saved music
music:writeGenerate and save music, add versions, delete (spends credits)
models:readList, read, and download saved 3D models; read generation jobs and the model catalog
models:writeGenerate, refine, and delete 3D models; cancel generation jobs (spends credits)
canvas:readList, read, and download Canvas images (menu, HUD and in-game art); read the image catalog
canvas:writeGenerate, edit, and delete Canvas images (spends credits)
live_endpoints:readList and read live endpoints, and fetch their cached audio through the Public TTS API (never generates)
live_endpoints:writeCreate, edit, and delete live endpoints
tts:generateGenerate speech with Voice Studio voices (spends credits)

Creating and Managing Keys

  1. 1Go to API Keys and choose New API Key.
  2. 2Name the key after the integration that will hold it ("Game build pipeline", "Support bot").
  3. 3Tick the permissions it needs — one row per resource with Read/Write checkboxes. At least one is required.
  4. 4Copy the key and store it in your secret manager. Treat it like a password.

Existing keys can be disabled (temporarily blocks all use), have their permissions edited at any time (takes effect immediately), or be deleted permanently.

Legacy keys

Keys created before scopes existed behave as if they had only tts:generate — exactly what they could do before. Edit their permissions to grant more.

Using a Key

Send the key with every request, preferably in the Authorization header:

# Preferred
curl -H "Authorization: Bearer $API_KEY" https://<host>/api/v1/verify

# Also accepted
curl -H "X-API-Key: $API_KEY" https://<host>/api/v1/verify

Verifying a key

GET /api/v1/verify works with any valid key (no scope required) and returns its name, organization, and scopes — useful in health checks and for debugging permission issues:

{
  "success": true,
  "result": {
    "keyId": "…",
    "name": "Game build pipeline",
    "organizationId": "…",
    "scopes": ["tts:generate", "lines:write", "lines:read"],
    "status": "active"
  }
}

Errors and Limits

StatusMeaning
401Missing, invalid, or disabled API key
403The key works but is missing the required scope (the error names it)
402Insufficient credit balance for a generation
429Rate limited — 60 requests/minute per key (Retry-After header included)

All v1 errors use the response envelope:

{ "success": false, "errors": [{ "code": "missing_scope", "message": "API key is missing the required scope: lines:write" }] }

Best Practices

Recommendations

  • • One key per integration — never share keys between apps.
  • • Grant the minimum scopes; prefer read-only keys wherever possible.
  • • models:write is the most expensive permission — one job reserves up to a few hundred credits — so give it only to the integrations that actually generate 3D models; a build pipeline that just downloads finished models needs models:read.
  • • Anything you ship to players that talks to Tonetta at runtime (a game fetching live endpoints, a mobile app) gets its own read-only key — live_endpoints:read, plus lines:read / sfx:read only if it downloads saved content — so a leaked key can fetch existing audio but never create, delete, or spend credits. Keep the full-scope key for development; a build that only plays imported audio needs no key at all. The Unreal plugin has a slot for each.
  • • Rotate by creating a new key, migrating, then deleting the old one.
  • • Disable (rather than delete) a key to investigate suspicious usage.
  • • Watch credit spend in the Credits dashboard — generation calls are attributed in the audit log.