Voices
GET/v1/voices
List voices: consented clones of the organization, your own clones and your chosen generic voices
Response 200
| Name | Type | Description |
|---|---|---|
data required | object[] | |
data[].id required | string | |
data[].name required | string | |
data[].kind required | "clone" | "generic" | |
data[].active required | boolean | |
data[].gender required | "male" | "female" | null | |
data[].status | "awaiting_consent" | "processing" | "ready" | "failed" | "revoked" | "expired" | Voices created through the API (consent flow). ready = usable in say. |
data[].consent_url | string | null | Send this link to the person whose voice it is. They sign in with the email of the request, read the consent sentence and record live. Shown while awaiting consent. |
data[].language | string | |
data[].person | object | |
data[].person.name required | string | |
data[].person.email required | string | Masked |
data[].failure_code | string | null | |
data[].expires_at | string | null | |
data[].created_at | string | |
data[].livemode | boolean |
Example
curl "https://api.kanutus.com/v1/voices" \
-H "Authorization: Bearer $KANUTUS_API_KEY"const res = await fetch("https://api.kanutus.com/v1/voices", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.KANUTUS_API_KEY}`,
},
});
console.log(res.status, await res.json());import os, uuid, requests
r = requests.request(
"GET",
"https://api.kanutus.com/v1/voices",
headers={"Authorization": f"Bearer {os.environ['KANUTUS_API_KEY']}"},
)
print(r.status_code, r.json())Try it
Runs from your browser against the real API. Use a kt_test_ key: nothing is charged. The key stays in this tab only.
GET /v1/voicesResponses by status
200 Voices
{
"data": [
{
"id": "string",
"name": "string",
"kind": "clone",
"active": true,
"gender": "male",
"status": "awaiting_consent",
"consent_url": "https://example.com",
"language": "string",
"person": {
"name": "string",
"email": "string"
},
"failure_code": "string",
"expires_at": "string",
"created_at": "string",
"livemode": true
}
]
}400 Invalid request
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 400,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}401 Missing, invalid, expired or revoked credential
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 401,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}403 Missing permission, blocked or not allowed
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 403,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}429 Rate limit exceeded (see RateLimit-* and Retry-After headers)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 429,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}POST/v1/voices
Clone a voice with verifiable consent: returns a link the person opens to read the consent sentence and record live Soon
Live mode answers 501 coming soon. Try it now with a kt_test_ key (simulator).
Parameters
| Name | Type | Description |
|---|---|---|
idempotency-key required | header · string | Unique key per create request; retries with the same key return the same result. |
Request body
| Name | Type | Description |
|---|---|---|
name required | string | length 1–60 |
language required | string | Language the person will read in (consent sentence: pt, en or es; others read in English). |
person required | object | |
person.name required | string | length 1–80 |
person.email required | string | The person signs in with this email to give consent and record. · length 0–254 |
Response 202
| Name | Type | Description |
|---|---|---|
id required | string | |
name required | string | |
kind required | "clone" | "generic" | |
active required | boolean | |
gender required | "male" | "female" | null | |
status | "awaiting_consent" | "processing" | "ready" | "failed" | "revoked" | "expired" | Voices created through the API (consent flow). ready = usable in say. |
consent_url | string | null | Send this link to the person whose voice it is. They sign in with the email of the request, read the consent sentence and record live. Shown while awaiting consent. |
language | string | |
person | object | |
person.name required | string | |
person.email required | string | Masked |
failure_code | string | null | |
expires_at | string | null | |
created_at | string | |
livemode | boolean |
Example
curl -X POST "https://api.kanutus.com/v1/voices" \
-H "Authorization: Bearer $KANUTUS_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"name":"Ana (atendimento)","language":"pt","person":{"name":"Ana Ribeiro","email":"ana@vertice.com"}}'const res = await fetch("https://api.kanutus.com/v1/voices", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KANUTUS_API_KEY}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json",
},
body: JSON.stringify({"name":"Ana (atendimento)","language":"pt","person":{"name":"Ana Ribeiro","email":"ana@vertice.com"}}),
});
console.log(res.status, await res.json());import os, uuid, requests
r = requests.request(
"POST",
"https://api.kanutus.com/v1/voices",
headers={"Authorization": f"Bearer {os.environ['KANUTUS_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
json={"name":"Ana (atendimento)","language":"pt","person":{"name":"Ana Ribeiro","email":"ana@vertice.com"}},
)
print(r.status_code, r.json())Try it
Runs from your browser against the real API. Use a kt_test_ key: nothing is charged. The key stays in this tab only.
POST /v1/voicesResponses by status
202 Waiting for the person's consent (status awaiting_consent)
{
"id": "string",
"name": "string",
"kind": "clone",
"active": true,
"gender": "male",
"status": "awaiting_consent",
"consent_url": "https://example.com",
"language": "string",
"person": {
"name": "string",
"email": "string"
},
"failure_code": "string",
"expires_at": "string",
"created_at": "string",
"livemode": true
}400 Invalid request
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 400,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}401 Missing, invalid, expired or revoked credential
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 401,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}403 Missing permission, blocked or not allowed
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 403,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}409 Conflict (idempotency or state)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 409,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}429 Rate limit exceeded (see RateLimit-* and Retry-After headers)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 429,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}501 Not available yet in live mode (use a kt_test_ key)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 501,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}GET/v1/voices/catalog
Generic voices you can choose (no consent needed)
Response 200
| Name | Type | Description |
|---|---|---|
data required | object[] | |
data[].id required | string | |
data[].name required | string | |
data[].gender required | "male" | "female" | |
data[].accent required | string | null | |
data[].description required | string | null | |
data[].preview_url required | string | null |
Example
curl "https://api.kanutus.com/v1/voices/catalog" \
-H "Authorization: Bearer $KANUTUS_API_KEY"const res = await fetch("https://api.kanutus.com/v1/voices/catalog", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.KANUTUS_API_KEY}`,
},
});
console.log(res.status, await res.json());import os, uuid, requests
r = requests.request(
"GET",
"https://api.kanutus.com/v1/voices/catalog",
headers={"Authorization": f"Bearer {os.environ['KANUTUS_API_KEY']}"},
)
print(r.status_code, r.json())Try it
Runs from your browser against the real API. Use a kt_test_ key: nothing is charged. The key stays in this tab only.
GET /v1/voices/catalogResponses by status
200 Catalog
{
"data": [
{
"id": "string",
"name": "string",
"gender": "male",
"accent": "string",
"description": "string",
"preview_url": "string"
}
]
}400 Invalid request
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 400,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}401 Missing, invalid, expired or revoked credential
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 401,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}403 Missing permission, blocked or not allowed
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 403,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}429 Rate limit exceeded (see RateLimit-* and Retry-After headers)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 429,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}POST/v1/voices/generic
Choose a generic voice from the catalog (adds it to your voices)
Request body
| Name | Type | Description |
|---|---|---|
voice_id required | string |
Response 200
| Name | Type | Description |
|---|---|---|
id required | string | |
name required | string | |
kind required | "clone" | "generic" | |
active required | boolean | |
gender required | "male" | "female" | null | |
status | "awaiting_consent" | "processing" | "ready" | "failed" | "revoked" | "expired" | Voices created through the API (consent flow). ready = usable in say. |
consent_url | string | null | Send this link to the person whose voice it is. They sign in with the email of the request, read the consent sentence and record live. Shown while awaiting consent. |
language | string | |
person | object | |
person.name required | string | |
person.email required | string | Masked |
failure_code | string | null | |
expires_at | string | null | |
created_at | string | |
livemode | boolean |
Example
curl -X POST "https://api.kanutus.com/v1/voices/generic" \
-H "Authorization: Bearer $KANUTUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"voice_id":"generic_EXAVITQu4vr4xnSDxMaL"}'const res = await fetch("https://api.kanutus.com/v1/voices/generic", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KANUTUS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"voice_id":"generic_EXAVITQu4vr4xnSDxMaL"}),
});
console.log(res.status, await res.json());import os, uuid, requests
r = requests.request(
"POST",
"https://api.kanutus.com/v1/voices/generic",
headers={"Authorization": f"Bearer {os.environ['KANUTUS_API_KEY']}"},
json={"voice_id":"generic_EXAVITQu4vr4xnSDxMaL"},
)
print(r.status_code, r.json())Try it
Runs from your browser against the real API. Use a kt_test_ key: nothing is charged. The key stays in this tab only.
POST /v1/voices/genericResponses by status
200 Chosen
{
"id": "string",
"name": "string",
"kind": "clone",
"active": true,
"gender": "male",
"status": "awaiting_consent",
"consent_url": "https://example.com",
"language": "string",
"person": {
"name": "string",
"email": "string"
},
"failure_code": "string",
"expires_at": "string",
"created_at": "string",
"livemode": true
}400 Invalid request
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 400,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}401 Missing, invalid, expired or revoked credential
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 401,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}403 Missing permission, blocked or not allowed
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 403,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}409 Conflict (idempotency or state)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 409,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}429 Rate limit exceeded (see RateLimit-* and Retry-After headers)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 429,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}GET/v1/voices/{id}
Get a voice (and its consent status)
Parameters
| Name | Type | Description |
|---|---|---|
id required | path · string |
Response 200
| Name | Type | Description |
|---|---|---|
id required | string | |
name required | string | |
kind required | "clone" | "generic" | |
active required | boolean | |
gender required | "male" | "female" | null | |
status | "awaiting_consent" | "processing" | "ready" | "failed" | "revoked" | "expired" | Voices created through the API (consent flow). ready = usable in say. |
consent_url | string | null | Send this link to the person whose voice it is. They sign in with the email of the request, read the consent sentence and record live. Shown while awaiting consent. |
language | string | |
person | object | |
person.name required | string | |
person.email required | string | Masked |
failure_code | string | null | |
expires_at | string | null | |
created_at | string | |
livemode | boolean |
Example
curl "https://api.kanutus.com/v1/voices/kqz-mbdt-wpa" \
-H "Authorization: Bearer $KANUTUS_API_KEY"const res = await fetch("https://api.kanutus.com/v1/voices/kqz-mbdt-wpa", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.KANUTUS_API_KEY}`,
},
});
console.log(res.status, await res.json());import os, uuid, requests
r = requests.request(
"GET",
"https://api.kanutus.com/v1/voices/kqz-mbdt-wpa",
headers={"Authorization": f"Bearer {os.environ['KANUTUS_API_KEY']}"},
)
print(r.status_code, r.json())Try it
Runs from your browser against the real API. Use a kt_test_ key: nothing is charged. The key stays in this tab only.
GET /v1/voices/{id}Responses by status
200 Voice
{
"id": "string",
"name": "string",
"kind": "clone",
"active": true,
"gender": "male",
"status": "awaiting_consent",
"consent_url": "https://example.com",
"language": "string",
"person": {
"name": "string",
"email": "string"
},
"failure_code": "string",
"expires_at": "string",
"created_at": "string",
"livemode": true
}400 Invalid request
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 400,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}401 Missing, invalid, expired or revoked credential
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 401,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}403 Missing permission, blocked or not allowed
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 403,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}404 Not found
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 404,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}429 Rate limit exceeded (see RateLimit-* and Retry-After headers)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 429,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}DELETE/v1/voices/{id}
Delete a voice: revokes a consented clone or removes a chosen generic voice
Parameters
| Name | Type | Description |
|---|---|---|
id required | path · string |
Response 200
| Name | Type | Description |
|---|---|---|
id required | string | |
deleted required | true |
Example
curl -X DELETE "https://api.kanutus.com/v1/voices/kqz-mbdt-wpa" \
-H "Authorization: Bearer $KANUTUS_API_KEY"const res = await fetch("https://api.kanutus.com/v1/voices/kqz-mbdt-wpa", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.KANUTUS_API_KEY}`,
},
});
console.log(res.status, await res.json());import os, uuid, requests
r = requests.request(
"DELETE",
"https://api.kanutus.com/v1/voices/kqz-mbdt-wpa",
headers={"Authorization": f"Bearer {os.environ['KANUTUS_API_KEY']}"},
)
print(r.status_code, r.json())Try it
Runs from your browser against the real API. Use a kt_test_ key: nothing is charged. The key stays in this tab only.
DELETE /v1/voices/{id}Responses by status
200 Deleted
{
"id": "string",
"deleted": true
}400 Invalid request
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 400,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}401 Missing, invalid, expired or revoked credential
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 401,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}403 Missing permission, blocked or not allowed
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 403,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}404 Not found
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 404,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}429 Rate limit exceeded (see RateLimit-* and Retry-After headers)
{
"type": "https://docs.kanutus.com/errors",
"title": "<code>",
"status": 429,
"code": "<code>",
"message": "…",
"request_id": "req_…"
}