Ir al contenido

Errores

{
"success": false,
"message": "API key inválida o expirada."
}

Siempre success: false y un message en español, pensado para que puedas mostrarlo o registrarlo tal cual. Un error nunca trae data.

success es el campo a mirar primero: en las respuestas correctas es true.

Código Significa Qué hacer
200 Todo bien —
401 Falta la key, o es inválida o expiró Revisa el header. No reintentes: no se va a arreglar solo
402 Sin saldo de consultas Compra una bolsa. No reintentes hasta recargar
403 La key es válida pero le falta el scope, el plan no incluye API, o la cuenta o la organización dueña de la key está suspendida Marca el scope, sube de plan o pide la reactivación. No reintentes
404 El recurso no existe en tu organización Verifica el identificador
422 Un parámetro no pasó validación Corrige el formato. No reintentes
429 Excediste el límite de peticiones Espera y reintenta con backoff
503 El RUNT no respondió, o /health detectó una dependencia caída Reintenta más tarde

Regla corta: 401, 402, 403 y 422 son tuyos —no reintentar sin cambiar algo—. 429 y 503 son transitorios —reintentar con espera—.

402 y 403 se parecen y no son lo mismo: 402 dice “recarga y vuelve”, 403 dice “tu llave no puede hacer esto”. Tratarlos igual te deja reintentando en vano o alertando a un humano que no hacía falta.

{
"success": false,
"message": "Sin saldo de consultas. Compra una bolsa para seguir usando el API."
}

El saldo es de la organización, no de la llave: todas tus llaves gastan del mismo. Se recarga en el panel, en Facturación → Consultas. Ver Límites de uso.

Dos mensajes distintos, y la diferencia importa:

{ "success": false, "message": "API key requerida. Proporciónala en el header X-API-Key o como Bearer token." }

No llegó ninguna key. Casi siempre es el header mal escrito, o un cliente HTTP que no lo está enviando.

{ "success": false, "message": "API key inválida o expirada." }

La key llegó pero no sirve: no existe, está desactivada o pasó su fecha de expiración. Revisa en el panel que siga activa.

{ "success": false, "message": "No tienes el scope necesario: vehicles.read" }

El mensaje nombra el scope exacto que falta, así que no hay que adivinar. Si tu key no tiene ningún scope marcado, todos los endpoints devuelven 403: una lista de scopes vacía niega todo. Ver Autenticación y scopes.

{
"success": false,
"message": "La cuenta o la organización de esta API key está suspendida."
}

La key existe y es válida, pero la cuenta que la creó fue desactivada o la organización a la que pertenece está suspendida. Mientras tanto, todos los endpoints responden esto, tenga los scopes que tenga.

La key no se borra: vuelve a funcionar sola apenas se reactiva la cuenta o la organización, sin cambiar nada en tu integración. Reintentar antes no sirve. Ver Si NotiAuto suspende la organización.

Solo lo devuelve GET /vehicles/{plate}:

{ "success": false, "message": "Vehículo no encontrado en tu organización." }

El mensaje es literal: puede que la placa exista en el RUNT, y hasta en NotiAuto, pero no está registrada en tu organización. La API de flota nunca devuelve datos de otras organizaciones.

También responde 404 un vehículo que la organización dio de baja en el panel. Los vehículos y conductores dados de baja no aparecen en la API: ni en GET /vehicles/{plate} ni en los listados GET /vehicles y GET /drivers, igual que los eliminados. La diferencia es que se pueden reactivar desde el panel, y entonces vuelven a aparecer.

Si lo que quieres son datos de un vehículo que no es tuyo, eso es POST /consults/vehicle, que consulta al RUNT.

Formato estándar de Laravel:

{
"message": "Placa inválida: escribe 3 letras y 3 números (ABC123). Moto: ABC12D o ABC12. Remolque: R12345.",
"errors": {
"plate": ["Placa inválida: escribe 3 letras y 3 números (ABC123). Moto: ABC12D o ABC12. Remolque: R12345."]
}
}

Lo devuelven los endpoints de consulta RUNT. Los formatos que exigen:

Campo Regla
plate Sin espacios ni guiones, no distingue mayúsculas: ABC123 (carro), ABC12D o ABC12 (moto), 123ABC (motocarro), R12345 o S12345 (remolque y semirremolque), T1234, CC1234, OI1234, AT1234 o iniciales de país y tres números (diplomáticas). Ver Vehículos
document Solo dígitos, entre 6 y 10
type_document Uno de los códigos válidos, distintos para vehículo y persona
first_surname Primer apellido de la persona, obligatorio en consultas de licencia

Los códigos de documento están en Consultas RUNT.

Sin cuerpo útil. La respuesta trae el header Retry-After con los segundos que faltan.

if (res.status === 429) {
const espera = Number(res.headers.get('Retry-After') ?? 60);
await new Promise((r) => setTimeout(r, espera * 1000));
// reintentar
}

Ver Límites de uso.

En los endpoints de consulta significa que el RUNT no respondió o rechazó la consulta. El message trae lo que reportó el RUNT:

{ "success": false, "message": "El RUNT no respondió a la consulta del vehículo." }

Un fallo del RUNT no se cachea nunca, así que el reintento sí puede dar otro resultado. Aun así, espera: si el RUNT está caído, reintentar de inmediato solo gasta tu límite de peticiones.

En GET /health un 503 significa que alguna dependencia está caída; mira dependencies para saber cuál.

POST /consults/vehicle puede responder 200 con soat o rtm en null:

{
"success": true,
"cached": false,
"data": { "plate": "ABC123", "marca": "CHEVROLET" },
"soat": null,
"rtm": { "numero": "...", "vigente": true }
}

Eso no significa “el vehículo no tiene SOAT”. Significa que esa sección del RUNT no respondió. Son cosas distintas y la API no las puede distinguir por ti.

Cuando pasa, la consulta no se cachea, así que volver a pedirla más tarde puede traer la sección completa. Nunca interpretes soat: null como “sin seguro”.

El detalle de un vehículo de tu flota trae public_service, con las pólizas de responsabilidad civil (RCC/RCE) y la tarjeta de operación que reporta el RUNT:

"public_service": {
"policies": [
{
"coverage": "RCC y RCE",
"number": "1234567",
"insurer": "SEGUROS DEL ESTADO",
"status": "VIGENTE",
"starts_on": "2026-03-01",
"date": "2027-03-01",
"state": "ok"
}
],
"card": {
"number": "987654",
"company": "TRANSPORTES DEL VALLE S.A.",
"mode": "PASAJEROS · POR CARRETERA",
"radius": "NACIONAL",
"status": "VIGENTE",
"date": "2027-01-15",
"state": "ok"
},
"history": { "policies": [], "cards": [] }
}
Campo Qué es
policies La póliza vigente de cada cobertura. coverage es RCC, RCE o RCC y RCE (una sola póliza que cubre las dos)
card La tarjeta de operación más reciente (number, company = empresa afiliadora, mode = modalidad, radius = radio de acción), o null si el RUNT no reporta ninguna
history Las demás pólizas (policies) y tarjetas (cards), de la más reciente a la más vieja
status El estado tal como lo dice el RUNT
date La fecha de vencimiento
state Nuestro veredicto: ok, soon (vence en 30 días o menos), expired (venció, o el RUNT ya no la reporta vigente) o missing

public_service: null no es un error: significa que el RUNT no reporta pólizas ni tarjeta para ese vehículo, que es lo normal en un particular. Es un campo agregado: si tu integración no lo lee, no le cambia nada.