> ## Documentation Index
> Fetch the complete documentation index at: https://developer.findity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fields - Mileage expenses

Create and manage mileage expense claims using the dynamic Fields system in the Expense API.

Create mileage expense claims (car specifications) using the dynamic Fields system. This guide covers initializing fields, handling the route and vehicle type selection, managing trip details, and saving mileage expenses.

## Overview

Mileage expenses use the `CarSpecification` expense type. They allow users to claim reimbursement for business travel based on distance driven, vehicle type, and optional extras like passengers, road tolls, and trailer usage.

The Fields system handles the complexity of mileage calculations — including country-specific reimbursement rates, vehicle type multipliers, and distance computation from routes. Your client renders the fields and lets the server do the math.

## Key concepts

| Concept | Description |
| - | - |
| **Route** | An ordered list of places (with coordinates) that defines the travel path. The server calculates distance automatically. |
| **Vehicle type** | The type of vehicle used (e.g., private car, company car, motorcycle). Affects reimbursement rates. |
| **Round trip** | A toggle that doubles the calculated distance. |
| **Manual distance** | Allows the user to override the server-calculated distance with a manually entered value. |
| **Trip details** | Optional extras: passengers, road tolls, gravel distance, trailer, caravan, etc. |
| **Commuting** | A variant of mileage for commuting expenses, with year/month/day selection instead of route-based travel. |

## API endpoints

All mileage field operations use the standard Fields endpoints with `expenseType=CarSpecification`:

| Operation | Method | Endpoint |
| - | - | - |
| Initialize fields | `GET` | `/v1/expense/me/organizations/{id}/expensetypes/CarSpecification/fields` |
| Update fields | `PUT` | `/v1/expense/me/organizations/{id}/expensetypes/CarSpecification/fields` |
| Create expense | `POST` | `/v1/expense/expenses?format=fields&organizationId={id}&expenseType=CarSpecification` |
| Update expense | `PUT` | `/v1/expense/expenses/{expenseId}?format=fields` |
| Get car types | `GET` | `/v1/expense/me/organizations/{id}/categories/{categoryId}/cartypes` |
| Get categories | `GET` | `/v1/expense/me/organizations/{id}/expensetypes/CarSpecification/categories` |

## Step 1: Initialize fields

Fetch the field structure for a new mileage expense:

```bash bash theme={"system"}
curl -X GET "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/CarSpecification/fields" \
  -H "Authorization: Bearer {access_token}"
```

To load an existing mileage expense for editing, pass the expense record ID:

```bash bash theme={"system"}
curl -X GET "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/CarSpecification/fields?expenseRecordId={expenseId}" \
  -H "Authorization: Bearer {access_token}"
```

### Field structure overview

The response contains these key fields:

| Field property | controlType | Description |
| - | - | - |
| `id` | `TEXT` | Expense ID (hidden, system field) |
| `categoryId` | `LIST` | Mileage category — `requiresUpdate: true` |
| `verification.comment` | `MULTI_LINE_TEXT` | User comment |
| `expenseReportId` | `LIST` | Assign to an expense report |
| `verification.travelDate` | `DATE_TIME` | Date and time of travel |
| `verification.destination` | `TEXT` | Auto-generated from route (hidden, read-only) |
| `verification.carType` | `LIST` | Vehicle type — `requiresUpdate: true` |
| `verification.travelRoute` | `FIELD_GROUP` | Route container with nested fields |
| `verification.travelTime` | `TEXT` | Travel time (hidden, system field) |
| Custom dimension fields | `LIST` | Organization-specific dimensions (e.g., cost center, project) |

## Step 2: Handle the route

The travel route is a `FIELD_GROUP` containing several nested fields:

| Nested field | controlType | Description |
| - | - | - |
| `verification.manualDistance` | `SWITCH` | Toggle manual distance entry — `requiresUpdate: true` |
| `verification.route` | `MILEAGE_ROUTE` | Array of route points with `place`, `latitude`, `longitude` |
| `verification.distance` | `DOUBLE` | Calculated distance (or manual entry when `manualDistance` is true) |
| `verification.roundTrip` | `SWITCH` | Doubles the distance — `requiresUpdate: true` |
| `verification.numberOfPassengers` | `INTEGER` | Number of extra passengers |
| `verification.tollCost` | `DOUBLE` | Road toll amount |
| `verification.distanceOnGravel` | `DOUBLE` | Distance driven on gravel roads |
| `verification.distanceInTransport` | `DOUBLE` | Distance with vehicle on transport |
| `verification.distanceWithTrailer` | `DOUBLE` | Distance with trailer attached |
| `verification.distanceWithCaravan` | `DOUBLE` | Distance with caravan attached |
| `verification.distanceWithHeavyCaravan` | `DOUBLE` | Distance with heavy caravan |
| `verification.distanceWithDog` | `DOUBLE` | Distance with dog in vehicle |
| `verification.travelTime` | `TEXT` | Calculated travel time — `requiresUpdate: true` |

> [!NOTE]
>
> Not all trip detail fields are visible by default. Their visibility depends on the organization's configuration and country-specific rules. Only render fields where `visible: true`.

### Route data format

The `MILEAGE_ROUTE` field holds an array of waypoints:

```json theme={"system"}
[
  { "place": "Stockholm, Sweden", "latitude": "59.3293481", "longitude": "18.0682306" },
  { "place": "Gothenburg, Sweden", "latitude": "57.7086375", "longitude": "11.9747055" }
]
```

The first entry is the origin, the last is the destination, and any entries in between are via points. When the route changes and `requiresUpdate` is true, the server recalculates the distance and generates a map image.

### Adding via points

Routes can include intermediate stops. A route with two via points:

```json theme={"system"}
[
  { "place": "Ludvika", "latitude": "60.1523510", "longitude": "15.1919879" },
  { "place": "Falun", "latitude": "60.609036", "longitude": "15.629638" },
  { "place": "Borlänge", "latitude": "60.489796", "longitude": "15.434664" },
  { "place": "Stockholm", "latitude": "59.3293481", "longitude": "18.0682306" }
]
```

### Route commands

The travel route field group includes a `commands` array for clearing the route:

```json theme={"system"}
{
  "commands": [
    {
      "text": "Clear travel route",
      "confirmationRequired": true,
      "confirmation": "Are you sure you want to clear travel routes?",
      "command": "action=removeTravelRoute"
    }
  ]
}
```

Execute by appending the command to the PUT URL:

```
PUT /v1/expense/me/organizations/{id}/expensetypes/CarSpecification/fields?action=removeTravelRoute
```

### Map image

After a route update, the server generates a map image. The URL is stored in the hidden field `virtual.mileageMap`:

```json theme={"system"}
{ "property": "virtual.mileageMap", "visible": false, "value": "https://expense.findity.com/api/resources/ff8080818cd9867f..." },
{ "property": "virtual.mileageMapChecksum", "visible": false, "value": "236c7fd6d8462091c3f36a33756cfa44b386433b" }
```

Use this URL to display a visual route preview in your UI. The server also provides a `virtual.mileageMapChecksum` field for cache validation. Both fields are hidden and read-only.

## Step 3: Vehicle type and category

Both the category (`categoryId`) and vehicle type (`verification.carType`) have `requiresUpdate: true`. Changing either triggers a server round-trip that may update reimbursement calculations and visible fields.

### Fetching vehicle types

Vehicle types are scoped to the selected category:

```
GET /v1/expense/me/organizations/{id}/categories/{categoryId}/cartypes
```

Common vehicle types include:

| Value | Description |
| - | - |
| `PRIVATE_CAR` | Private car |
| `COMPANY_CAR` | Company car |
| `COMPANY_CAR_DIESEL` | Company car (diesel) |
| `COMPANY_CAR_ELECTRICITY` | Company car (electric) |
| `MOTOR_CYCLE` | Motorcycle |
| `MOTOR_CYCLE_GT_125CC` | Motorcycle > 125cc |
| `MOTOR_CYCLE_LTE_125CC` | Motorcycle ≤ 125cc |
| `MOPED` | Moped |
| `CYCLE_OR_WALKING` | Bicycle or walking |
| `PUBLIC_TRANSPORTATION` | Public transportation |

> [!NOTE]
>
> The full list of vehicle types depends on the organization's country and configuration. Always fetch from the API rather than hardcoding values.

## Step 4: The update cycle

Mileage expenses have several fields with `requiresUpdate: true`. When the user changes any of these, send the full fields array back to the server:

```
PUT /v1/expense/me/organizations/{id}/expensetypes/CarSpecification/fields
```

Fields that trigger an update:

| Field | What changes on update |
| - | - |
| `categoryId` | Visible fields, vehicle type options, reimbursement rates |
| `verification.carType` | Reimbursement rate, trip detail visibility |
| `verification.manualDistance` | Toggles between calculated and manual distance input |
| `verification.roundTrip` | Doubles or halves the distance |
| `verification.route` | Recalculates distance and generates a new map |
| `verification.fuelType` | Updates toll cost calculations (where applicable) |
| `verification.bompeng` | Updates road toll data (Norwegian organizations) |

### Example update request

```bash bash theme={"system"}
curl -X PUT "https://stage-api.findity.com/api/v1/expense/me/organizations/{orgId}/expensetypes/CarSpecification/fields" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      { "property": "id", "value": null },
      { "property": "categoryId", "value": "b219079277d14c77a0c85497504cf90b" },
      { "property": "verification.carType", "value": "PRIVATE_CAR" },
      { "property": "verification.travelDate", "value": "2024-01-05T12:46:11Z" },
      { "property": "verification.travelRoute", "fields": [
        { "property": "verification.manualDistance", "value": false },
        { "property": "verification.route", "value": [
          { "place": "Stockholm, Sweden", "latitude": "59.3293481", "longitude": "18.0682306" },
          { "place": "Ludvika, Sweden", "latitude": "60.1523510", "longitude": "15.1919879" }
        ]},
        { "property": "verification.distance", "value": 434 },
        { "property": "verification.roundTrip", "value": false }
      ]}
    ]
  }'
```

> [!WARNING]
>
> Always send the complete fields array — including hidden fields and fields you didn't modify. The server uses the full state to compute the response.

## Step 5: Save the expense

Once the user is finished, save the mileage expense:

### Using fields format

```
POST /v1/expense/expenses?format=fields&organizationId={id}&expenseType=CarSpecification
```

Send the full fields payload as the request body. The server validates all fields and returns the created expense.

### Using standard JSON format

Alternatively, extract values from the fields and use the standard expense format:

```bash bash theme={"system"}
curl -X POST "https://stage-api.findity.com/api/v1/expense/expenses" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "organizationId": "ff808181963979e20196397a2098004b",
    "categoryId": "b2d50112c6fa4411b75208c23c21b323",
    "verification": {
      "type": "CarSpecification",
      "carType": "PRIVATE_CAR",
      "travelDate": "2024-01-31T23:00:00Z",
      "description": "Trip to Gothenburg",
      "manualDistance": false,
      "roundTrip": false,
      "distance": 468,
      "distanceUnit": "KM",
      "route": [
        { "place": "Stockholm, Sweden", "latitude": "59.3293481", "longitude": "18.0682306" },
        { "place": "Gothenburg, Sweden", "latitude": "57.7086375", "longitude": "11.9747055" }
      ],
      "passengers": [],
      "tripDetails": {
        "carRegistrationNumber": "AB12345",
        "numberOfPassengers": 2,
        "tollCost": 10,
        "distanceOnGravel": 0,
        "distanceInTransport": 0,
        "distanceWithTrailer": 0,
        "distanceWithCaravan": 0,
        "distanceWithHeavyCaravan": 0,
        "distanceWithDog": 0
      }
    }
  }'
```

### Example response

```json theme={"system"}
{
  "id": "67c18882083149599859054bcebb4ca0",
  "organizationId": "ff808181963979e20196397a2098004b",
  "personId": "ff808181963979e20196397a119f002d",
  "status": "NORMAL",
  "processStatus": "DRAFT",
  "categoryId": "b2d50112c6fa4411b75208c23c21b323",
  "reimbursementCurrency": "SEK",
  "reimbursementAmount": 2340.00,
  "dateCreated": "2024-01-31T10:52:48Z",
  "lastUpdated": "2024-01-31T10:52:48Z",
  "verification": {
    "type": "CarSpecification",
    "carType": "PRIVATE_CAR",
    "travelDate": "2024-01-31T23:00:00Z",
    "description": "Trip to Gothenburg",
    "destination": "Stockholm, Sweden - Gothenburg, Sweden",
    "distance": 468,
    "distanceUnit": "KM",
    "manualDistance": false,
    "roundTrip": false,
    "route": [
      { "place": "Stockholm, Sweden", "latitude": "59.3293481", "longitude": "18.0682306" },
      { "place": "Gothenburg, Sweden", "latitude": "57.7086375", "longitude": "11.9747055" }
    ],
    "passengers": [],
    "tripDetails": {
      "carRegistrationNumber": "AB12345",
      "numberOfPassengers": 2,
      "tollCost": 10,
      "distanceOnGravel": 0,
      "distanceInTransport": 0,
      "distanceWithTrailer": 0,
      "distanceWithCaravan": 0,
      "distanceWithHeavyCaravan": 0,
      "distanceWithDog": 0
    }
  }
}
```

## Commuting variant

Some organizations configure mileage categories for commuting. Commuting expenses replace the route-based travel with a year/month/day selection:

| Field | controlType | Description |
| - | - | - |
| `verification.commuting.year` | `LIST_SEARCHABLE` | Year to report commuting for |
| `verification.commuting.month` | `LIST_SEARCHABLE` | Month to report — `requiresUpdate: true` |
| `verification.commuting.days` | `LIST_SEARCHABLE` | Number of commuting days |

Fetch the available values from these endpoints:

```
GET /v1/expense/me/organizations/{id}/commuting/years
GET /v1/expense/me/organizations/{id}/commuting/months?year=2025
GET /v1/expense/me/organizations/{id}/commuting/days?year=2025&month=6
```

The route field group is still present in commuting mode but with a simplified structure — the vehicle type is typically locked (e.g., `PRIVATE_CAR` with `disabled: true`).

## Named passengers

Some organizations require named passengers instead of just a count. When enabled, the `passengers` array contains individual entries:

```json theme={"system"}
{
  "passengers": [
    { "name": "Albert", "distance": 100 },
    { "name": "Herbert", "distance": 200 },
    { "name": "Kyle", "distance": 150 }
  ]
}
```

Each passenger has a `name` and the `distance` they traveled. This is used for per-passenger reimbursement calculations in some countries.

## Fleet management integration

Organizations with fleet management integrations can link mileage expenses to tracked vehicle trips:

```json theme={"system"}
{
  "verification": {
    "relatedTrips": [
      { "fleetManagementTripId": "12345678" },
      { "fleetManagementTripId": "12345679" }
    ]
  }
}
```

Fetch available trips from:

```
GET /v1/expense/me/organizations/{id}/categories/{categoryId}/fleetmanagementtrips
```

In the fields format, fleet management trips appear as a `LIST` field with `multiSelect: true` at `verification.fleetManagementTripIds`.

## Toll cost data

For Norwegian organizations using AutoPASS or similar toll systems, toll cost data can be included:

```json theme={"system"}
{
  "verification": {
    "tollCostFuelType": "HYBRID",
    "tollCostData": {
      "price": 100,
      "discountedPrice": 90,
      "returnPrice": 200,
      "returnDiscountedPrice": 180
    }
  }
}
```

The `tollCostFuelType` affects the toll rate calculation and supports: `PETROL`, `DIESEL`, `ELECTRIC`, `HYBRID`, and `HYDROGEN`.

## Common integration patterns

> **Route suggestions with place search**
>
> Use the route suggestions endpoint to provide autocomplete when users type a place name:
>
> ```
> GET /v1/expense/route/suggestions?place=Stoc
> ```
>
> Returns a list of matching places. After the user selects origin and destination, call the directions endpoint to get coordinates and calculated distance:
>
> ```
> POST /v1/expense/route/directions
> ```
>
> With a body of `[{ "place": "Stockholm" }, { "place": "Gothenburg" }]`.

> **Handling manual distance override**
>
> When the user toggles `verification.manualDistance` to `true`, the `verification.distance` field becomes editable and the `verification.route` field is no longer required. Send a PUT to update the fields — the server will adjust field visibility accordingly. When toggled back to `false`, the distance is recalculated from the route.

> **Round trip handling**
>
> When `verification.roundTrip` is toggled to `true`, the server doubles the calculated distance. This is a `requiresUpdate` field — send a PUT to get the updated distance value. The route itself stays the same; only the distance is doubled.

> **Rendering the route summary**
>
> The travel route `FIELD_GROUP` includes a `summary` array for displaying a compact preview:
>
> ```json theme={"system"}
> [
>   { "type": "image" },
>   { "type": "property_value", "property": "Distance", "value": "468 km" }
> ]
> ```
>
> Use the `image` type to display the map from `virtual.mileageMap`, and `property_value` entries to show key metrics like distance.

## Error handling

Common errors when working with mileage expenses:

| Status code | Error code | Description |
| - | - | - |
| `400` | `NOT_A_CAR_SPECIFICATION_CATEGORY` | The category ID provided is not a mileage category. Fetch categories for `CarSpecification` expense type. |
| `400` | `INVALID_JSON_BODY` | Failed to parse the request body or no known properties received. |
| `400` | `INVALID_JSON_PROPERTY_VALUE` | Missing or invalid `type` on verification — ensure `type` is set to `CarSpecification`. |
| `400` | `TOO_FEW_ROUTE_PLACES` | Route requires at least 2 places (origin and destination). |
| `404` | `EXPENSE_RECORD_NOT_FOUND` | The expense ID does not exist or is not accessible by the current user. |
| `404` | `CATEGORY_NOT_FOUND` | The specified category does not exist in the organization. |
| `404` | `FLEET_MANAGEMENT_ACCOUNT_NOT_FOUND` | Fleet management account not configured for the organization. |
| `404` | `FLEET_MANAGEMENT_VEHICLE_NOT_FOUND` | No vehicle found for the current user in fleet management. |

## Next steps

> **[Fields reference](/docs/fields)**
>
> Full reference for the Fields system, control types, and the update cycle

> **[Route directions](/reference/get-route-directions)**
>
> API reference for calculating route directions and distances

> **[Receipt expenses](/docs/fields-receipt-expenses)**
>
> Guide for creating receipt-based expenses using Fields

> **[Per diem expenses](/docs/fields-per-diem-expenses)**
>
> Guide for creating per diem / subsistence allowance expenses
