Conceptos
La API de Drometra es la misma que usan la consola y Dromivia: REST sobre HTTPS con JSON y el mismo modelo de permisos. Está en producción en https://api.drometra.com y la versión actual es la 0.4.0.
Hoy se entra con la sesión de una persona de tu empresa, con sus mismos permisos. Todavía no entregamos credenciales propias para que un sistema se conecte solo; si necesitas integrar uno, escríbenos y lo vemos contigo. Para recibir avisos en tu sistema ya puedes usar los webhooks.
Autenticación
Cada petición lleva un token de acceso OIDC emitido por auth.drometra.com en la cabecera Authorization, y la cabecera x-tenant-id con el identificador de tu empresa. En cada petición el servidor comprueba que la persona siga siendo miembro activo de esa empresa y con qué rol: lector, operador o administrador. Lo que diga el token sobre roles no da acceso por sí solo.
curl "https://api.drometra.com/v1/context" \
-H "Authorization: Bearer $DROMETRA_TOKEN" \
-H "x-tenant-id: $DROMETRA_TENANT"Las acciones sensibles, como configurar webhooks o leer la auditoría, piden un administrador con verificación en dos pasos. Un token nunca viaja en la URL.
Escrituras sin efectos dobles
Las operaciones que crean o cambian algo piden la cabecera idempotency-key con un UUID nuevo por operación. Si una petición se corta y la repites con la misma clave, el cambio no se aplica dos veces. La referencia marca en cada ruta las cabeceras que pide.
Paginación
Las listas largas se paginan por cursor y aceptan limit. Cada lista indica su parámetro de cursor (after, cursor o before) y la respuesta trae el de la página siguiente, que es null en la última. Si un cursor venció, vuelve a pedir desde la primera página.
Errores
Los errores responden con el código HTTP y un cuerpo con la misma forma siempre.
{
"error": "vehicle_unlinked",
"requestId": "6d1f0a2c-3b4e-4f5a-8c9d-0e1f2a3b4c5d",
"reason": "…"
}| Código | Qué significa |
|---|---|
| 400 | La petición no cumple el contrato: falta un campo, sobra uno o tiene otro formato. |
| 401 | Falta el token, expiró o no es válido. |
| 403 | El token es válido, pero tu rol en esa empresa no permite la acción, o pide verificación en dos pasos. |
| 404 | No existe, o existe fuera de tu empresa. Es la misma respuesta a propósito. |
| 409 | Choca con el estado actual de lo que intentas cambiar. |
| 410 | Lo que pediste ya no está disponible. |
| 413 | El cuerpo es demasiado grande. |
| 415 | El tipo de contenido no corresponde. |
| 422 | El formato está bien, pero el contenido no se puede aplicar. |
| 429 | Se superó un límite o una cuota. La cabecera retry-after dice cuántos segundos esperar. |
| 503 | Un servicio interno no está disponible por un momento. Reintenta con espera creciente. |
El campo error trae uno de estos 41 valores:
invalid_requestunauthorizedforbiddennot_foundconflictcursor_expiredsnapshot_quotastorage_quotarate_limitunavailablerouting_coverage_unavailablerouting_no_routerouting_capability_unsupportedrouting_concurrency_limitrouting_provider_unavailableoptimization_quotaoptimization_concurrency_limitoptimization_solver_unavailableintegration_provider_authentication_failedintegration_provider_instance_blockedintegration_provider_permission_deniedintegration_provider_rate_limitedintegration_provider_budget_exhaustedintegration_provider_concurrency_limiteddistribution_quotageocoding_concurrency_limitgeocoding_provider_unavailablefield_quotacapability_unavailableevidence_rejectedimport_rejectedexport_rejectedvehicle_unlinkedroute_closedwebhook_quotaverification_failednotification_quotareport_too_largeplace_quotamichiva_quotamichiva_unavailable
Incluye el requestId al reportar un problema: con él encontramos la petición exacta.
Límites y cuotas
Hay límites de uso por empresa y cuotas por función, como las de Michiva, el ruteo o las importaciones. Al superarlos la API responde 429 con la cabecera retry-after en segundos. Espera ese tiempo y reintenta con espera creciente.
Webhooks
Drometra le avisa a tu sistema con un POST HTTPS cuando ocurre algo en tu empresa, por ejemplo un pedido creado o una ruta iniciada. Los destinos los configura un administrador con verificación en dos pasos, y el formato es el de Standard Webhooks.
- Cada envío lleva
webhook-id(no cambia entre reintentos),webhook-timestampywebhook-signature, una firma HMAC SHA-256 del cuerpo tal cual llegó. - Responde 2xx en menos de 10 segundos. Si no, se reintenta 8 veces durante unas 28 horas.
- La entrega es al menos una vez y sin orden garantizado: deduplica por webhook-id.
- El secreto se muestra una sola vez y se puede rotar con hasta 7 días de gracia. Cada entrega queda 30 días en el registro.
- El destino tiene que ser un nombre público con HTTPS al puerto 443. Drometra no publica IPs fijas de salida: verifica la firma.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verificar(secreto, headers, cuerpoCrudo) {
const id = headers["webhook-id"], ts = headers["webhook-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // ±5 minutos
const clave = Buffer.from(secreto.replace(/^whsec_/, ""), "base64");
const esperada = createHmac("sha256", clave).update(`${id}.${ts}.${cuerpoCrudo}`).digest();
return headers["webhook-signature"].split(" ").some((parte) => {
const dada = Buffer.from(parte.replace(/^v1,/, ""), "base64");
return dada.length === esperada.length && timingSafeEqual(dada, esperada);
});
}Estado del servicio
GET /health/live y GET /health/ready responden sin sesión. El enlace de seguimiento que recibe un destinatario (/t/…) tampoco la pide.
Con esto ya puedes leer cualquier ruta de la referencia.
