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.

request
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 body
{
  "error": "vehicle_unlinked",
  "requestId": "6d1f0a2c-3b4e-4f5a-8c9d-0e1f2a3b4c5d",
  "reason": "…"
}
CodeWhat does it mean?
400The request doesn't meet the contract: a field is missing, there's an extra one or it has another format.
401The token is missing, expired or invalid.
403The token is valid, but your role in that company doesn't allow the action, or it requires two-step verification.
404It doesn't exist, or it exists outside your company. It's the same response on purpose.
409It conflicts with the current state of what you're trying to change.
410What you asked for is no longer available.
413The body is too large.
415The content type doesn't match.
422The format is fine, but the content can't be applied.
429A limit or quota was exceeded. The retry-after header says how many seconds to wait.
503An 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-timestamp and webhook-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.
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.