Ingesta de combustible
Registra las cargas de combustible de la flota. El endpoint es genérico: no
asume ningún proveedor de tarjetas. Cualquier cliente, con cualquier sistema de
control de combustible, escribe acá — el proveedor entra como el valor del
campo source_system.
Sobre estos datos corren las reglas de alerta de consumo (rendimiento fuera de rango, carga mayor que el tanque, odómetro incoherente y carga fuera de horario).
Ingesta idempotente de transacciones de combustible, en lotes de hasta 500.
Caso de uso
Un sistema externo lee periódicamente las transacciones de su proveedor de
combustible, las normaliza a esta forma y las envía. Reenviar el mismo rango
no duplica: la llave de idempotencia es (tenant, source_system, source_id).
Campos del payload
Raíz
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
source_system | string (≤30) | sí | Sistema de origen. Se normaliza a minúsculas. |
transactions | array | sí | Entre 1 y 500 ítems. Más de 500 → 400. |
Cada transacción
Requeridos
| Campo | Tipo | Descripción |
|---|---|---|
source_id | string (≤128) | Identificador estable de la transacción en el sistema de origen. Es la llave de idempotencia. |
plate | string (≤20) | Placa del vehículo. Se normaliza a mayúsculas y sin espacios ni guiones: pb-0001, PB 0001 y PB0001 ligan al mismo vehículo. |
occurred_at | string ISO 8601 | Fecha y hora de la carga con offset UTC explícito (Z o ±HH:MM). Sin offset → 400. |
volume_liters | number | Litros cargados. Debe ser mayor que 0. |
raw_payload | object | Registro original del sistema de origen, para trazabilidad. |
Opcionales
| Campo | Tipo | Descripción |
|---|---|---|
unit_price | number | Precio por litro |
amount | number | Monto total |
product_name | string (≤60) | Producto (DIESEL, SUPER, …) |
odometer_reported | number | Odómetro reportado en el surtidor |
station_name | string (≤120) | Estación de servicio |
station_address | string (≤255) | Dirección de la estación (texto) |
driver_name_reported | string (≤120) | Nombre del conductor según el origen. No es una referencia al catálogo de conductores. |
card_number_masked | string (≤30) | Número de tarjeta ya enmascarado |
Dato personal: no envíes documentos de identidad. Si el campo
CITIZEN_IDviene dentro deraw_payload, Smartfleet lo descarta — no se guarda en ninguna columna ni dentro del payload crudo.
Respuesta — los cuatro contadores
Los cuatro son disjuntos y suman received.
| Contador | Significado |
|---|---|
received | Ítems recibidos en el lote. |
inserted | Transacciones nuevas que se ligaron a un vehículo por placa. |
duplicates | Ítems cuyo source_id ya existía para ese source_system. No es un error: se cuenta y se sigue. |
quarantined | Transacciones nuevas cuya placa no coincide con ningún vehículo. No se pierden: se guardan con el vehículo vacío y se pueden religar después. |
Request
{
"source_system": "fleetmagic",
"transactions": [
{
"source_id": "a3f1c8e2b7d9",
"plate": "PB0001",
"occurred_at": "2026-08-12T16:07:07-06:00",
"volume_liters": 20.0,
"unit_price": 2.0,
"amount": 40.0,
"product_name": "DIESEL",
"odometer_reported": 15000,
"station_name": "ESTACION 1",
"station_address": "DIRECCION",
"driver_name_reported": "CONDUCTOR 1",
"raw_payload": { "REFERENCE": "000123456" }
}
]
}Response
{
"ok": true,
"code": "SYNC_OK",
"message": "Sync processed successfully.",
"data": {
"received": 50,
"inserted": 47,
"duplicates": 2,
"quarantined": 1
},
"meta": {
"route": "/transportes/sync/fuel-transactions",
"method": "PostFuelTransactionsSync",
"operation": "ingest",
"source_system": "fleetmagic"
}
}Reenvío del mismo lote (idempotencia)
{
"received": 50,
"inserted": 0,
"duplicates": 50,
"quarantined": 0
}Errores
Todos los errores de validación abortan el lote entero — no hay ingesta parcial.
| Situación | Respuesta |
|---|---|
volume_liters menor o igual que 0 | 400 CAPTURED_ERROR: Validation error: … |
source_id ausente o vacío | 400 CAPTURED_ERROR: Validation error: … |
occurred_at sin offset UTC | 400 CAPTURED_ERROR: Validation error: … (tenant timezone is '…') |
occurred_at con una fecha que no existe (2026-13-45T…, 2026-02-31T…) | 400 CAPTURED_ERROR: Validation error: occurred_at is not a real calendar date-time. |
Un numérico que no cabe en la columna (odometer_reported de 15 dígitos) | 400 CAPTURED_ERROR: Validation error: … |
raw_payload ausente | 400 CAPTURED_ERROR: Validation error: … |
| Más de 500 transacciones | 400 CAPTURED_ERROR: Validation error: … |
Un lote con muchos ítems inválidos devuelve los primeros 20 problemas y un
contador del resto (… (+380 more)): el mensaje está acotado a propósito para
que la respuesta siga siendo un 400 legible.
El mensaje de occurred_at incluye la zona horaria configurada del cliente:
es la zona con la que hay que estampar el offset cuando el sistema de origen
reporta la fecha y la hora por separado y sin zona.
Cuarentena
Una transacción cuya placa no existe en el catálogo de vehículos no se
rechaza y no se pierde: se guarda con el vehículo vacío y marcada como
unmatched_vehicle, con la placa tal cual llegó. Al dar de alta el vehículo con
esa placa, esas transacciones se pueden religar.
Perder consumo real es peor que guardar un registro huérfano.
Reglas de alerta que corren sobre estos datos
Se configuran como cualquier otra regla del motor de alertas (tipo de regla + parámetros + destinatarios). Ninguna nombra a un proveedor.
| Tipo de regla | Dispara cuando | Parámetros |
|---|---|---|
FUEL_EFFICIENCY_OUT_OF_RANGE | El km/l de una carga se desvía del baseline del vehículo (mediana de sus cargas previas) más que la tolerancia | min_samples (5), tolerance_pct (30) |
FUEL_VOLUME_EXCEEDS_TANK | Los litros cargados superan la capacidad del tanque más el margen. Los vehículos sin capacidad cargada se omiten | margin_pct (5) |
FUEL_ODOMETER_INCONSISTENT | El odómetro retrocede, salta más de lo posible, o no avanza entre dos cargas | max_km_jump (2000) |
FUEL_TRANSACTION_OFF_HOURS | La carga ocurre fuera de la jornada, en la hora local del cliente. La ventana puede cruzar la medianoche (turno nocturno) | start_hour (6), end_hour (18), weekend_is_off (true) |
La regla de rendimiento evalúa todas las cargas de la ventana, no sólo la última: una carga anómala seguida de una normal igual genera su alerta.