Automatice llamadas telefónicas desde su propio sistema
Esta guía cubre los 22 endpoints públicos de OctoCall: cómo cargar una lista de contactos, lanzar las llamadas, seguir su avance y recuperar los resultados con su transcripción, su clasificación y sus archivos adjuntos. Léala completa antes de armar su colección en Postman o Apidog: la mitad de los problemas de integración se resuelven entendiendo la diferencia entre una campaña y un lote.
Conceptos clave
Cuatro palabras que aparecen en casi todos los endpoints. Si las confunde, va a mandar el identificador correcto al campo equivocado.
- Campaña
- La configuración reutilizable: qué dice el agente, a qué departamento pertenece y qué variables acepta. Se crea una vez y se usa muchas veces. En el JSON viaja como
campaign_id.
- Lote
- Una ejecución concreta de una campaña sobre una lista de contactos. Cada vez que lanza llamadas está creando un lote. Es lo que se pausa, se reanuda y de lo que se leen resultados.
- Agente
- La voz que llama. Ya configurado en su organización; usted solo elige cuál usar con
agent_id.
- Resultado
- El registro de una llamada: a quién se llamó, cuánto duró, qué se dijo, cómo se clasificó y qué archivos se adjuntaron.
Una campaña se define una vez y se ejecuta muchas veces. Cada ejecución es un lote distinto. Por eso, cuando lanza llamadas, el campo campaign_id del cuerpo apunta a la campaña (la configuración), mientras que el identificador que recibe de vuelta es el del lote recién creado.
Hay un detalle heredado que conviene tener presente: en las rutas de lotes el parámetro de la URL figura técnicamente como campaign_id, pero ahí siempre va el identificador del lote — el que le devolvió el lanzamiento, no el de la campaña. En esta guía lo escribimos como {batch_id} para evitar confusiones; el valor que usted envía es el mismo.
Autenticación
Todas las peticiones requieren una clave de acceso en la cabecera Authorization.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
La clave la genera un administrador de su organización desde el panel o desde el endpoint de creación. Se muestra una sola vez, en el momento de crearla: si la pierde, hay que revocarla y emitir una nueva.
Cada clave pertenece a una organización y solo ve los datos de esa organización. No hay forma de consultar recursos ajenos: si pide algo que no le pertenece, la respuesta es la misma que si no existiera.
Configure la autenticación a nivel de colección, no request por request: tipo Bearer Token con su clave. Guarde la URL base como variable de entorno y así podrá alternar entre pruebas y producción sin tocar cada petición.
Flujo típico
El orden en que conviene llamar a los endpoints la primera vez. Los pasos 1 a 3 se hacen una vez; del 4 en adelante, cada vez que quiera llamar.
-
Averigüe con qué puede trabajar
Liste sus agentes, sus campañas y sus números telefónicos. Anote los identificadores: los necesitará en el lanzamiento.
-
Revise cómo se clasifican las llamadas
Consulte la taxonomía del departamento de su campaña. Ahí están las etiquetas con las que se clasificará cada llamada, y de ahí saldrán los códigos que use para configurar reintentos.
-
Decida su política de reintentos
Cuántas veces reintentar un contacto que no atiende, cada cuánto, y ante qué resultados. Si no configura nada, se aplica un comportamiento por defecto conservador: un solo intento.
-
Lance el lote
Envíe la lista de contactos con sus variables a lanzar lote. Recibirá el identificador del lote y las llamadas empezarán a salir.
-
Siga el avance
Consulte el estado del lote o las estadísticas para ver cuántas llamadas se completaron y cómo se están clasificando.
-
Recupere e importe los resultados
Lea los resultados, tráigalos a su sistema y márquelos como procesados para no volver a traerlos en la siguiente consulta.
Forma de las respuestas
Las listas no usan todas el mismo envoltorio. Conviene saberlo antes de escribir el código que las recorre.
| Endpoints | Envoltorio | Paginación |
|---|---|---|
| Agentes, campañas, lotes, resultados | items, total, skip, limit |
Sí |
| Números telefónicos | phone_numbers, total |
No — devuelve todos |
| Departamentos | items, total |
No — devuelve todos |
| Claves de acceso | data, count |
Sí |
Donde hay paginación funciona igual: skip es cuántos registros saltar y limit cuántos traer. El campo total es el total real, no el de la página, así que sirve para saber cuántas páginas faltan.
Las fechas se devuelven en formato ISO 8601 (2026-07-20T14:32:10) y los identificadores son UUID.
Agentes
Las voces disponibles para llamar. Solo lectura: los agentes se configuran desde el panel.
Lista los agentes de su organización.
Filtros
| Parámetro | Qué hace | Por defecto |
|---|---|---|
skip | Cuántos saltar | 0 |
limit | Cuántos traer (máximo 100) | 50 |
is_active | Solo activos o solo inactivos | todos |
business_area_id | Filtra por área de negocio | todas |
Cada agente incluye
agent_id (el que usará al lanzar), name, description, is_active, el área de negocio a la que pertenece y su fecha de creación.
Trae un agente puntual. Devuelve los mismos campos que el listado.
Si el agente no existe, responde 404.
Campañas
Las configuraciones reutilizables. De aquí sale el campaign_id que necesita para lanzar.
Lista las campañas disponibles, de la más reciente a la más antigua.
Filtros
| Parámetro | Qué hace | Por defecto |
|---|---|---|
skip | Cuántas saltar | 0 |
limit | Cuántas traer (máximo 100) | 50 |
department_id | Filtra por departamento | todos |
business_area_id | Filtra por área de negocio | todas |
Cada campaña incluye
| Campo | Para qué sirve |
|---|---|
id | El valor que enviará como campaign_id al lanzar un lote |
campaign_name | Nombre legible de la campaña |
department_id | Departamento al que pertenece — úselo para consultar la taxonomía |
variable_keys | Nombres de las variables que el agente puede mencionar en la llamada |
Es la lista de datos que el agente sabe decir: por ejemplo nombre_cliente o monto_deuda. Al cargar cada contacto puede enviar valores para esas variables y el agente los usará durante la conversación. Si envía una variable que no está en esta lista, simplemente no se menciona.
Números telefónicos
Desde qué número saldrán las llamadas.
Lista los números disponibles para su organización: tanto los propios como los de uso general. Los inactivos no aparecen.
De cada número obtiene su phone_number_id, el número en formato internacional, un nombre amigable y si tiene SMS habilitado.
No admite filtros ni paginación: devuelve todos.
Si no indica un número en el lanzamiento, se asigna automáticamente el primero disponible. Especifíquelo solo si necesita que sus llamadas salgan desde un número concreto.
Taxonomía
El vocabulario con el que se clasifica cada llamada terminada. Consúltelo antes de configurar reintentos o filtrar resultados.
Lista los departamentos de su organización. Empiece por aquí: necesita un department_id para consultar la taxonomía.
También puede tomar el department_id directamente de una campaña.
Devuelve las etiquetas de clasificación disponibles para un departamento.
Parámetros
| Parámetro | Qué hace | Por defecto |
|---|---|---|
department_id | Obligatorio. De qué departamento quiere la taxonomía | — |
view | grouped agrupa por familias; catalog separa las etiquetas base de las propias de su organización | grouped |
Qué contiene cada etiqueta
| Campo | Para qué sirve |
|---|---|
slug | El código de la etiqueta. Es el que aparece como resultado_label en los resultados y el que usa para configurar reintentos |
display_name | El nombre legible, para mostrar en su interfaz |
success_flag | Indica si esa etiqueta cuenta como llamada exitosa |
source | Si la etiqueta es del catálogo base o creada por su organización |
Las etiquetas vienen organizadas en familias: las de no contacto agrupan los casos en que no se habló con nadie, las de contacto efectivo los casos en que sí. Esa agrupación es la que conviene usar para decidir qué reintentar.
Lotes
Crear ejecuciones, seguirlas y controlarlas. Aquí está el endpoint más importante de toda la API.
Crea un lote y empieza a llamar, en una sola petición. Responde 201.
Lo mínimo que necesita
{
"name": "Cobranza julio - primera pasada",
"agent_id": "a3f1...",
"campaign_id": "7b2c...",
"contacts": [
{
"phone": "+59891828169",
"name": "María Pérez",
"variables": { "monto_deuda": "4520" }
}
]
}
Campos obligatorios
| Campo | Qué es | Reglas |
|---|---|---|
name | Nombre del lote, para reconocerlo después | 1 a 200 caracteres. Se guarda tal cual, sin prefijos. Único entre sus lotes: si repite un nombre ya usado, se rechaza |
agent_id | Qué agente llama | Del listado de agentes |
campaign_id | Qué campaña se ejecuta | Debe tener un departamento configurado |
contacts | A quién llamar | Al menos uno. Teléfonos repetidos: se carga la primera ocurrencia y se ignoran las demás (duplicates en la respuesta) |
Cada contacto
| Campo | Qué es | Reglas |
|---|---|---|
phone | Número a marcar | Obligatorio. Marcable: 6–20 caracteres, solo dígitos (admite +, espacios, guiones, paréntesis). Si no es marcable (p. ej. "00"), el contacto se carga pero no se llama (Skipped) |
name | Nombre de la persona | Opcional. Hasta 100 caracteres |
variables | Datos que el agente puede mencionar | Opcional. Use los nombres de variable_keys |
Cuándo llamar
| Campo | Qué hace | Si lo omite |
|---|---|---|
date | Un único día, en formato YYYY-MM-DD | Se llama hoy |
start_dateend_date | Un rango de días. Van juntos o ninguno | Se llama hoy |
call_hours_start | Hora de inicio, formato HH:MM | 09:00 |
call_hours_end | Hora de fin, formato HH:MM | 21:00 |
date y el par start_date/end_date son excluyentes: use uno u otro, nunca los dos.
Opciones de la llamada
| Campo | Qué hace | Por defecto |
|---|---|---|
phone_number_id | Desde qué número salen las llamadas | El primero disponible |
enable_voicemail | Dejar mensaje si atiende un buzón de voz | false |
enable_dtmf | Permitir transferir a un agente humano | false |
dtmf_number | A qué extensión transferir | Obligatorio si activa la transferencia |
sort_by | En qué orden llamar, por ejemplo ["monto_deuda:desc"] | Orden de carga. Hasta 3 criterios |
Reintentos
El bloque retry controla qué pasa cuando una llamada no logra su objetivo. Si lo omite, se aplica un único intento por contacto.
{
"retry": {
"max_attempts": 3, // intentos por contacto (0 a 50)
"delay_minutes": 30, // espera entre intentos (0 a 1440)
"taxonomy": {
"enabled": true,
"retry_eligible_labels": ["no_contesta", "buzon_voz"],
"batch_at_list_end": false
}
}
}
| Campo | Qué hace |
|---|---|
max_attempts | Cuántas veces se marca a un mismo contacto. 1 significa un solo intento, sin reintentos |
delay_minutes | Cuánto esperar antes de volver a marcar |
retry_eligible_labels | Ante qué clasificaciones se reintenta. Use los slug de la taxonomía |
batch_at_list_end | false reintenta apenas cuelga; true espera a terminar toda la lista y reintenta en una segunda pasada |
Qué recibe
El id del lote creado — guárdelo, es el que usará para consultar resultados —, su estado, el total de contactos importados y un mensaje de confirmación. También incluye callable_contacts, skipped_contacts y, si aplica, el array skipped con los contactos cargados pero no marcados (teléfono inválido → estado de cola Skipped). Si el mismo teléfono aparece más de una vez, se carga solo la primera ocurrencia (first-wins) y la respuesta incluye duplicate_contacts y duplicates (ocurrencias ignoradas, no importadas; distintos de skipped). Los índices de skipped[] y duplicates[] son 0-based respecto al array contacts del request.
| Campo | Qué significa |
|---|---|
duplicates[].index | Índice 0-based de la ocurrencia ignorada en el request |
duplicates[].phone | Teléfono tal como llegó en esa fila |
duplicates[].name | Nombre si se envió |
duplicates[].kept_index | Índice 0-based de la fila que sí se cargó (la primera) |
Indicador de capacidad — capacity_warning
La respuesta incluye capacity_warning siempre que se pueda calcular — es informativo, no bloqueante: el lote se lanza igual, incluso cuando el estado es insufficient. Estima cuántos contactos se pueden procesar en la ventana de fechas/horario elegida, usando los canales que se proyecta tendrá disponibles su organización (según su cupo asignado), una duración de llamada típica y un factor de ocupación de los canales — no una tasa fija por canal.
{
"capacity_warning": {
"status": "insufficient",
"message": "~7543 contactos procesables en la ventana estimada (22 canal(es), 1 día(s) válido(s)) · Insuficiente para 27097 contacto(s) marcable(s)",
"estimated_capacity": 7543,
"ratio": 0.278,
"total_hours": 10,
"valid_days": 1,
"channels_expected": 22,
"occupancy_factor_assumed": 0.4
}
}
| Campo | Qué significa |
|---|---|
status | sufficient (ratio ≥ 1.2), tight (0.8–1.2) o insufficient (< 0.8) |
ratio | estimated_capacity / callable_contacts. 1.0 es justo |
estimated_capacity | Contactos que se estima poder procesar en la ventana |
total_hours | Horas efectivas consideradas. Si el lote arranca hoy, la primera jornada descuenta lo ya transcurrido (un lote lanzado a las 17:00 con ventana 09:00–21:00 cuenta 4h reales, no 12) |
valid_days | Días hábiles dentro de la ventana (feriados excluidos si skip_holidays es true) |
channels_expected | Canales que se proyecta tendrá disponibles su organización |
occupancy_factor_assumed | Fracción del tiempo que se asume a esos canales discando activamente |
Errores frecuentes
| Código | Motivo |
|---|---|
| 400 | Falta campaign_id, no existe, o su campaña no tiene departamento configurado |
| 400 | El número indicado no existe, está inactivo o no es de su organización |
| 400 | Ningún contacto pudo importarse, o ningún teléfono del body es marcable |
| 404 | El agente no existe |
| 422 | Algún campo no cumple su formato (fecha, hora, sort_by, etc.) |
| 422 | Ya existe un lote con ese name en su organización — elija otro nombre |
Si su organización activó el import asíncrono (contacte a soporte para activarlo — pensado para lotes grandes, decenas de miles de contactos), este mismo endpoint responde 202 Accepted en vez de 201. El request es idéntico; la diferencia es que el import de contactos y el inicio de llamadas corren en segundo plano en vez de dentro de la misma petición HTTP. Es opt-in por partner — si no lo activó, nada cambia.
{
"id": "campaign-uuid-here",
"status": "Queued",
"submitted_contacts": 30000,
"callable_contacts": 29500,
"skipped_contacts": 350,
"message": "Lote encolado para import asíncrono. 29850 contacto(s) a procesar. Consulte el progreso en import_status_url.",
"import_status_url": "/api/v1/external/batches/campaign-uuid-here/import-status",
"capacity_warning": null
}
submitted_contacts es el conteo crudo del request (antes de partición/dedupe) — no lo compare con total_contacts del 201, que es post-import. callable_contacts/skipped_contacts ya vienen calculados (post partición/dedupe) porque se resuelven en la misma petición. Use import_status_url para seguir el progreso.
Progreso del import asíncrono de un lote (ver arriba). Responde 404 si el lote no existe, 403 si existe pero es de otra organización.
{
"campaign_id": "campaign-uuid-here",
"status": "processing",
"submitted_contacts": 30000,
"importable_contacts_count": 29850,
"processed_contacts": 18000,
"error_detail": null,
"note": null
}
| Campo | Qué significa |
|---|---|
status | pending (todavía no arrancó), processing, done o error |
importable_contacts_count | Denominador real de processed_contacts (post partición/dedupe) — no submitted_contacts |
processed_contacts | Contactos ya procesados. Converge a importable_contacts_count |
error_detail | Motivo del fallo si status es error |
note | Poblado solo si el lote se lanzó por el camino síncrono (flag apagado) o es previo a esta funcionalidad — ahí el estado se deriva de la campaña, no de un job real |
Lista sus lotes, con su estado y su avance de análisis.
Filtros
| Parámetro | Qué hace |
|---|---|
status | Por estado del lote |
agent_id | Solo los de un agente |
campaign_id | Solo los de una campaña |
last_call_since | Solo los que tuvieron llamadas desde una fecha |
skip / limit | Paginación (máximo 100 por página) |
El bloque analysis
Cada lote trae cuántas llamadas ya tienen su análisis terminado (analyzed), cuántas hay en total (total) y un indicador ready que es true cuando todas están listas.
Espere a que ready sea true antes de traer los resultados a su sistema. Si importa antes, se llevará llamadas cuya clasificación todavía se está calculando.
Trae un lote puntual, con los mismos campos del listado. Responde 404 si no existe.
Detiene un lote en curso. Las llamadas ya iniciadas terminan; no se marcan nuevas.
Solo funciona sobre lotes activos. Si el lote ya estaba pausado, responde 400 indicando su estado actual.
Reanuda un lote pausado, o activa uno en borrador.
Acepta opcionalmente max_concurrent_calls para ajustar cuántas llamadas simultáneas permitir al reanudar.
Solo funciona sobre lotes pausados o en borrador. Si el lote ya está activo, responde 400.
Resultados
Qué pasó en cada llamada. Es la parte que va a consultar todos los días.
Lista los resultados de un lote. Por defecto trae solo las llamadas cuyo análisis ya terminó.
Filtros
| Parámetro | Qué hace | Por defecto |
|---|---|---|
status | Por estado de la llamada | todos |
resultado_label | Por clasificación, usando el slug de la taxonomía | todas |
client_processed | false trae solo lo que aún no importó | todos |
date_from / date_to | Rango de fechas, formato YYYY-MM-DD | sin límite |
time_from / time_to | Franja horaria, formato HH:MM | sin límite |
include_transcript | Incluir la transcripción completa | true |
include_summary | Incluir el resumen | true |
include_pending | Incluir llamadas sin análisis terminado | false |
skip / limit | Paginación (máximo 200 por página) | 0 / 50 |
La combinación más útil es client_processed=false: trae únicamente lo que todavía no importó. Impórtelo, márquelo como procesado, y la próxima consulta ya no lo devolverá. Así no necesita llevar la cuenta por su lado.
Qué trae cada resultado
| Campo | Qué es |
|---|---|
id | Identificador del resultado |
phone_number | Número que se marcó |
status | Cómo terminó la llamada |
resultado_label | Clasificación asignada al analizar la conversación |
duration_seconds | Cuánto duró |
started_at / ended_at | Cuándo empezó y terminó |
end_reason | Por qué terminó — por ejemplo, buzón de voz u ocupado |
transcript | Transcripción de la conversación |
summary | Resumen breve de lo hablado |
analysis | Datos extraídos de la conversación (ver abajo) |
attachments | Archivos del expediente (ver Adjuntos) |
context | Las variables con que se cargó el contacto |
client_processed | Si ya lo importó a su sistema |
dtmf_used | Si hubo transferencia a un agente humano |
batch_name | Nombre del lote al que pertenece |
El bloque analysis
Cuando la llamada fue efectiva, aquí llegan los datos concretos que el agente logró recoger — una fecha de pago comprometida, un monto, un motivo — dentro de extracted_data, junto con un nivel de confianza y un estado que indica si el análisis se realizó o se omitió por no haber conversación que analizar.
Resumen agregado de un lote, sin traer las llamadas una por una.
Devuelve el total de llamadas, cuántas se completaron, cuántas fallaron, la duración promedio y el desglose por clasificación.
Parámetros
| Parámetro | Qué hace | Por defecto |
|---|---|---|
date_from / date_to | Acota el rango de fechas | todo el lote |
is_detailed | Con true, cada clasificación incluye además la lista de llamadas que la componen | false |
El detalle completo de una llamada, con los mismos campos del listado.
Este es el único endpoint que devuelve el campo attachments con contenido. En el listado de un lote siempre llega vacío, para que traer 200 resultados no implique preparar cientos de enlaces de descarga.
Marca un resultado como ya importado a su sistema.
{ "client_processed": true }
Devuelve el resultado actualizado.
409 significa que el análisis de esa llamada todavía no terminó: espere y reintente, no la marque aún.
429 significa que está marcando de a uno demasiado rápido. Este endpoint admite pocas peticiones por minuto a propósito — para volúmenes altos use la versión masiva.
Marca hasta 500 resultados de una vez. Es la forma recomendada de cerrar una sincronización.
{
"result_ids": ["9f8e...", "1a2b..."],
"client_processed": true
}
Qué recibe
| Campo | Qué contiene |
|---|---|
updated | Cuántos se marcaron correctamente |
not_found_ids | Identificadores que no existen |
access_denied_ids | Identificadores que no son de su organización |
not_ready_ids | Llamadas cuyo análisis aún no terminó — reintente estas más tarde |
La operación no es todo o nada: los que se pueden marcar se marcan, y los demás se le informan por separado.
Adjuntos
Archivos asociados al expediente de una llamada: comprobantes, capturas, documentos.
| Regla | Valor |
|---|---|
| Archivos por llamada | Hasta 8 |
| Tamaño por archivo | Hasta 10 MB |
| Formatos aceptados | PNG, JPEG, WEBP, GIF y PDF |
| Cómo se valida el formato | Por el contenido real del archivo, no por su extensión |
| Vigencia de los enlaces | Alrededor de 1 hora |
Cada archivo llega con un enlace temporal que se genera en el momento de la consulta. No lo guarde en su base de datos: dejará de funcionar en aproximadamente una hora. Guarde el identificador del adjunto y pida un enlace nuevo cuando lo necesite.
Sube un archivo. Envío tipo formulario con el campo file.
Responde 201 con los datos del archivo y su enlace de descarga. Si el archivo no cumple alguna regla, responde 400 explicando el motivo.
Sube varios archivos en una sola petición. Envío tipo formulario con el campo files repetido una vez por archivo.
curl -X POST \
"https://api.octocall.ai/api/v1/external/results/{result_id}/attachments/bulk" \
-H "Authorization: Bearer sk_live_su_clave" \
-F "files=@./expediente/comprobante.png" \
-F "files=@./expediente/recibo.pdf" \
-F "files=@./expediente/cedula.jpg"
Éxito parcial
Responde 200 aunque algunos archivos sean rechazados. Nunca es todo o nada: los válidos se guardan y los demás se le informan con su motivo, en la misma respuesta.
{
"uploaded": [
{
"id": "9f8e...",
"filename": "comprobante.png",
"content_type": "image/png",
"size_bytes": 245678,
"url": "https://..."
}
],
"failed": [
{
"filename": "contrato.docx",
"error": "El contenido del archivo no coincide con un tipo permitido."
}
],
"total_after": 1
}
total_after es cuántos adjuntos tiene la llamada después de esta petición, contando los que ya tenía.
Límites de la petición
| Situación | Respuesta |
|---|---|
| Más de 8 archivos en un envío | 413 — no se procesa ninguno |
| Ningún archivo en el envío | 422 |
| Un archivo inválido entre varios válidos | 200 — el inválido va en failed |
| Se supera el tope de 8 por llamada | 200 — el excedente va en failed |
Como el máximo por envío (8) coincide con el máximo por llamada (8), ese rechazo solo aparece cuando la llamada ya tenía archivos. Por ejemplo: con 6 adjuntos previos y 4 nuevos, se aceptan 2 y se rechazan 2. En cambio, un envío de 12 archivos se rechaza entero antes de evaluar nada.
Genera un enlace de descarga nuevo para un archivo que ya subió.
Úselo cuando el enlace que tenía haya caducado. Evita tener que volver a pedir el detalle completo de la llamada solo para refrescar una dirección.
Devuelve los mismos datos del archivo, con un enlace recién emitido.
Claves de acceso
Gestión de las credenciales de su organización. Requiere permisos de administrador.
Crea una clave nueva.
{
"name": "Integración ERP - producción",
"scopes": ["read", "write"],
"expires_at": "2027-01-01T00:00:00"
}
Solo name es obligatorio. Si indica una fecha de expiración, debe ser futura.
La clave completa viene en el campo key de esta respuesta y no se puede recuperar después. Guárdela en su gestor de secretos antes de cerrar la ventana. Si la pierde, revoque esa clave y cree otra.
Lista las claves de su organización. Por seguridad nunca devuelve la clave completa, solo su prefijo para poder identificarla.
De cada una obtiene su nombre, si sigue activa, cuándo expira y cuándo se usó por última vez — útil para detectar credenciales olvidadas.
La respuesta viene en data con el total en count.
Revoca una clave. Deja de funcionar de inmediato.
La clave no se borra: queda registrada como inactiva para conservar el historial de uso.
Errores y límites
Qué significa cada código y qué hacer al recibirlo.
| Código | Qué pasó | Qué hacer |
|---|---|---|
| 400 | Algún dato del envío no es válido | Lea el mensaje: indica el campo exacto |
| 401 | Falta la clave o no es válida | Revise la cabecera Authorization |
| 403 | El recurso es de otra organización | Verifique que el identificador sea suyo |
| 404 | El recurso no existe | Verifique el identificador |
| 409 | El análisis de la llamada aún no terminó | Espere y reintente |
| 413 | Demasiados archivos en un envío | Divida en envíos de hasta 8 |
| 422 | Falta un campo obligatorio o tiene formato incorrecto | Revise el detalle: señala qué campo falló |
| 429 | Demasiadas peticiones seguidas | Espere antes de reintentar |
| 503 | La modalidad pedida no está disponible | Reintente más tarde o contacte a soporte |
Sobre los límites de uso
Hay dos techos: 50 peticiones por minuto por API key y 200 por minuto por organización. Si una key se pasa, las demás de la misma org siguen; si la org llega a 200, todas esperan. El 429 caduca solo al cerrar la ventana (1 minuto, o 5 si el exceso se repite). Que la key no tenga fecha de vencimiento no deja el bloqueo permanente.
El marcado individual de resultados como procesados tiene un límite más estricto, a propósito: está pensado para correcciones puntuales. Para volúmenes reales use siempre la versión masiva, que acepta 500 por petición.
Los adjuntos responden 404, no 403
En la mayoría de los endpoints, pedir un recurso ajeno devuelve 403. En los de adjuntos devuelve 404, igual que si no existiera. Es deliberado: así no se revela la existencia de expedientes de otras organizaciones. No lo interprete como un error de su integración.