Errores
Cada código de error de la API, qué significa y qué hacer.
La forma de un error
Todas las respuestas de error, sin excepción, tienen este cuerpo:
{
"error": {
"code": "validation_error",
"message": "telefono must contain at least 10 digits",
"field": "telefono",
"docs_url": "https://docs.zevra.co/integraciones/api-captacion/errores#validation_error"
},
"request_id": "req_4f1c9a2b7d3e8c5a6b0f1e2d"
}codees estable: programa contra él. Elmessageestá en inglés, pensado para quien programa, y puede cambiar de redacción.fieldaparece solo cuando el error apunta a un campo o cabecera concretos, en notación con puntos (propiedad.codigo,extras.presupuesto,Idempotency-Key).docs_urlapunta a la sección de esta página que explica el código.request_ididentifica el intento. Aparece también en la cabeceraX-Request-Idy en Solicitudes recibidas dentro del dashboard.
Resumen
| HTTP | code | Reintentar |
|---|---|---|
| 400 | validation_error | Después de corregir el cuerpo. |
| 401 | invalid_key | No, hasta tener una llave válida. |
| 404 | not_found | No. |
| 405 | method_not_allowed | No. |
| 409 | idempotency_conflict | Con otra Idempotency-Key. |
| 409 | idempotency_in_progress | Sí, después de Retry-After (1 segundo). |
| 413 | payload_too_large | Después de reducir el cuerpo. |
| 415 | unsupported_media_type | Después de corregir Content-Type. |
| 422 | property_not_found | Después de corregir la propiedad. |
| 429 | rate_limited | Sí, después de Retry-After. |
| 500 | internal_error | Sí, con la misma Idempotency-Key. |
| 503 | temporarily_unavailable | Sí, después de Retry-After (5 segundos). |
Errores de validación
400 validation_error. El cuerpo, uno de sus campos o una cabecera no pasó la validación. field indica cuál. Casos comunes:
body: el cuerpo no es JSON válido o no es un objeto.nombre: falta o pasa de 200 caracteres.telefono: tiene menos de 10 dígitos.email: no tiene forma de correo.mensaje: pasa de 2 000 caracteres.propiedad: trae dos identificadores, ninguno, o una llave que no escodigo,external_codeniid.extras: más de 20 entradas, una llave de más de 60 caracteres, un valor de más de 200 caracteres, o un valor que no es texto, número ni booleano.Idempotency-Key: vacía, de más de 200 caracteres o con caracteres que no son ASCII imprimible.
Corrige el campo y vuelve a mandar. Si usaste Idempotency-Key, puedes reutilizarla: un intento fallido no la reserva.
Llave inválida
401 invalid_key. La cabecera Authorization falta, no usa el esquema Bearer, la llave no existe o fue revocada. Revisa que estés mandando la llave completa (zvr_live_...) y que no haya sido revocada en Captación. El intento queda registrado en Solicitudes recibidas aunque la llave sea inválida, con el prefijo que mandaste.
Ruta no encontrada
404 not_found. La ruta no existe. Las rutas válidas son GET /v1, GET /v1/openapi.json y POST /v1/leads. Revisa que no falte el prefijo /v1 y que no sobre una barra o un parámetro.
Método no permitido
405 method_not_allowed. La ruta existe pero no con ese método (por ejemplo, un GET /v1/leads). La cabecera Allow lista los métodos válidos. OPTIONS también responde 405: no hay preflight porque no hay CORS.
Conflicto de idempotencia
409 idempotency_conflict. Ya usaste esa Idempotency-Key en las últimas 24 horas con un cuerpo distinto. Una llave corresponde a un envío; si el contenido cambió, es otro envío y necesita otra llave. Detalle en Idempotencia.
Solicitud en curso
409 idempotency_in_progress. Otra solicitud con la misma Idempotency-Key y el mismo cuerpo sigue procesándose (típico cuando dos procesos reintentan a la vez). Trae Retry-After: 1: espera un segundo y reintenta; recibirás la respuesta original con "replay": true.
Cuerpo demasiado grande
413 payload_too_large. El cuerpo pasa de 64 000 bytes. Lo normal es un mensaje o unos extras enormes; recorta lo que no sea del lead. La conexión se cierra al responder.
Tipo de contenido no soportado
415 unsupported_media_type. La cabecera Content-Type no es application/json. Un application/x-www-form-urlencoded (el envío por defecto de un <form> HTML) o un text/plain caen aquí. Serializa a JSON y manda la cabecera correcta.
Propiedad no encontrada
422 property_not_found. El identificador de propiedad no corresponde a ninguna propiedad de tu organización. Revisa el código en el dashboard (la ficha de la propiedad muestra su código ZVR-#### y tu código propio) y que la propiedad no esté archivada. field es propiedad. Un intento fallido no reserva la Idempotency-Key.
Límite de solicitudes
429 rate_limited. Pasaste de 60 solicitudes por minuto con esta llave. Retry-After dice cuántos segundos esperar y las cabeceras X-RateLimit-* te dan el estado de la ventana. Un reintento en bucle sin espera (un Zapier que reintenta sin pausa) es la causa habitual. Detalle en Límites.
Error interno
500 internal_error. Algo falló de nuestro lado al guardar el lead. Reintenta con la misma Idempotency-Key: si el lead alcanzó a crearse, recibirás su respuesta; si no, se creará ahora. Si persiste, escríbenos con el request_id.
Servicio temporalmente no disponible
503 temporarily_unavailable. La base de datos no respondió al consultar la llave o la idempotencia. Trae Retry-After: 5. Nada se escribió; reintenta después de esos segundos con la misma Idempotency-Key.