Primera transcripción
De un mp3 a JSON con hablantes separados, en cuatro llamadas.
Cuatro llamadas: comprobar la clave, subir el audio, encolar la transcripción y recoger el resultado. La transcripción es asíncrona —devuelve un id y el resultado se recoge después—, y esa es la única parte que sorprende a quien viene de una API síncrona.
1. Comprobar la clave
export CALLSIST_API_KEY="sk_live_…"
curl https://api.callsist.com/v1/me \
-H "Authorization: Bearer $CALLSIST_API_KEY"Si esto devuelve tu organización y tus scopes, sigue. Si no, ve a Autenticación.
2. Subir el audio
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"
}También se puede pasar una URL pública en lugar de subir el fichero. Con fichero subido la estimación de coste es exacta porque se conoce el tamaño; con URL se asume una duración conservadora. Los detalles, en Subir audio.
3. Encolar la transcripción
curl -X POST https://api.callsist.com/v1/transcripts \
-H "Authorization: Bearer $CALLSIST_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: file_9xKp2mQvRt4L" \
-d '{
"file_id": "file_9xKp2mQvRt4L",
"language_hints": ["es", "ca"],
"understanding": {
"topic_detection": { "taxonomy": "contact_center" },
"content_moderation": {},
"pii_redaction": { "policy": "entity_name" },
"profanity_filter": { "policy": "mask" },
"sentiment_analysis": { "scope": "customer" },
"summarization": { "format": "bullets" },
"action_items": true
},
"retention": "30d",
"metadata": { "ticket": "T-91823" }
}'Responde 202 con el id y una estimación de coste:
{
"id": "tr_MoKLFufBqnzJ",
"object": "transcript",
"status": "queued",
"estimated_cost": { "eur": 0.0453, "assumed_seconds": 240 }
}Cuatro decisiones metidas en ese cuerpo, y todas importan:
Idempotency-Keyes elfile_id. Un reintento de red sin clave de idempotencia crea una segunda transcripción y la cobra. Usando elfile_id, reintentar devuelve la original conIdempotency-Replayed: truey no cuesta nada.language_hintses lo que más mejora la detección de idioma. Pon solo los que de verdad aparecen en tus llamadas: quitar al italiano de la competición mejora notablemente el castellano contra el catalán.- Los siete módulos o ninguno. El pack cuesta 0,29 €/h y solo se aplica con los siete; seis sueltos cuestan 0,35 €/h. Pedir los siete sale más barato que pedir seis.
metadataes lo que hace útil la integración. Ahí va el id del ticket, del agente y del cliente; vuelve tal cual al leer la transcripción y te ahorra mantener una tabla de correspondencias aparte.
4. Recoger el resultado
curl https://api.callsist.com/v1/transcripts/tr_MoKLFufBqnzJ \
-H "Authorization: Bearer $CALLSIST_API_KEY"Mientras no esté lista, la respuesta es corta: status vale queued o processing.
Sondea cada 10 segundos. Cuando pase a completed, llega todo:
{
"id": "tr_MoKLFufBqnzJ",
"status": "completed",
"language": "es",
"audio_duration": 216.999,
"billed_duration": 240,
"text": "Acme Telecom, buenos días, le atiende Marta. ¿En qué puedo ayudarle?…",
"utterances": [
{ "speaker": "1", "speakerRole": "agent", "text": "…", "start": 0, "end": 5.2 },
{ "speaker": "0", "speakerRole": "customer", "text": "…", "start": 5.66, "end": 15.82 }
],
"speaker_role_confidence": 0.9,
"understanding": { "…": "…" },
"pii": { "…": "…" },
"warnings": [],
"usage": { "total_eur": 0.041 }
}Antes de usar nada de ahí, lee warnings. Es la lista de lo que pediste y no llegó.
Un módulo que aparece en warnings no está en understanding, y tratarlo como vacío es
un error de datos disfrazado de resultado. Y si activaste la redacción de PII, el texto
tapado no es text: está en pii.text_redacted. Las dos cosas, en
Leer el resultado.
El flujo completo, resumido
1. GET /v1/me ← comprobar clave y scopes
2. GET /v1/balance ← ¿hay saldo para el lote?
3. POST /v1/files ← subir el mp3 → file_id
4. POST /v1/transcripts ← con Idempotency-Key → tr_… (202)
5. GET /v1/transcripts/{id} ← sondear cada 10 s hasta completed | failed
6. leer warnings ← ¿llegó lo que pediste?
7. POST /v1/chat/completions ← análisis con plantilla, si hace falta