Subir audio
Fichero o URL, formatos admitidos y los cinco parámetros que se aceptan y se ignoran.
Hay dos formas de darle audio a Callsist. Con fichero subido la estimación de coste es exacta porque se conoce el tamaño; con URL se asume una duración conservadora.
POST /v1/files
Scope: files:write. Content-Type: multipart/form-data con el campo file.
curl -X POST https://api.callsist.com/v1/files \
-H "Authorization: Bearer $CALLSIST_API_KEY" \
-F "file=@llamada.mp3"{
"id": "file_9xKp2mQvRt4L",
"object": "file",
"filename": "llamada.mp3",
"bytes": 427617,
"content_type": "audio/mpeg",
"created_at": "2026-07-29T08:12:44.812Z"
}- Formatos:
wav,mp3,flac,mpga,oga,ogg,m4a,mp4. - Tamaño máximo: 2 GB. Se rechaza por
Content-Lengthantes de leer el cuerpo. - Duración máxima: 10 horas.
- No hay URLs prefirmadas: el fichero pasa por el dominio de Callsist en streaming.
- El
file_idcaduca según la retención por defecto de la organización.
Otros métodos: GET /v1/files/{id} (requiere files:write) y DELETE /v1/files/{id}.
No mandes Idempotency-Key en POST /v1/files. El middleware hashea el cuerpo para
detectar reintentos, y para eso lo convierte en una cadena — incluido un multipart de
hasta 2 GB. Mándala en POST /v1/transcripts, que es el endpoint que cobra: una subida
duplicada solo deja un fichero huérfano, una transcripción duplicada se factura.
POST /v1/transcripts
Scope: transcripts:write. Es asíncrono: devuelve 202 con un id.
Hay que indicar exactamente uno de audio_url o file_id. Mandar los dos, o
ninguno, es 400 invalid_audio_source.
{
"audio_url": "https://…/llamada.mp3", // máx. 2048 caracteres, http o https
"file_id": "file_9xKp2mQvRt4L", // máx. 64 caracteres
"model": "callsist-scribe-1", // único valor válido; es el defecto
"language": "auto", // "auto" o ISO-639-1 de dos letras
"language_hints": ["es", "ca"], // 1 a 10 códigos. MUY recomendable
"punctuate": true,
"format_text": true,
"custom_vocabulary": ["Fibra Óptica"], // hasta 1000, 80 caracteres cada uno
"understanding": { /* los siete módulos */ },
"priority": "standard", // "standard" | "economy"
"metadata": { "ticket": "T-91823" },
"retention": "30d" // "none" | "24h" | "7d" | "30d"
}language_hints es lo que más mejora la detección
Pon solo los idiomas que de verdad aparecen en tus llamadas. Quitar al italiano de la competición mejora sensiblemente la discriminación entre castellano y catalán, que es la confusión más frecuente en llamadas peninsulares.
metadata es la pieza que hace útil la integración
Diccionario de hasta 64 caracteres por clave y 512 por valor. Vuelve tal cual en
GET /v1/transcripts/{id} y en el listado. Ahí es donde va el id del cliente, el del
agente y el del ticket del CRM: es lo que permite cruzar la transcripción con el resto
de tus datos sin mantener una tabla de correspondencias aparte.
retention explícito, aunque coincida con tu defecto
No porque haga falta, sino porque deja la intención escrita en la petición y no en una configuración que alguien puede cambiar sin avisar.
Cinco parámetros que se aceptan y no hacen nada
Pasan la validación, no dan error y no cambian el resultado. El pipeline solo recibe
language, language_hints, custom_vocabulary, punctuate y format_text.
| Parámetro | Lo que parece | Lo que pasa |
|---|---|---|
speaker_labels: false | Desactivar la diarización | Se diariza igual |
speakers_expected: 2 | Ayudar al diarizador | Se ignora; el número de hablantes se decide solo |
channels: "multichannel" | Separar por canal | Se ignora; siempre se mezcla a mono |
word_timestamps: false | No devolver words | Vienen igual |
language_confidence_threshold | Umbral del detector de idioma | Se ignora |
No construyas lógica que dependa de ellos. Para grabaciones de contact center no
suele importar —son mono y la diarización acústica funciona—, pero si tienes estéreo con
agente y cliente en canales separados, hoy no se aprovecha: se avisa con
stereo_source_available en warnings.
Idempotencia
Manda Idempotency-Key: <valor único> en el POST. Durante 24 h:
- misma clave, mismo cuerpo → se devuelve la respuesta original, con la cabecera
Idempotency-Replayed: true, y no se cobra otra vez; - misma clave, cuerpo distinto →
409 idempotency_key_reused.
Úsala siempre. Un reintento de red sin ella crea una segunda transcripción y la cobra.
Un buen valor es el file_id, o el id de la llamada en tu sistema.