Concepts
The Drometra API is the same one the console and Dromivia use: REST over HTTPS with JSON and the same permission model. It is in production at https://api.drometra.com and the current version is 0.4.0.
Today you get in with the session of a person in your company, with their same permissions. We don't yet issue credentials for a system to connect on its own; if you need to integrate one, write to us and we'll work it out with you. To receive notifications in your system you can already use webhooks.
Authentication
Every request carries an OIDC access token issued by auth.drometra.com in the header Authorization, and the header x-tenant-id with your company's identifier. On every request the server checks that the person is still an active member of that company and with which role: reader, operator or administrator. What the token says about roles doesn't grant access on its own.
curl "https://api.drometra.com/v1/context" \
-H "Authorization: Bearer $DROMETRA_TOKEN" \
-H "x-tenant-id: $DROMETRA_TENANT"Sensitive actions, such as configuring webhooks or reading the audit log, require an administrator with two-step verification. A token never travels in the URL.
Writes without double effects
Operations that create or change something require the header idempotency-key with a new UUID per operation. If a request is cut off and you repeat it with the same key, the change is not applied twice. The reference marks the headers each route requires.
Pages
Long lists are paginated by cursor and accept limit. Each list states its cursor parameter (after, cursor or before) and the response includes the one for the next page, which is null on the last one. If a cursor expired, request again from the first page.
Errors
Errors respond with the HTTP status code and a body that always has the same shape.
{
"error": "vehicle_unlinked",
"requestId": "6d1f0a2c-3b4e-4f5a-8c9d-0e1f2a3b4c5d",
"reason": "…"
}| Code | What does it mean? |
|---|---|
| 400 | The request doesn't meet the contract: a field is missing, there's an extra one or it has another format. |
| 401 | The token is missing, expired or invalid. |
| 403 | The token is valid, but your role in that company doesn't allow the action, or it requires two-step verification. |
| 404 | It doesn't exist, or it exists outside your company. It's the same response on purpose. |
| 409 | It conflicts with the current state of what you're trying to change. |
| 410 | What you asked for is no longer available. |
| 413 | The body is too large. |
| 415 | The content type doesn't match. |
| 422 | The format is fine, but the content can't be applied. |
| 429 | A limit or quota was exceeded. The retry-after header says how many seconds to wait. |
| 503 | An internal service is briefly unavailable. Retry with increasing waits. |
The error field carries one of these 41 values:
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
Include the requestId when you report a problem: with it we find the exact request.
Limits and quotas
There are usage limits per company and quotas per function, such as Michiva, routing or imports. When you exceed them the API responds 429 with the header retry-after en segundos. Espera ese tiempo y reintenta con espera creciente.
Webhooks
Drometra notifies your system with an POST HTTPS when something happens in your company, for example an order is created or a route starts. Destinations are configured by an administrator with two-step verification, and the format is Standard Webhooks.
- Each delivery carries
webhook-id(it does not change between retries),webhook-timestampandwebhook-signature, an HMAC SHA-256 signature of the body exactly as it arrived. - Respond with 2xx in under 10 seconds. Otherwise it is retried 8 times over about 28 hours.
- Delivery is at least once and without guaranteed order: deduplicate by webhook-id.
- The secret is shown only once and can be rotated with up to 7 days of grace. Each delivery stays in the log for 30 days.
- The destination must be a public name with HTTPS on port 443. Drometra doesn't publish fixed outbound IPs: verify the signature.
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);
});
}Service status
GET /health/live and GET /health/ready respond without a session. The tracking link a recipient receives (/t/…) doesn't require one either.
With this you can now read any route in the reference.
