> ## Documentation Index
> Fetch the complete documentation index at: https://docs.1to1ai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errores

> Cómo la API señala los errores y cómo manejarlos.

La API sigue un contrato **REST puro**: el status code HTTP es la señal de
éxito o error.

## Forma de la respuesta

<CodeGroup>
  ```json Éxito theme={null}
  { "message_uuid": "...", "wamid": "..." }
  ```

  ```json Error theme={null}
  {
    "code": "WINDOW_CLOSED",
    "message": "The 24-hour messaging window is closed. Send an approved template to reopen it."
  }
  ```
</CodeGroup>

Un éxito devuelve el payload directo, sin envelope. Un error devuelve siempre
`{ code, message }` — ambos campos están garantizados.

<Tip>
  Haz `switch` sobre `code`: es estable y forma parte del contrato. El
  `message` es texto humano de ayuda y puede afinarse entre versiones de la
  API sin aviso. Los mensajes se entregan en inglés (estándar de industria,
  mismo patrón que Stripe, GitHub o Linear). Si necesitas mostrarlos
  traducidos al usuario final, mapéalos en tu cliente por `code`.
</Tip>

## Familias de status

| HTTP  | Significado                                                                        | ¿Reintentar?               |
| ----- | ---------------------------------------------------------------------------------- | -------------------------- |
| `2xx` | Éxito — `200` lectura, `201` creación, `202` aceptado (async), `207` multi-status. | —                          |
| `4xx` | Error del request — auth, validación o recurso inexistente.                        | No, corrígelo primero.     |
| `429` | Rate limit excedido.                                                               | Sí, tras el `Retry-After`. |
| `5xx` | Error del servidor.                                                                | Sí, con backoff.           |

## Catálogo de códigos

<Note>
  El status HTTP de cada código es **típico**: el endpoint puntual puede devolver
  otro status si el contexto lo justifica. El authoritative por endpoint vive en
  la sección **Referencia de API**. La tabla aquí es referencia general, no
  contrato vinculante por endpoint.

  Los códigos de ambigüedad de resolución de conversación (`PHONE_NUMBER_AMBIGUOUS`,
  `USERNAME_AMBIGUOUS`) pueden aparecer en **cualquier** endpoint que acepte una
  referencia `conversation` por `phone`/`username`, aunque su Referencia de API
  liste otros códigos `409`.
</Note>

### Auth y tenant

| Code                      | HTTP | Descripción                                                                                        |
| ------------------------- | ---- | -------------------------------------------------------------------------------------------------- |
| `INVALID_API_TOKEN`       | 401  | El token no existe o fue revocado. Genera uno nuevo en Settings → API Token.                       |
| `TOKEN_BUSINESS_MISMATCH` | 403  | El token no pertenece al slug del negocio en la URL. Verifica que ambos refieran al mismo negocio. |

### Rate limit

| Code                  | HTTP | Descripción                                                                                                          |
| --------------------- | ---- | -------------------------------------------------------------------------------------------------------------------- |
| `RATE_LIMIT_EXCEEDED` | 429  | Superaste el bucket de 60 req/min. Espera los segundos del header `Retry-After`. Ver [Rate limits](/es/rate-limits). |

### Validación

| Code                   | HTTP | Descripción                                                                                          |
| ---------------------- | ---- | ---------------------------------------------------------------------------------------------------- |
| `INVALID_REQUEST`      | 400  | El body no pasó la validación de schema (campo faltante, tipo incorrecto, valor fuera de rango).     |
| `INVALID_CURSOR`       | 400  | El cursor de paginación es inválido o expiró. Reinicia el listado sin cursor.                        |
| `BATCH_LIMIT_EXCEEDED` | 400  | El grupo de acciones excede el máximo permitido en una sola request. El `message` lleva el cap real. |

### Conversación, contacto y canal

| Code                                | HTTP | Descripción                                                                                                                                                      |
| ----------------------------------- | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CONVERSATION_NOT_FOUND`            | 404  | El identificador de `conversation` (`uuid`, `whatsapp_user_id`, `username` o `phone`) no resuelve a ninguna conversación del negocio.                            |
| `CONTACT_NOT_FOUND`                 | 404  | El identificador de contacto no resuelve a ninguno del negocio.                                                                                                  |
| `PHONE_NUMBER_AMBIGUOUS`            | 409  | Varios contactos comparten ese teléfono (números reciclados / identidades separadas). Identifica la conversación por `whatsapp_user_id` o `uuid`.                |
| `USERNAME_AMBIGUOUS`                | 409  | Varios contactos comparten ese username. Identifica la conversación por `whatsapp_user_id` o `uuid`.                                                             |
| `CHANNEL_NOT_CONFIGURED`            | 422  | La conversación no tiene un canal de WhatsApp configurado. Conecta uno en el dashboard antes de enviar.                                                          |
| `TESTER_CONVERSATION_NOT_WRITABLE`  | 422  | Las conversaciones tester no aceptan envíos reales a WhatsApp. Usa una real, o limita la acción a tags/notas/mailbox.                                            |
| `TRANSCRIPTION_REQUIRED_TO_RESOLVE` | 422  | `POST /conversation/resolve`: la conversación tiene media entrante con transcripción pendiente. Completa la transcripción manual desde el dashboard y reintenta. |

### Tags

| Code                        | HTTP | Descripción                                                                                                   |
| --------------------------- | ---- | ------------------------------------------------------------------------------------------------------------- |
| `TAG_NOT_FOUND`             | 404  | El tag no existe para este negocio.                                                                           |
| `TAG_ALREADY_ASSIGNED`      | 409  | El tag ya está asignado a esta conversación.                                                                  |
| `TAG_NOT_ASSIGNED`          | 404  | El tag no está asignado, por lo que no se puede remover.                                                      |
| `TAG_AMBIGUOUS`             | 409  | Hay varios tags con ese nombre. Usa `tag_uuid` para desambiguar.                                              |
| `TAG_BUSINESS_MISMATCH`     | 400  | El tag pertenece a otro negocio.                                                                              |
| `CANNOT_ASSIGN_DEFAULT_TAG` | 422  | El tag es de sistema (lo administra el backend, ej. el de conversión pendiente) y no puede asignarse por API. |
| `CANNOT_REMOVE_DEFAULT_TAG` | 422  | El tag es de sistema (lo administra el backend, ej. el de conversión pendiente) y no puede removerse por API. |

### Mailboxes y categorías

| Code                         | HTTP | Descripción                                                                        |
| ---------------------------- | ---- | ---------------------------------------------------------------------------------- |
| `CATEGORY_NOT_FOUND`         | 404  | La categoría de mailbox no existe para este negocio.                               |
| `CATEGORY_BUSINESS_MISMATCH` | 403  | La categoría pertenece a otro negocio.                                             |
| `AMBIGUOUS_CATEGORY`         | 409  | Hay varias categorías con ese nombre. Usa `category_uuid` para desambiguar.        |
| `MAILBOX_NOT_FOUND`          | 404  | El mailbox no existe para este negocio.                                            |
| `MAILBOX_ALREADY_ASSIGNED`   | 409  | La conversación ya está en ese mailbox.                                            |
| `AMBIGUOUS_MAILBOX`          | 409  | Hay varios mailboxes con ese nombre. Usa `mailbox_uuid` para desambiguar.          |
| `NO_MAILBOXES_IN_CATEGORY`   | 422  | La categoría no tiene mailboxes configurados. Agrega al menos uno en el dashboard. |

### Guards de precondición

| Code                      | HTTP | Descripción                                                                                                       |
| ------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------- |
| `WINDOW_CLOSED`           | 422  | La ventana de 24h está cerrada. Envía una [plantilla](/es/templates) aprobada para reabrirla.                     |
| `WALLET_BLOCKED`          | 402  | El wallet de tokens del modelo AI requerido está vacío o bloqueado. Recarga para continuar.                       |
| `VISION_WALLET_BLOCKED`   | 402  | El wallet de vision tokens está vacío. El procesamiento de visión requiere recarga.                               |
| `VISION_BLOCKED`          | 402  | El pipeline de visión del thread está bloqueado. Resuelve la media pendiente en el dashboard antes de reintentar. |
| `NO_AI_EMPLOYEE_ASSIGNED` | 422  | La conversación no tiene un empleado AI asignado. Asigna uno antes de ejecutar la acción.                         |

### Coherencia owner ↔ executor (schedules)

| Code             | HTTP | Descripción                                                                                                                   |
| ---------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------- |
| `OWNER_MISMATCH` | 422  | El executor del scheduled message no coincide con el owner actual de la conversación. Reasigna o cancela el schedule primero. |

### Empleados AI y ejecución

| Code                           | HTTP | Descripción                                                                                          |
| ------------------------------ | ---- | ---------------------------------------------------------------------------------------------------- |
| `AI_EMPLOYEE_NOT_FOUND`        | 404  | El empleado AI no existe para este negocio.                                                          |
| `AMBIGUOUS_AI_EMPLOYEE`        | 409  | Hay varios empleados con ese nombre. Usa `ai_employee_uuid` para desambiguar.                        |
| `AI_EMPLOYEE_ALREADY_ASSIGNED` | 409  | Ese empleado AI ya está asignado a la conversación.                                                  |
| `INVALID_ASSIGNEE_FOR_RUN_AI`  | 409  | La conversación es human-owned y no se pasó `ai_employee`. Especifica uno o reasigna un AI primero.  |
| `AI_EXECUTION_FAILED`          | 500  | La ejecución del AI falló inesperadamente. Reintenta; si persiste, revisa el dashboard del empleado. |
| `ACTIONS_DEPTH_EXCEEDED`       | 422  | Las acciones AI encadenadas exceden la profundidad máxima permitida en una request.                  |

### Scheduled message action

| Code                                | HTTP | Descripción                                                                                                        |
| ----------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------ |
| `SCHEDULED_MESSAGE_ACTION_REQUIRED` | 422  | Hay un scheduled message activo en la conversación. Especifica `scheduled_message_action` (`reassign` o `cancel`). |
| `SCHEDULED_MESSAGE_ACTION_INVALID`  | 400  | El valor de `scheduled_message_action` es inválido. Debe ser `reassign` o `cancel`.                                |

### Uploads

| Code                                 | HTTP | Descripción                                                                                                                        |
| ------------------------------------ | ---- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `INVALID_FILE_TYPE`                  | 400  | El tipo de archivo no está permitido. Ver la documentación para la lista de MIME types aceptados.                                  |
| `FILE_TOO_LARGE`                     | 400  | El archivo excede el tamaño máximo para su categoría.                                                                              |
| `STORAGE_QUOTA_EXCEEDED`             | 413  | El negocio alcanzó su cuota de storage. Libera espacio o sube de plan.                                                             |
| `STORAGE_QUOTA_CLEANUP_INSUFFICIENT` | 507  | El storage está lleno y la limpieza automática no pudo liberar suficiente espacio para este upload. Libera espacio o sube de plan. |
| `FILE_NOT_FOUND`                     | 404  | No existe un archivo con ese `file_uuid` para este negocio.                                                                        |
| `FILE_NOT_UPLOADED`                  | 422  | El archivo fue registrado pero el upload nunca se confirmó. Re-súbelo antes de referenciarlo.                                      |
| `SIZE_MISMATCH`                      | 422  | El tamaño real del archivo subido no coincide con el declarado en `request-upload`.                                                |
| `MIME_MISMATCH`                      | 422  | El MIME type real no coincide con el declarado. Re-sube con el `Content-Type` correcto.                                            |
| `UPLOAD_FAILED`                      | 500  | El upload no se pudo completar por un error de storage. Reintenta.                                                                 |

### Mensajes

| Code                  | HTTP | Descripción                                                                                                                                                                                 |
| --------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PREPARE_FAILED`      | 500  | El mensaje no se pudo preparar (error de DB o upstream). Reintenta.                                                                                                                         |
| `SEND_FAILED`         | 502  | El envío a WhatsApp falló. Verifica la salud del canal y reintenta.                                                                                                                         |
| `BSUID_SEND_DISABLED` | 409  | El contacto no tiene teléfono y el envío por su identidad BSUID (business-scoped user ID) está deshabilitado para este negocio. Usa un contacto con teléfono o habilita el envío por BSUID. |

### Quick replies y plantillas

| Code                                         | HTTP | Descripción                                                                                                                           |
| -------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `QUICK_REPLY_NOT_FOUND`                      | 404  | La quick reply no existe para este negocio.                                                                                           |
| `QUICK_REPLY_AMBIGUOUS`                      | 409  | Hay varias quick replies con ese nombre. Usa `quick_reply_uuid` para desambiguar.                                                     |
| `QUICK_REPLY_EMPTY`                          | 422  | La quick reply no tiene acciones configuradas. Agrega al menos una en el dashboard.                                                   |
| `TEMPLATE_NOT_FOUND`                         | 404  | La plantilla no existe para este negocio.                                                                                             |
| `TEMPLATE_NOT_APPROVED`                      | 422  | La plantilla no está aprobada por Meta. La aprobación es requisito para enviar.                                                       |
| `AUTH_TEMPLATE_REQUIRES_PHONE`               | 409  | No se puede enviar una plantilla de autenticación a un contacto sin teléfono: Meta exige el número. Envía a un contacto con teléfono. |
| `TEMPLATE_AMBIGUOUS`                         | 409  | Hay varias plantillas con ese nombre. Especifica `language` para desambiguar.                                                         |
| `TEMPLATE_VARIABLES_INVALID`                 | 422  | Las variables del body no coinciden con la plantilla (conteo incorrecto, índice faltante o valor vacío).                              |
| `TEMPLATE_HEADER_MISMATCH`                   | 400  | El tipo de header no coincide con el que declara la plantilla (ej: la plantilla espera imagen y enviaste texto).                      |
| `TEMPLATE_FAKE_REQUIRES_TESTER_CONVERSATION` | 422  | La plantilla es del módulo Tester (fake) y solo puede enviarse a conversaciones tester.                                               |

### Operaciones genéricas

| Code            | HTTP | Descripción                                                                    |
| --------------- | ---- | ------------------------------------------------------------------------------ |
| `FETCH_FAILED`  | 500  | No se pudieron leer los datos necesarios para completar el request. Reintenta. |
| `UPDATE_FAILED` | 500  | El cambio no se pudo aplicar (error de DB). Reintenta.                         |
| `UNKNOWN_ERROR` | 500  | Error inesperado. Contacta a soporte si persiste.                              |
