Cómo integrar una API de placas de Ecuador
Publicado el
Una API de placas permite incorporar datos básicos de un vehículo a una aplicación de flotas, seguros, compraventa o verificación documental sin obligar a tu equipo a consultar cada placa manualmente.
En esta guía integraremos la ficha básica del vehículo. El ejemplo evita datos personales y muestra cómo normalizar la placa, autenticar la solicitud, leer el JSON y responder ante errores temporales.
Qué endpoint usar para una consulta vehicular
Usa GET /api/v1/placas/{placa}/vehiculo para obtener marca, modelo, año, color, clase, servicio y fechas de matriculación disponibles. Es un buen punto de partida cuando no necesitas información adicional.
La documentación también presenta endpoints separados para otras consultas vehiculares. Selecciona solo los datos que correspondan a tu producto y a la finalidad informada al usuario.
Cómo preparar la placa y la API key
- Genera una API key y mantenla como variable de entorno en el backend.
- Convierte la placa a mayúsculas y elimina espacios o guiones antes de construir la URL.
- Codifica el valor como un segmento de URL y no formes rutas con texto sin validar.
- Usa un valor ficticio en pruebas y evita almacenar consultas completas en logs.
Ejemplos para consultar una placa desde código
Los cuatro ejemplos consultan la misma ficha básica. Sustituye ABC1234 por la placa normalizada que necesites procesar.
GET /api/v1/placas/{placa}/vehiculoEl ejemplo usa un identificador ficticio. Reemplázalo por el dato que necesitas consultar.
curl --request GET "https://api.ecuadorapi.com/api/v1/placas/ABC1234/vehiculo" \
--header "Authorization: Bearer $ECUADORAPI_KEY" \
--header "Accept: application/json" \
--fail-with-body \
--max-time 60const response = await fetch("https://api.ecuadorapi.com/api/v1/placas/ABC1234/vehiculo", {
headers: {
Authorization: "Bearer " + process.env.ECUADORAPI_KEY,
Accept: "application/json",
},
signal: AbortSignal.timeout(60_000),
})
const contentType = response.headers.get("content-type") ?? ""
const body = contentType.includes("json")
? await response.json().catch(() => null)
: null
if (!response.ok || body?.error) {
throw new Error(body?.message ?? "Request failed: " + response.status)
}
if (!body || !("data" in body)) {
throw new Error("API returned an invalid response")
}
const result = body.data
// Use result in your server-side flow. Avoid logging personal responses.import os, requests
response = requests.get(
"https://api.ecuadorapi.com/api/v1/placas/ABC1234/vehiculo",
headers={
"Authorization": f"Bearer {os.environ['ECUADORAPI_KEY']}",
"Accept": "application/json",
},
timeout=60,
)
content_type = response.headers.get("content-type", "")
try:
body = response.json() if "json" in content_type else None
except requests.exceptions.JSONDecodeError:
body = None
if not response.ok or (isinstance(body, dict) and body.get("error")):
message = body.get("message") if isinstance(body, dict) else None
raise RuntimeError(message or f"Request failed: {response.status_code}")
if not isinstance(body, dict) or "data" not in body:
raise RuntimeError("API returned an invalid response")
data = body["data"]
# Use data in your server-side flow. Avoid logging personal responses.$ch = curl_init("https://api.ecuadorapi.com/api/v1/placas/ABC1234/vehiculo");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("ECUADORAPI_KEY"),
"Accept: application/json",
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
$rawBody = curl_exec($ch);
if ($rawBody === false) {
$transportError = curl_error($ch);
curl_close($ch);
throw new RuntimeException("Request transport failed: " . $transportError);
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$body = json_decode($rawBody, true);
if (!is_array($body)) {
throw new RuntimeException("API returned invalid JSON");
}
if ($statusCode >= 400 || ($body["error"] ?? false)) {
throw new RuntimeException(
($body["message"] ?? null) ?: "Request failed: " . $statusCode
);
}
if (!array_key_exists("data", $body)) {
throw new RuntimeException("API returned an invalid response");
}
$data = $body["data"];
// Use $data in your server-side flow. Avoid logging personal responses.Respuesta de ejemplo · 200 OK
JSON ficticio con la misma estructura que devuelve la API. Verlo o copiarlo no consume saldo.
{
"data": {
"plate": "ABC1234",
"camv_cpn": "T01234567",
"brand": "CHEVROLET",
"model": "AVEO ACTIVO 1.6",
"year": 2018,
"color": "PLATEADO",
"vehicle_class": "AUTOMOVIL",
"service": "PARTICULAR",
"engine_cc": 1600,
"country": "ECUADOR",
"last_registration_date": "2025-04-16",
"registration_expiry_date": "2026-04-16",
"fetched_at": "2026-06-20T16:00:00Z"
},
"error": null,
"message": null
}Campos principales de la respuesta
- data.plate identifica la placa asociada a la ficha.
- data.brand, data.model y data.year describen el vehículo.
- data.color, data.vehicle_class y data.service ayudan a contrastar sus características básicas.
- data.last_registration_date y data.registration_expiry_date pueden ser null cuando no existe una fecha confirmada.
- data.fetched_at indica cuándo se obtuvo la información presentada por la API.
Cómo manejar errores y reintentos
- 400: revisa el formato y la normalización del identificador.
- 401, 402 o 403: comprueba la API key, el saldo y el estado de la cuenta según el mensaje recibido.
- 404: no se encontraron datos; no asumas que el vehículo no existe sin revisar el valor enviado.
- 429: respeta Retry-After y evita reintentos simultáneos.
- 502 o 503: usa espera progresiva con un número máximo de intentos.
Buenas prácticas para una integración vehicular
- Compara la placa devuelta con la solicitada antes de guardar el resultado.
- Tolera campos null y cambios no destructivos en la respuesta.
- Conserva la API key solo en el servidor y rótala si llega a exponerse.
- Consulta el precio vigente en la documentación antes de estimar costos por volumen.
Preguntas frecuentes
Respuestas rápidas sobre esta guía.