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. |
| 403 | plan_feature_unavailable | No, hasta que la organización cambie a un plan de pago. |
| 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. |
| 422 | unit_type_not_found | Después de corregir el Modelo señalado en field. |
| 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.calificacion.operacion: un valor distinto decomprarorentar.calificacion.presupuesto:minomaxno son números (cero o mayores).calificacion.modelos: no es una lista, está vacía, trae más de 10 entradas, alguna entrada traeidynombrea la vez o ninguno de los dos, viene sinpropiedaden el cuerpo (los Modelos se buscan dentro de esa propiedad), o el cuerpo traemodeloymodelosal mismo tiempo (fieldescalificacion.modelos).calificacion.modelo: la forma corta de un solo Modelo, con las mismas reglas por entrada.atribucion: no es un objeto.atribucion.campana(ofuente,medio,contenido,pagina): el valor no es texto.atribucion.paginatambién cuando no es una URL ni una ruta que empiece por/.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.
Plan sin API de leads
403 plan_feature_unavailable. La llave es válida, pero el plan de tu organización no incluye la API de leads (el plan Gratis no la trae). Pídele a un Administrador de tu organización que cambie a un plan de pago; en cuanto el cambio se aplique, la misma llave vuelve a funcionar sin generar otra. El intento queda registrado en Solicitudes recibidas. Nada se escribió y la Idempotency-Key no queda reservada.
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.
Modelo no encontrado
422 unit_type_not_found. Alguno de los Modelos indicados no existe en esa propiedad. Cada entrada de calificacion.modelos se busca solo entre los Modelos de la propiedad que mandaste, por id o por nombre exacto (sin distinguir mayúsculas, pero sin coincidencias aproximadas); la API se detiene en el primero que no encuentra y no guarda nada. field señala esa entrada por su posición, por ejemplo calificacion.modelos[1] para la segunda (o calificacion.modelo si usaste la forma corta de un solo Modelo). Revisa el nombre o el id en el dashboard: la ficha de la propiedad muestra sus Modelos en la tarjeta Modelos. Si la propiedad no tiene Modelos todavía, omite modelos. 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.