Saltar al contenido
FlotaDoc

API para integraciones

Viajes

Viajes de trabajo de los conductores (libro de viajes).

En esta página

Lista los viajes (libro o sincronización incremental)

POST/movimientos/viajes/list

  • Permiso lectura

Devuelve los viajes de la empresa. Tiene dos modos.

Libro (sin updatedSince ni cursor): las líneas activas (sin anuladas ni descartadas), en orden cronológico: día (tripDate), hora de inicio (los registrados a mano, sin hora, van después de los iniciados ese día) y orden de alta (tripId). order: "desc" es el reverso exacto de asc. limit (1-500) recorta la serie y, sin él, vienen todas: { "order": "desc", "limit": 1 } es el último viaje. Para el libro de un mes, from y to (incluidos). La respuesta solo trae trips.

Sincronización incremental (con updatedSince o cursor): todo lo que cambió, también los viajes anulados y descartados (active: false) y los que están en curso, en orden de cambio (updatedAt, tripId) y por páginas (limit 1-200, por defecto 200). order no se admite.

  1. Primera página: { "updatedSince": "2026-10-13T08:00:00Z" } más los filtros que quieras. Entrega los viajes cuyo updatedAt es posterior a updatedSince (exclusivo) y como mucho igual a syncedUntil, que fija esta primera página: la hora de la base de datos menos 60 s, o updatedSince si es posterior (nunca hacia atrás).
  2. Siguientes páginas, mientras nextCursor no sea null: el mismo cuerpo con "cursor": "<nextCursor>". El cursor es opaco, manda sobre updatedSince (que puedes volver a mandar o quitar) y lleva el mismo syncedUntil. Repite los filtros en cada página: el cursor no los guarda.
  3. Al acabar (nextCursor: null): guarda syncedUntil tal cual (UTC con microsegundos) y empieza la siguiente sincronización con { "updatedSince": "<syncedUntil>" }. Usa syncedUntil, no el mayor updatedAt que hayas visto (updatedAt va en milisegundos).

Dentro de un recorrido no hay duplicados ni huecos: un viaje que cambia mientras recorres las páginas queda fuera de ese syncedUntil y llega en la siguiente sincronización. Un cambio tarda como poco 60 s en aparecer; lo que registra tu propia integración ya lo tienes en la respuesta de viajes/save.

updatedAt cambia con cualquier escritura de la fila: alta, corrección, anulación, descarte, fin, firma del cliente, consumo o recorrido GPS. No cambia por el coste derivado (depende de los gastos y las lecturas del mes), ni por el nombre del conductor, la matrícula o el nombre de la categoría: si necesitas esas cifras al día, vuelve a pedir el mes en modo libro con from/to. Los viajes que la retención fiscal purga (más de 4 años) no se anuncian.

Filtros (en los dos modos; se combinan): from y to (YYYY-MM-DD, incluidos, from ≤ to), userId (conductor), vehicleId y status. Un userId o vehicleId que no es de tu empresa da lista vacía, nunca 404.

Con clave API se ve toda la empresa (la clave actúa como el owner que la creó). Cada viaje es un ViajesTrip con su coste y su semáforo calculados en el momento de la lectura y con apiKeyId (la clave con la que se dio de alta, o null si lo registró una persona). La lista no trae attendedByName ni signedAt (solo hasSignature): pídelos con viajes/get.

Errores propios

  • 422 invalid_input: error.fields trae todos los campos erróneos a la vez. invalid en from, to (también si es anterior a from), userId, vehicleId, status, limit (fuera de 1-500, o de 1-200 al sincronizar), order (cualquier valor al sincronizar), updatedSince (sin zona horaria, fecha imposible o anterior a 1970) y cursor (no lo emitió el servidor); unexpected_field en cualquier otra clave. Sin fields si el cuerpo no es un objeto JSON.

Petición

Cuerpo opcional

Opcional. Sin cuerpo equivale a {} (el libro entero de la empresa).

Todo opcional. Con updatedSince o cursor es una sincronización incremental.

  • fromstring (date) | null

    Desde este día (YYYY-MM-DD, incluido).

  • tostring (date) | null

    Hasta este día (YYYY-MM-DD, incluido). No anterior a from.

  • userIdinteger | string | null

    Solo los viajes de este conductor.

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • vehicleIdinteger | string | null

    Solo los viajes de este vehículo.

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • statusstring | null

    Solo los viajes en este estado.

    recorded: registrado a mano a posteriori (web, app o API). in_progress: iniciado en la app y aún sin finalizar. finished: iniciado y finalizado en la app.

    Valores: recorded in_progress finished

  • orderstring | null

    Solo en modo libro (con updatedSince o cursor, cualquier valor es invalid).

    Valores: asc descPor defecto: asc

  • limitinteger | null

    Modo libro: 1-500; sin él, todas. Sincronización: 1-200, por defecto 200.

    Mínimo 1Máximo 500

  • updatedSincestring | null

    Empieza una sincronización: viajes con updatedAt posterior a este instante. ISO 8601 con zona (Z o ±hh:mm); segundos opcionales y hasta 6 decimales; desde 1970. Ejemplos: 2026-10-13T08:00:00Z, 2026-10-13T10:00+02:00, el syncedUntil de la sincronización anterior.

    Patrón: ^\d{4}-\d{2}-\d{2}T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{1,6})?)?(Z|[+-](0\d|1[0-4]):[0-5]\d)$

  • cursorstring | null

    El nextCursor de la página anterior, tal cual (opaco). Manda sobre updatedSince.

    De 1 a 200 caracteresPatrón: ^[A-Za-z0-9_-]+$

Ejemplo: Libro de octubre de un vehículo

curl -sS -X POST "https://app.flotadoc.com/api/movimientos/viajes/list" \
  -H "Authorization: Bearer $FLOTADOC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "2026-10-01",
    "to": "2026-10-31",
    "vehicleId": 7
  }'
Otro ejemplo: Último viaje de un conductor
{
  "userId": 15,
  "order": "desc",
  "limit": 1
}
Otro ejemplo: Sincronización, primera página
{
  "updatedSince": "2026-10-13T08:00:00Z",
  "limit": 200
}
Otro ejemplo: Sincronización, página siguiente
{
  "limit": 200,
  "cursor": "eyJ2IjoxLCJ1IjoiMjAyNi0xMC0xM1QwOTo1ODo0MS4wMDQxMTJaIiwidCI6IjIwMjYtMTAtMTNUMDk6MTI6MDMuNTEyMzMxWiIsImkiOjQxMn0"
}

Respuesta

200

Viajes del filtro. En modo libro solo trips; en una sincronización, además nextCursor y syncedUntil.

Cabeceras

  • X-Request-Idstring (uuid)

    Id de la petición en el historial de la empresa (para soporte).

  • dataobject
    • tripsViajesTrip[]

      Un viaje con su coste y su semáforo, calculados en el momento de la lectura.

    • nextCursorstring | nullopcional

      Solo en una sincronización. Cursor de la página siguiente; null si no hay más.

    • syncedUntilstringopcional

      Solo en una sincronización. Hasta dónde llega este recorrido (UTC con microsegundos, el mismo en todas sus páginas). Al acabar, es el updatedSince de la siguiente sincronización.

      Patrón: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z$

Ejemplo de respuesta: Modo libro
{
  "data": {
    "trips": [
      {
        "tripId": 398,
        "tenantId": 42,
        "userId": 18,
        "userName": "Iván Comercial",
        "vehicleId": 7,
        "vehiclePlate": "1234ABC",
        "status": "finished",
        "tripDate": "2026-10-08",
        "startedAt": "2026-10-08T07:05:12.318Z",
        "endedAt": "2026-10-08T07:41:55.902Z",
        "origin": "Polígono Cantabria, Logroño",
        "destination": "Calle Portales 20, Logroño",
        "originLat": 42.481203,
        "originLng": -2.462011,
        "originAccuracyM": 8,
        "destinationLat": 42.466517,
        "destinationLng": -2.44538,
        "destinationAccuracyM": 12.5,
        "distanceKm": 25.1,
        "routeKm": 24.6,
        "routeDurationMin": 31,
        "odometerKm": 48210,
        "reason": "Visita comercial a Distribuciones Ebro",
        "reasonCategoryId": 1,
        "reasonCategoryName": "Visita a cliente",
        "costBasis": "fuel",
        "kmRate": null,
        "amount": null,
        "consumptionL100km": 6.2,
        "trackKm": 25.4,
        "trackGapKm": 0,
        "hasSignature": true,
        "correctedAt": null,
        "active": true,
        "updatedAt": "2026-10-08T07:45:02.114Z",
        "apiKeyId": null,
        "cost": 3.87,
        "costKind": "justified",
        "costPending": null,
        "provisionalCost": null,
        "justifiedAmount": 3.87,
        "monthTicketsAmount": 186.4,
        "monthOdometerKm": 1210,
        "monthShareKm": 1210,
        "estimatedLiters": 1.56,
        "consumptionCost": 2.43,
        "fuelPricePerLiter": 1.559,
        "fuelPriceSource": "month",
        "fuelPriceTicketDate": null,
        "alertLevel": "ok",
        "alertReasons": []
      }
    ]
  }
}
Ejemplo de respuesta: Sincronización con más páginas
{
  "data": {
    "trips": [
      {
        "tripId": 412,
        "tenantId": 42,
        "userId": 15,
        "userName": "Bea Conductora",
        "vehicleId": 9,
        "vehiclePlate": "5678DEF",
        "status": "recorded",
        "tripDate": "2026-10-09",
        "startedAt": null,
        "endedAt": null,
        "origin": "Calle Mayor 1, Logroño",
        "destination": "Polígono Cantabria, Logroño",
        "originLat": null,
        "originLng": null,
        "originAccuracyM": null,
        "destinationLat": null,
        "destinationLng": null,
        "destinationAccuracyM": null,
        "distanceKm": 7.4,
        "routeKm": null,
        "routeDurationMin": null,
        "odometerKm": null,
        "reason": "Revisión de la instalación del cliente",
        "reasonCategoryId": 3,
        "reasonCategoryName": "Servicio técnico o instalación",
        "costBasis": "km_rate",
        "kmRate": 0.26,
        "amount": 1.92,
        "consumptionL100km": null,
        "trackKm": null,
        "trackGapKm": null,
        "hasSignature": false,
        "correctedAt": null,
        "active": false,
        "updatedAt": "2026-10-13T09:12:03.512Z",
        "apiKeyId": 5,
        "cost": 1.92,
        "costKind": "allowance",
        "costPending": null,
        "provisionalCost": null,
        "justifiedAmount": null,
        "monthTicketsAmount": null,
        "monthOdometerKm": null,
        "monthShareKm": null,
        "estimatedLiters": null,
        "consumptionCost": null,
        "fuelPricePerLiter": null,
        "fuelPriceSource": null,
        "fuelPriceTicketDate": null,
        "alertLevel": "warn",
        "alertReasons": [
          "manual"
        ]
      }
    ],
    "nextCursor": "eyJ2IjoxLCJ1IjoiMjAyNi0xMC0xM1QwOTo1ODo0MS4wMDQxMTJaIiwidCI6IjIwMjYtMTAtMTNUMDk6MTI6MDMuNTEyMzMxWiIsImkiOjQxMn0",
    "syncedUntil": "2026-10-13T09:58:41.004112Z"
  }
}

Además, las respuestas comunes: 401, 403, 404, 422, 429, 503.

Ficha de un viaje

POST/movimientos/viajes/get

  • Permiso lectura

Ficha de un viaje activo de la empresa: el viaje completo con attendedByName y signedAt (firma del cliente), el coste y el semáforo calculados en el momento, y integration: la clave API con la que se dio de alta (apiKeyId, nombre y prefijo visible, también si la clave ya está revocada) o null si lo registró una persona. Si el nombre de la clave no se puede leer, integration llega con name y prefix a null y la ficha sale igual.

Un viaje anulado o descartado responde 404: su historial sigue en viajes/history y la sincronización de viajes/list lo entrega con active: false.

Errores propios

  • 404 trip_not_found: no existe, es de otra empresa o está anulado o descartado.
  • 422 invalid_input: fields.tripId = required o invalid; cualquier otra clave, unexpected_field.

Petición

Cuerpo obligatorio

  • tripIdinteger | stringobligatorio

    Identificador. Entero positivo; también se admite como texto de dígitos ("412").

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

Ejemplo

curl -sS -X POST "https://app.flotadoc.com/api/movimientos/viajes/get" \
  -H "Authorization: Bearer $FLOTADOC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tripId": 412
  }'

Respuesta

200

La ficha del viaje.

Cabeceras

  • X-Request-Idstring (uuid)

    Id de la petición en el historial de la empresa (para soporte).

  • dataobject
    • tripobject

      Incluye todos los campos de ViajesTripDetail.

      • integrationViajesIntegration | null

        Clave API con la que se dio de alta el viaje (también si ya está revocada), o null si lo registró una persona. name y prefix son null si no se pudieron leer.

Ejemplo de respuesta
{
  "data": {
    "trip": {
      "tripId": 412,
      "tenantId": 42,
      "userId": 15,
      "userName": "Bea Conductora",
      "vehicleId": 9,
      "vehiclePlate": "5678DEF",
      "status": "recorded",
      "tripDate": "2026-10-09",
      "startedAt": null,
      "endedAt": null,
      "origin": "Calle Mayor 1, Logroño",
      "destination": "Polígono Cantabria, Logroño",
      "originLat": null,
      "originLng": null,
      "originAccuracyM": null,
      "destinationLat": null,
      "destinationLng": null,
      "destinationAccuracyM": null,
      "distanceKm": 7.4,
      "routeKm": null,
      "routeDurationMin": null,
      "odometerKm": null,
      "reason": "Revisión de la instalación del cliente",
      "reasonCategoryId": 3,
      "reasonCategoryName": "Servicio técnico o instalación",
      "costBasis": "km_rate",
      "kmRate": 0.26,
      "amount": 1.92,
      "consumptionL100km": null,
      "trackKm": null,
      "trackGapKm": null,
      "hasSignature": false,
      "correctedAt": null,
      "active": true,
      "updatedAt": "2026-10-09T16:20:11.482Z",
      "apiKeyId": 5,
      "cost": 1.92,
      "costKind": "allowance",
      "costPending": null,
      "provisionalCost": null,
      "justifiedAmount": null,
      "monthTicketsAmount": null,
      "monthOdometerKm": null,
      "monthShareKm": null,
      "estimatedLiters": null,
      "consumptionCost": null,
      "fuelPricePerLiter": null,
      "fuelPriceSource": null,
      "fuelPriceTicketDate": null,
      "alertLevel": "warn",
      "alertReasons": [
        "manual"
      ],
      "attendedByName": null,
      "signedAt": null,
      "integration": {
        "apiKeyId": 5,
        "name": "ERP Contabilidad",
        "prefix": "fd_live_Ab12"
      }
    }
  }
}

Además, las respuestas comunes: 401, 403, 404, 422, 429, 503.

Historial de versiones de un viaje

POST/movimientos/viajes/history

  • Permiso lectura

Versiones selladas de un viaje cuando la empresa tiene activados los registros inalterables: alta (create, también al finalizar un viaje iniciado en la app), correcciones (correct, también de la firma del cliente), anulación (void) y versiones técnicas del recorrido GPS (technical: puntos que llegaron tarde; sin autor, sin motivo y sin instantánea). Cada versión trae quién y cuándo, el motivo del cambio, la instantánea fiscal después del cambio, las huellas de sus ficheros (firma y recorrido), qué campos de la instantánea cambiaron respecto a la anterior y su huella en la cadena (entryHash).

Alcanza también un viaje anulado o descartado. versions es [] si el viaje es anterior a la activación, si la empresa no tiene el ajuste o si el viaje no ha llegado al libro (en curso o descartado). Como mucho 500 versiones por viaje, de la primera a la última.

integration es la de viajes/get. El alta que hace una integración la firma (author) el owner que creó la clave.

Una versión con redacted: true ha perdido su contenido o no se entiende: es una alteración, y movimientos/integridad/verify da la cadena por rota.

Errores propios

  • 404 trip_not_found: no existe o es de otra empresa.
  • 422 invalid_input: fields.tripId = required o invalid; cualquier otra clave, unexpected_field.

Petición

Cuerpo obligatorio

  • tripIdinteger | stringobligatorio

    Identificador. Entero positivo; también se admite como texto de dígitos ("412").

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

Ejemplo

curl -sS -X POST "https://app.flotadoc.com/api/movimientos/viajes/history" \
  -H "Authorization: Bearer $FLOTADOC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tripId": 412
  }'

Respuesta

200

Las versiones del viaje, de la primera a la última.

Cabeceras

  • X-Request-Idstring (uuid)

    Id de la petición en el historial de la empresa (para soporte).

  • dataobject
    • tripIdinteger

      Mínimo 1

    • integrationViajesIntegration | null

      Clave API con la que se dio de alta el viaje (también si ya está revocada), o null si lo registró una persona. name y prefix son null si no se pudieron leer.

    • Hasta 500 elementos

Ejemplo de respuesta
{
  "data": {
    "tripId": 412,
    "integration": {
      "apiKeyId": 5,
      "name": "ERP Contabilidad",
      "prefix": "fd_live_Ab12"
    },
    "versions": [
      {
        "seq": 141,
        "version": 1,
        "change": "create",
        "author": {
          "userId": 3,
          "name": "Marta Titular"
        },
        "recordedAt": "2026-10-09T16:20:11.482Z",
        "reason": null,
        "snapshot": {
          "status": "recorded",
          "tripDate": "2026-10-09",
          "userId": 15,
          "vehicleId": 9,
          "startedAt": null,
          "endedAt": null,
          "origin": "Calle Mayor 1, Logroño",
          "originLat": null,
          "originLng": null,
          "destination": "Polígono Cantabria, Logroño",
          "destinationLat": null,
          "destinationLng": null,
          "distanceKm": 7.4,
          "odometerKm": null,
          "reason": "Revisión de la instalación del cliente",
          "reasonCategory": "Servicio técnico o instalación",
          "costBasis": "km_rate",
          "kmRate": 0.26,
          "amount": 1.92,
          "attendedByName": null,
          "signedAt": null,
          "signatureSha256": null
        },
        "files": [],
        "changed": [],
        "entryHash": "1b7d0c9e5a3f4b2d8e6c1a0f9b8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e",
        "redacted": false
      },
      {
        "seq": 187,
        "version": 2,
        "change": "void",
        "author": {
          "userId": 3,
          "name": "Marta Titular"
        },
        "recordedAt": "2026-10-13T09:12:03.512Z",
        "reason": "Viaje duplicado en el ERP",
        "snapshot": {
          "status": "recorded",
          "tripDate": "2026-10-09",
          "userId": 15,
          "vehicleId": 9,
          "startedAt": null,
          "endedAt": null,
          "origin": "Calle Mayor 1, Logroño",
          "originLat": null,
          "originLng": null,
          "destination": "Polígono Cantabria, Logroño",
          "destinationLat": null,
          "destinationLng": null,
          "distanceKm": 7.4,
          "odometerKm": null,
          "reason": "Revisión de la instalación del cliente",
          "reasonCategory": "Servicio técnico o instalación",
          "costBasis": "km_rate",
          "kmRate": 0.26,
          "amount": 1.92,
          "attendedByName": null,
          "signedAt": null,
          "signatureSha256": null
        },
        "files": [],
        "changed": [],
        "entryHash": "77a04c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b",
        "redacted": false
      }
    ]
  }
}

Además, las respuestas comunes: 401, 403, 404, 422, 429, 503.

Lista las categorías de motivo

POST/movimientos/viajes/reasons-list

  • Permiso lectura

Categorías activas del catálogo de motivos de la empresa, en orden de alta (las seis por defecto, primero). Sirven para reasonCategoryId en viajes/save: el motivo del viaje (reason) es siempre un texto libre obligatorio y la categoría es opcional.

Si la empresa aún no tiene ninguna categoría (ni activa ni borrada), la primera consulta crea las seis por defecto (isDefault: true): Visita a cliente, Reunión, Servicio técnico o instalación, Compra de material, Gestión administrativa y Formación. Una categoría por defecto renombrada sigue siendo isDefault. El catálogo lo mantiene el owner en la web; no se edita por la API.

Errores propios

  • 422 invalid_input: cualquier clave del cuerpo es unexpected_field.

Petición

Cuerpo opcional

Opcional. Sin cuerpo equivale a {}.

object

Ejemplo

curl -sS -X POST "https://app.flotadoc.com/api/movimientos/viajes/reasons-list" \
  -H "Authorization: Bearer $FLOTADOC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Respuesta

200

Las categorías activas.

Cabeceras

  • X-Request-Idstring (uuid)

    Id de la petición en el historial de la empresa (para soporte).

Ejemplo de respuesta
{
  "data": {
    "reasonCategories": [
      {
        "reasonCategoryId": 1,
        "name": "Visita a cliente",
        "isDefault": true,
        "updatedAt": "2026-10-06T10:00:00.000Z"
      },
      {
        "reasonCategoryId": 2,
        "name": "Reunión",
        "isDefault": true,
        "updatedAt": "2026-10-06T10:00:00.000Z"
      },
      {
        "reasonCategoryId": 3,
        "name": "Servicio técnico o instalación",
        "isDefault": true,
        "updatedAt": "2026-10-06T10:00:00.000Z"
      },
      {
        "reasonCategoryId": 4,
        "name": "Compra de material",
        "isDefault": true,
        "updatedAt": "2026-10-06T10:00:00.000Z"
      },
      {
        "reasonCategoryId": 5,
        "name": "Gestión administrativa",
        "isDefault": true,
        "updatedAt": "2026-10-06T10:00:00.000Z"
      },
      {
        "reasonCategoryId": 6,
        "name": "Formación",
        "isDefault": true,
        "updatedAt": "2026-10-06T10:00:00.000Z"
      },
      {
        "reasonCategoryId": 9,
        "name": "Entrega de pedidos",
        "isDefault": false,
        "updatedAt": "2026-10-07T12:31:44.208Z"
      }
    ]
  }
}

Además, las respuestas comunes: 401, 403, 404, 422, 429, 503.

Registra un viaje para un conductor o corrige uno

POST/movimientos/viajes/save

  • Permiso registros
  • Admite Idempotency-Key

Alta (sin tripId) de un viaje ya hecho, a nombre de un conductor, o corrección completa (con tripId) de una línea del libro. Responde 200 con el viaje tal como ha quedado, con su coste y su semáforo.

Alta con clave API

  • driverUserId es obligatorio: el conductor a cuyo nombre queda el viaje (userId de la respuesta). Tiene que ser un conductor de la empresa: rol user u owner (también un invitado que aún no ha entrado), no desactivado; un gestor no conduce. Puede ser el propio owner que creó la clave.
  • vehicleId: un vehículo activo de la empresa (404 vehicle_not_found si no existe, es de otra empresa o está de baja) que el conductor pueda usar con sus reglas: un user, los vehículos variables y los fijos donde figura como conductor; un owner, todos (si no, 422 fields.driverUserId: vehicle_not_allowed).
  • Nace con status: recorded (registrado a mano: aviso manual del semáforo), sin horas de inicio ni fin, y guarda la clave (apiKeyId): la web lo muestra como «Registrado por la integración «nombre»». El autor del sello de integridad y de la auditoría es el owner de la clave.

Km, tarifa e importe (los fija el servidor; no se mandan):

  • distanceKm son los km declarados: el dato fiscal. routeKm/routeDurationMin (ruta estimada) solo lo respaldan; si los declarados se desvían más de un 25 % de routeKm, el semáforo avisa (route_deviation).
  • costBasis se copia del régimen del vehículo: propio → km_rate; de empresa → fuel.
  • km_rate: kmRate se copia de la tarifa por km de la empresa en la misma escritura y amount = ROUND(distanceKm × kmRate, 2) lo calcula la base de datos. cost = amount.
  • fuel: sin tarifa ni importe (kmRate y amount null). cost es la parte justificada de los tickets de energía del mes del vehículo (monthTicketsAmount × distanceKm ÷ monthShareKm), calculada al leer; queda pendiente mientras falte la lectura del cuentakilómetros del mes o no cuadre. consumptionL100km solo se guarda en fuel (en km_rate se ignora).

Corrección (con tripId), como el owner en la web:

  • Reemplaza todos los campos editables: los opcionales ausentes o null se guardan vacíos, salvo consumptionL100km (ausente conserva el que tenga; null lo quita). Lee antes el viaje con viajes/get y manda el conjunto completo.
  • No cambian nunca el conductor (si mandas driverUserId, tiene que ser el que ya tiene: si no, 422 immutable), el estado, las horas de inicio y fin ni el origen de la línea (apiKeyId). En un viaje finished (iniciado y finalizado en la app), tripDate y las coordenadas son evidencia: se ignoran los del cuerpo.
  • Un vehículo distinto tiene que ser un vehículo activo de la empresa (404 vehicle_not_found); su régimen pasa a ser la base de coste. Si el vehículo no cambia, la línea conserva su base y su tarifa aunque después hayan cambiado el régimen del vehículo o la tarifa de la empresa. El vehículo nuevo lo tiene que poder usar el conductor de la línea con sus reglas, como en el alta (un user, los variables y los fijos donde conduce; un owner, todos): si no, 422 fields.vehicleId: vehicle_not_allowed, sin cambiar nada.
  • La categoría que el viaje ya tenía vale aunque se haya borrado del catálogo; una nueva tiene que estar activa.
  • Si cambia un dato fiscal (día, vehículo, origen, destino, km, motivo o categoría), correctedAt pasa a ser ahora (aviso corrected).
  • Un viaje en curso no se corrige (409 trip_in_progress): lo finaliza o lo descarta el conductor en la app.

Mes cerrado. Un alta no entra en un mes cerrado del vehículo, y una corrección no sale del mes cerrado de la línea ni entra en otro (vehículo y día de destino): 409 period_closed con error.periods = [{ "vehicleId": 7, "month": "2026-09" }]. Hay que reabrir el mes en la web (movimientos/cierres).

Registros inalterables. Si la empresa los tiene activados, el alta sella una versión create y la corrección una correct, que exige changeReason (422 reason_required, sin escribir nada). Sin el ajuste, changeReason se acepta y no se guarda: mándalo siempre al corregir.

Cuenta en solo lectura. Con la prueba o el contrato vencidos, la cuenta pendiente del primer pago, suspendida o cancelada: 423 account_read_only (error.reason: account, pending_payment o suspended).

Idempotencia. Manda una Idempotency-Key distinta por cada viaje que registras (por ejemplo, el id del viaje en tu sistema): un reintento por un corte de red no duplica el viaje. Cualquier respuesta que no sea 5xx (también un 409 o un 422) queda guardada 24 h con esa clave y se repite tal cual: después de corregir el problema (reabrir el mes, arreglar un campo), reintenta con otra Idempotency-Key.

Orden de comprobaciones: puerta de la API → cuerpo objeto JSON (422) → cuenta que escribe (423) → campos (422 invalid_input) → alta: driverUserId presente (422), vehículo (404), conductor (422 not_found / vehicle_not_allowed), categoría (404), mes cerrado (409) · corrección: viaje (404), en curso (409), conductor (422 immutable), vehículo nuevo (404 y 422 vehicle_not_allowed), categoría nueva (404), mes cerrado (409) y, si se puede escribir, motivo con registros inalterables (422 reason_required).

Errores propios

  • 404 trip_not_found: corrección de un viaje que no existe, es de otra empresa o está anulado o descartado.
  • 404 vehicle_not_found: el vehículo no existe, es de otra empresa o está de baja.
  • 404 reason_category_not_found: la categoría no existe, es de otra empresa o está borrada (salvo la que el viaje ya tenía).
  • 409 trip_in_progress: corrección de un viaje en curso.
  • 409 period_closed: mes cerrado del vehículo; los meses en error.periods.
  • 422 invalid_input: error.fields con todos los campos erróneos: required, invalid, too_long, in_future (tripDate posterior a hoy en Madrid) o unexpected_field (una clave que no admite, p. ej. userId, kmRate, amount, costBasis, status o apiKeyId). Para driverUserId, además, y en solitario: required (alta sin él), not_found (no es conductor activo de la empresa), vehicle_not_allowed (no puede usar ese vehículo) e immutable (corrección con otro conductor). Para vehicleId, en solitario: vehicle_not_allowed (corrección a un vehículo que el conductor de la línea no puede usar).
  • 422 reason_required: corrección con registros inalterables activos y sin changeReason.
  • 423 account_read_only: la cuenta no admite registros (error.reason).

Petición

Cabeceras

  • Idempotency-Keystring

    Clave de idempotencia de la escritura (opcional, recomendada). Vale 24 horas por clave API: la misma Idempotency-Key con la misma ruta y el mismo cuerpo exacto devuelve la respuesta guardada con Idempotent-Replayed: true sin volver a ejecutar la operación. Con otro cuerpo u otra ruta: 409 idempotency_conflict; si la primera aún está en curso: 409 idempotency_in_progress. Una respuesta 5xx no se guarda (se puede reintentar). Mal formada: 422 invalid_idempotency_key.

    Patrón: ^[A-Za-z0-9_-]{1,100}$

Cuerpo obligatorio

Sin tripId: alta (con clave API, driverUserId obligatorio). Con tripId: corrección completa (los opcionales ausentes o null se guardan vacíos, salvo consumptionL100km). Los textos se recortan; los números van como número JSON ("12.5" no vale) y los ids admiten también texto de dígitos.

  • tripIdinteger | string | null

    Ausente o null, alta. Un id, corrección de ese viaje.

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • driverUserIdinteger | string | null

    Conductor del viaje: user u owner activo (o invitado) de la empresa que pueda usar vehicleId. Obligatorio en un alta con clave API. En una corrección es opcional y, si llega, tiene que ser el conductor que ya tiene el viaje (immutable).

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • tripDatestring (date)obligatorio

    Día del viaje (YYYY-MM-DD), no posterior a hoy en Madrid. En un viaje finished se ignora al corregir.

  • vehicleIdinteger | stringobligatorio

    Identificador. Entero positivo; también se admite como texto de dígitos ("412").

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • originstringobligatorio

    Salida (1-200 caracteres tras recortar espacios).

    De 1 a 200 caracteresPatrón: \S

  • destinationstringobligatorio

    Destino (1-200 caracteres tras recortar espacios).

    De 1 a 200 caracteresPatrón: \S

  • originLatnumber | null

    Latitud de la salida (WGS84). Con originLng: los dos o ninguno (required en el que falte). Se guarda con 6 decimales. En un viaje finished se ignora al corregir.

    Mínimo -90Máximo 90

  • originLngnumber | null

    Longitud de la salida (WGS84). Pareja de originLat.

    Mínimo -180Máximo 180

  • destinationLatnumber | null

    Latitud del destino (WGS84). Con destinationLng, los dos o ninguno.

    Mínimo -90Máximo 90

  • destinationLngnumber | null

    Longitud del destino (WGS84). Pareja de destinationLat.

    Mínimo -180Máximo 180

  • distanceKmnumberobligatorio

    Km declarados (el dato fiscal), con 2 decimales como mucho.

    Mayor que 0Máximo 99999.99

  • routeKmnumber | null

    Km de la ruta estimada (2 decimales como mucho).

    Mayor que 0Máximo 99999.99

  • routeDurationMininteger | null

    Duración de la ruta estimada, en minutos.

    Mínimo 0Máximo 10080

  • odometerKminteger | null

    Lectura del cuentakilómetros.

    Mínimo 0Máximo 9999999

  • reasonstringobligatorio

    Motivo del viaje, texto libre obligatorio (1-500 caracteres tras recortar espacios).

    De 1 a 500 caracteresPatrón: \S

  • reasonCategoryIdinteger | string | null

    Categoría activa del catálogo (viajes/reasons-list). Opcional.

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • consumptionL100kmnumber | null

    Consumo (l/100 km), 2 decimales como mucho. Solo se guarda en un vehículo de empresa (fuel); en km_rate se ignora. En una corrección, ausente conserva el que tenga y null lo quita.

    Mayor que 0Máximo 99.99

  • changeReasonstring | null

    Motivo de la corrección (hasta 500 caracteres tras recortar; en blanco = sin motivo). Obligatorio al corregir si la empresa tiene registros inalterables (reason_required); un alta lo ignora. No es reason (el motivo del viaje).

    Hasta 500 caracteres

Ejemplo: Alta de un viaje para un conductor

curl -sS -X POST "https://app.flotadoc.com/api/movimientos/viajes/save" \
  -H "Authorization: Bearer $FLOTADOC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -d '{
    "driverUserId": 15,
    "vehicleId": 9,
    "tripDate": "2026-10-09",
    "origin": "Calle Mayor 1, Logroño",
    "destination": "Polígono Cantabria, Logroño",
    "distanceKm": 7.4,
    "reason": "Revisión de la instalación del cliente",
    "reasonCategoryId": 3
  }'
Otro ejemplo: Corrección completa de un viaje
{
  "tripId": 412,
  "driverUserId": 15,
  "vehicleId": 9,
  "tripDate": "2026-10-09",
  "origin": "Calle Mayor 1, Logroño",
  "destination": "Polígono Cantabria, Logroño",
  "distanceKm": 9.8,
  "reason": "Revisión de la instalación del cliente",
  "reasonCategoryId": 3,
  "changeReason": "Km mal tecleados en el ERP"
}

Respuesta

200

El viaje tal como ha quedado (alta o corrección).

Cabeceras

  • X-Request-Idstring (uuid)

    Id de la petición en el historial de la empresa (para soporte).

  • Idempotent-Replayedstring

    true si es la respuesta guardada de una petición anterior con la misma Idempotency-Key.

    Valores: true

  • dataobject
    • El viaje con los datos de la firma del cliente (attendedByName, signedAt).

Ejemplo de respuesta
{
  "data": {
    "trip": {
      "tripId": 412,
      "tenantId": 42,
      "userId": 15,
      "userName": "Bea Conductora",
      "vehicleId": 9,
      "vehiclePlate": "5678DEF",
      "status": "recorded",
      "tripDate": "2026-10-09",
      "startedAt": null,
      "endedAt": null,
      "origin": "Calle Mayor 1, Logroño",
      "destination": "Polígono Cantabria, Logroño",
      "originLat": null,
      "originLng": null,
      "originAccuracyM": null,
      "destinationLat": null,
      "destinationLng": null,
      "destinationAccuracyM": null,
      "distanceKm": 7.4,
      "routeKm": null,
      "routeDurationMin": null,
      "odometerKm": null,
      "reason": "Revisión de la instalación del cliente",
      "reasonCategoryId": 3,
      "reasonCategoryName": "Servicio técnico o instalación",
      "costBasis": "km_rate",
      "kmRate": 0.26,
      "amount": 1.92,
      "consumptionL100km": null,
      "trackKm": null,
      "trackGapKm": null,
      "hasSignature": false,
      "correctedAt": null,
      "active": true,
      "updatedAt": "2026-10-09T16:20:11.482Z",
      "apiKeyId": 5,
      "cost": 1.92,
      "costKind": "allowance",
      "costPending": null,
      "provisionalCost": null,
      "justifiedAmount": null,
      "monthTicketsAmount": null,
      "monthOdometerKm": null,
      "monthShareKm": null,
      "estimatedLiters": null,
      "consumptionCost": null,
      "fuelPricePerLiter": null,
      "fuelPriceSource": null,
      "fuelPriceTicketDate": null,
      "alertLevel": "warn",
      "alertReasons": [
        "manual"
      ],
      "attendedByName": null,
      "signedAt": null
    }
  }
}

Además, las respuestas comunes: 401, 403, 404, 409, 422, 423, 429, 503.

Anula un viaje

POST/movimientos/viajes/delete

  • Permiso registros
  • Admite Idempotency-Key

Anula una línea del libro, como el owner en la web. Es un borrado lógico: la fila se conserva 4 años (art. 66 LGT), deja de salir en el libro y en viajes/get (404) y la sincronización de viajes/list la entrega con active: false. La firma y el recorrido GPS se conservan.

  • Un viaje en curso aún no es una línea del libro: no se anula (409 trip_in_progress); lo descarta el conductor en la app.
  • Una línea de un mes cerrado del vehículo no se anula (409 period_closed, con error.periods): hay que reabrir el mes en la web.
  • Registros inalterables: con el ajuste activo, anular es «anular con motivo»: sella una versión void y exige changeReason (422 reason_required, sin anular nada; solo se comprueba cuando el viaje existe y su mes está abierto). Sin el ajuste, changeReason se acepta y no se guarda: mándalo siempre.
  • Anular una línea ya anulada responde 404 trip_not_found. Con Idempotency-Key, un reintento de la misma petición repite el 200 original.

Errores propios

  • 404 trip_not_found: no existe, es de otra empresa o ya está anulado o descartado.
  • 409 trip_in_progress: el viaje está en curso.
  • 409 period_closed: mes cerrado del vehículo de la línea (error.periods).
  • 422 invalid_input: fields.tripId = required o invalid; fields.changeReason = invalid o too_long; cualquier otra clave, unexpected_field.
  • 422 reason_required: registros inalterables activos y sin changeReason.
  • 423 account_read_only: la cuenta no admite registros (error.reason: account, pending_payment o suspended).

Petición

Cabeceras

  • Idempotency-Keystring

    Clave de idempotencia de la escritura (opcional, recomendada). Vale 24 horas por clave API: la misma Idempotency-Key con la misma ruta y el mismo cuerpo exacto devuelve la respuesta guardada con Idempotent-Replayed: true sin volver a ejecutar la operación. Con otro cuerpo u otra ruta: 409 idempotency_conflict; si la primera aún está en curso: 409 idempotency_in_progress. Una respuesta 5xx no se guarda (se puede reintentar). Mal formada: 422 invalid_idempotency_key.

    Patrón: ^[A-Za-z0-9_-]{1,100}$

Cuerpo obligatorio

  • tripIdinteger | stringobligatorio

    Identificador. Entero positivo; también se admite como texto de dígitos ("412").

    integer: mínimo 1integer: máximo 9007199254740991string: patrón ^[1-9][0-9]{0,15}$

  • changeReasonstring | null

    Motivo de la anulación (hasta 500 caracteres tras recortar; en blanco = sin motivo). Obligatorio si la empresa tiene registros inalterables (reason_required); sin el ajuste no se guarda.

    Hasta 500 caracteres

Ejemplo

curl -sS -X POST "https://app.flotadoc.com/api/movimientos/viajes/delete" \
  -H "Authorization: Bearer $FLOTADOC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -d '{
    "tripId": 412,
    "changeReason": "Viaje duplicado en el ERP"
  }'

Respuesta

200

Viaje anulado.

Cabeceras

  • X-Request-Idstring (uuid)

    Id de la petición en el historial de la empresa (para soporte).

  • Idempotent-Replayedstring

    true si es la respuesta guardada de una petición anterior con la misma Idempotency-Key.

    Valores: true

  • dataobject
    • deletedboolean

      Siempre true

    • tripIdinteger

      Mínimo 1

Ejemplo de respuesta
{
  "data": {
    "deleted": true,
    "tripId": 412
  }
}

Además, las respuestas comunes: 401, 403, 404, 409, 422, 423, 429, 503.

Modelos

Objetos que devuelven o reciben las operaciones de esta área. Cada campo enlaza a su modelo.

ViajesTripobject

Un viaje con su coste y su semáforo, calculados en el momento de la lectura.

  • tripIdinteger

    Mínimo 1

  • tenantIdinteger

    Empresa.

    Mínimo 1

  • userIdinteger

    Conductor, a cuyo nombre está el viaje.

    Mínimo 1

  • userNamestring | null

    Nombre actual del conductor.

  • vehicleIdinteger

    Mínimo 1

  • vehiclePlatestring | null

    Matrícula actual del vehículo (no se copia al viaje).

  • statusstring

    recorded: registrado a mano a posteriori (web, app o API). in_progress: iniciado en la app y aún sin finalizar. finished: iniciado y finalizado en la app.

    Valores: recorded in_progress finished

  • tripDatestring (date)

    Día fiscal del viaje (YYYY-MM-DD, Europe/Madrid).

  • startedAtstring (date-time) | null

    Inicio en la app (UTC). null en un viaje recorded.

  • endedAtstring (date-time) | null

    Fin en la app (UTC). null en un viaje recorded o en curso.

  • originstring | null

    Salida. null solo en un viaje en curso que aún no la tiene.

    Hasta 200 caracteres

  • destinationstring | null

    Destino. null solo en un viaje en curso.

    Hasta 200 caracteres

  • originLatnumber | null

    Latitud de la salida (WGS84, 6 decimales).

    Mínimo -90Máximo 90

  • originLngnumber | null

    Longitud de la salida (WGS84, 6 decimales).

    Mínimo -180Máximo 180

  • originAccuracyMnumber | null

    Precisión en metros del punto de salida capturado por el GPS del móvil.

    Mínimo 0

  • destinationLatnumber | null

    Mínimo -90Máximo 90

  • destinationLngnumber | null

    Mínimo -180Máximo 180

  • destinationAccuracyMnumber | null

    Mínimo 0

  • distanceKmnumber | null

    Km declarados, el dato fiscal. null solo en un viaje en curso.

    Mayor que 0Máximo 99999.99

  • routeKmnumber | null

    Km de la ruta estimada, que respaldan los declarados.

    Mayor que 0Máximo 99999.99

  • routeDurationMininteger | null

    Duración de la ruta estimada, en minutos.

    Mínimo 0Máximo 10080

  • odometerKminteger | null

    Lectura del cuentakilómetros anotada en el viaje.

    Mínimo 0Máximo 9999999

  • reasonstring | null

    Motivo del viaje (texto libre). null solo en un viaje en curso.

    Hasta 500 caracteres

  • reasonCategoryIdinteger | null

    Mínimo 1

  • reasonCategoryNamestring | null

    Nombre actual de la categoría, también si se borró del catálogo.

  • costBasisstring

    Cómo se valora el viaje, copiado del régimen del vehículo al registrarlo: km_rate (vehículo propio: km × tarifa) o fuel (vehículo de empresa: parte justificada de los gastos de energía del mes).

    Valores: km_rate fuel

  • kmRatenumber | null

    Tarifa (EUR/km) copiada de la empresa al guardar. null en fuel y en curso.

    Mínimo 0Máximo 10

  • amountnumber | null

    ROUND(distanceKm × kmRate, 2) en EUR, calculado por la base de datos. null en fuel y en curso.

  • consumptionL100kmnumber | null

    Consumo anotado (l/100 km). Solo en fuel.

    Mayor que 0Máximo 99.99

  • trackKmnumber | null

    Km del recorrido GPS grabado, medidos al finalizar. null sin recorrido.

    Mínimo 0

  • trackGapKmnumber | null

    Km del recorrido en tramos sin señal.

    Mínimo 0

  • hasSignatureboolean

    Tiene firma del cliente (imagen).

  • correctedAtstring (date-time) | null

    Marca «Corregida»: la última corrección que cambió un dato fiscal (día, vehículo, origen, destino, km, motivo o categoría). null = nunca.

  • activeboolean

    false si está anulado o descartado (solo puede llegar así en la sincronización de viajes/list).

  • updatedAtstring (date-time)

    Último cambio de la fila (UTC, milisegundos). Ordena la sincronización incremental.

  • apiKeyIdinteger | null

    Clave API con la que se dio de alta; null si lo registró una persona.

    Mínimo 1

  • costnumber | null

    Coste oficial en EUR: en km_rate, amount; en fuel, la parte justificada (null mientras esté pendiente). Calculado al leer.

  • costKindstring | null

    allowance: km × tarifa (km_rate). justified: parte justificada (fuel). provisional: fuel sin lectura de fin de mes, vale su coste de consumo (provisionalCost). pending: sin cifra. null en un viaje en curso.

    Valores: justified provisional allowance pending

  • costPendingstring | null

    Por qué un viaje fuel ya cerrado aún no tiene parte justificada: falta la lectura del cuentakilómetros del mes, o los km de los viajes del mes la superan en 1 km o más.

    Valores: missing_odometer_reading odometer_mismatch

  • provisionalCostnumber | null

    Solo con costKind: provisional.

  • justifiedAmountnumber | null

    ROUND(monthTicketsAmount × distanceKm ÷ monthShareKm, 2) si el mes cuadra. Solo fuel.

  • monthTicketsAmountnumber | null

    Total de los tickets de energía (combustible y recarga) del vehículo en el mes. Solo fuel.

  • monthOdometerKmnumber | null

    Km del mes según el cuentakilómetros. Solo fuel.

  • monthShareKmnumber | null

    Km del reparto: los del cuentakilómetros o, si los viajes del mes los pasan dentro del margen de redondeo (1 km), los de los viajes. Solo fuel.

  • estimatedLitersnumber | null

    ROUND(distanceKm × consumptionL100km ÷ 100, 2). Solo fuel.

  • consumptionCostnumber | null

    Litros estimados × EUR/litro. Solo fuel.

  • fuelPricePerLiternumber | null

    EUR/litro: media de los tickets de combustible del mes o el del último ticket anterior; con el mes cerrado, el congelado en el cierre. Solo fuel.

  • fuelPriceSourcestring | null

    Valores: month last_ticket

  • fuelPriceTicketDatestring (date) | null

    Fecha del ticket del que sale el precio con last_ticket.

  • alertLevelstring | null

    Semáforo: bad (bloquea el cierre del mes), warn (revisar) u ok. null en un viaje en curso de menos de 12 h.

    Valores: ok warn bad

  • alertReasonsstring[]

    Motivos del semáforo en orden fijo. Rojos: open_too_long (en curso más de 12 h) y odometer_mismatch (los km del mes superan los del cuentakilómetros). Ámbar: route_deviation (km declarados a más de un 25 % de la ruta estimada), corrected, manual (registrado a mano) y missing_consumption (vehículo de empresa no eléctrico sin l/100).

    Valores: open_too_long odometer_mismatch route_deviation corrected manual missing_consumption

  • attendedByNamestring | nullopcional

    Quién atendió y firmó. Solo en viajes/get y en la respuesta de viajes/save.

    Hasta 120 caracteres

  • signedAtstring (date-time) | nullopcional

    Cuándo se guardó la firma. Solo en viajes/get y en la respuesta de viajes/save.

ViajesTripDetailobject

El viaje con los datos de la firma del cliente (attendedByName, signedAt).

Incluye todos los campos de ViajesTrip.

  • attendedByNamestring | null

    Quién atendió y firmó. Solo en viajes/get y en la respuesta de viajes/save.

    Hasta 120 caracteres

  • signedAtstring (date-time) | null

    Cuándo se guardó la firma. Solo en viajes/get y en la respuesta de viajes/save.

ViajesIntegrationobject | null

Clave API con la que se dio de alta el viaje (también si ya está revocada), o null si lo registró una persona. name y prefix son null si no se pudieron leer.

  • apiKeyIdinteger

    Mínimo 1

  • namestring | null

    Nombre que el owner dio a la clave.

    Hasta 60 caracteres

  • prefixstring | null

    Prefijo visible de la clave (nunca la clave entera).

    Patrón: ^fd_live_[A-Za-z0-9]{4}$

ViajesTripVersionobject

  • seqinteger

    Posición de la entrada en la cadena de huellas de la empresa.

    Mínimo 1

  • versioninteger

    1, 2, 3… dentro del viaje.

    Mínimo 1

  • changestring

    create alta o fin · correct corrección (también de la firma) · void anulación · technical puntos GPS tardíos.

    Valores: create correct void technical

  • authorobject | null

    Quién hizo el cambio; null solo en una versión technical.

    • userIdinteger

      Mínimo 1

    • namestring | null

      null si la persona no se ve desde la empresa (equipo de FlotaDoc).

  • recordedAtstring (date-time)

    Hora del sellado (UTC).

  • reasonstring | null

    Motivo del cambio (changeReason). null en un alta y en una versión technical.

    Hasta 500 caracteres

  • snapshotViajesTripSnapshot | null

    Instantánea fiscal después del cambio. null en una versión technical o redacted.

  • Huellas de los ficheros de la versión (sin claves ni nombres de S3).

  • changedstring[]

    Claves de la instantánea que cambiaron respecto a la versión anterior ([] en la primera).

  • entryHashstring

    Huella SHA-256 de la entrada en la cadena.

    Patrón: ^[0-9a-f]{64}$

  • redactedboolean

    true si el contenido falta o no se entiende (alteración: verify la da por rota).

ViajesReasonCategoryobject

  • reasonCategoryIdinteger

    Mínimo 1

  • namestring

    De 1 a 60 caracteres

  • isDefaultboolean

    Una de las seis por defecto (aunque se haya renombrado).

  • updatedAtstring (date-time)

ViajesTripSnapshotobject

Lo que la asesoría y Hacienda miran de la línea del libro en esa versión.

  • statusstring

    recorded: registrado a mano a posteriori (web, app o API). in_progress: iniciado en la app y aún sin finalizar. finished: iniciado y finalizado en la app.

    Valores: recorded in_progress finished

  • tripDatestring (date)
  • userIdinteger

    Conductor.

  • vehicleIdinteger
  • startedAtstring | null

    UTC con microsegundos (YYYY-MM-DDTHH:MM:SS.ffffffZ).

  • endedAtstring | null

    UTC con microsegundos.

  • originstring | null
  • originLatnumber | null
  • originLngnumber | null
  • destinationstring | null
  • destinationLatnumber | null
  • destinationLngnumber | null
  • distanceKmnumber | null
  • odometerKminteger | null
  • reasonstring | null

    Motivo del viaje.

  • reasonCategorystring | null

    Nombre de la categoría en ese momento.

  • costBasisstring

    Cómo se valora el viaje, copiado del régimen del vehículo al registrarlo: km_rate (vehículo propio: km × tarifa) o fuel (vehículo de empresa: parte justificada de los gastos de energía del mes).

    Valores: km_rate fuel

  • kmRatenumber | null
  • amountnumber | null
  • attendedByNamestring | null
  • signedAtstring | null

    UTC con microsegundos.

  • signatureSha256string | null

    Huella de la imagen de la firma.

    Patrón: ^[0-9a-f]{64}$

ViajesSealFileobject

  • kindstring

    signature imagen de la firma del cliente (como mucho una) · track recorrido GPS.

    Valores: signature track

  • sha256string

    Patrón: ^[0-9a-f]{64}$

  • bytesintegeropcional

    Tamaño en bytes, si se conoce.

    Mínimo 0

¿Quieres conectar tu sistema?

Cuéntanos qué quieres integrar y lo vemos en una llamada: qué datos necesitas, con qué permisos y cada cuánto.

Si tu empresa ya usa FlotaDoc, el titular puede pedir el acceso desde la web, en Mi cuenta › Integraciones.

Habla con nosotros