> For the complete documentation index, see [llms.txt](https://docs-integration.squake.earth/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs-integration.squake.earth/travel-data/retrieve-travel-data.md).

# Retrieve & Delete Travel Data

Read stored trips, activities, and calculations back — and delete a trip — with the /v2/travel-data/trips endpoints.

After ingestion, the trip endpoints let you read back exactly what SQUAKE stored, and delete a trip you shouldn't have sent.

Use them to reconcile your system against SQUAKE, to fetch the calculations of additional methodologies, to look up the audit log of a stored calculation, or to clean up test and duplicate data.

***

## Endpoints

| Endpoint                                                       | Returns                                                            |
| -------------------------------------------------------------- | ------------------------------------------------------------------ |
| `GET /v2/travel-data/trips`                                    | Paginated list of your stored trips, newest ingested first.        |
| `GET /v2/travel-data/trips/{id}`                               | A single trip.                                                     |
| `GET /v2/travel-data/trips/{trip_id}/activities`               | All activities of a trip, each with its traveler and calculations. |
| `GET /v2/travel-data/trips/{trip_id}/activities/{activity_id}` | A single activity with its traveler and calculations.              |
| `DELETE /v2/travel-data/trips/{id}`                            | Deletes the trip, its activities, and their calculations.          |

### Authentication

* **Bearer Token** or **HTTP Basic Auth** (API key as username, no password) — the same credentials you use for `POST /v2/travel-data`.

### Environments

| Environment | Base URL                           |
| ----------- | ---------------------------------- |
| Sandbox     | `https://api.sandbox.squake.earth` |
| Production  | `https://api.squake.earth`         |

> ℹ️ Ingesting travel data must be enabled for your account — until it is, `POST /v2/travel-data` and the CSV imports respond with `404` and error code `travel_data_not_found`. The read endpoints serve whatever is stored for you; a client with nothing stored gets an empty list.

***

## The two-level shape

A trip response carries the trip's own attributes and the **IDs** of its activities, never the activities themselves. The activities — with their traveler, calculations, and audit references — live one request away:

```
GET /v2/travel-data/trips/{id}
  ├── trip_reference / client_id / submitted_by_client_id
  ├── trip_name / trip_purpose / trip_status
  ├── start_date_utc / end_date_utc
  ├── booking_provider / amount_in_cents / currency
  ├── cost_center { name, purpose, email }
  └── activity_ids[]  ────────────┐
                                  │
GET /v2/travel-data/trips/{id}/activities
  └── activities[]  ←─────────────┘
        ├── type / external_reference
        ├── origin / destination / fuel_type   (by type — see below)
        ├── traveler { name, email, traveler_type }
        └── calculations[]
              ├── methodology / methodology_version
              ├── co2_in_grams
              └── audit { id }
```

This keeps a trip response small and predictable: no matter how many activities a trip holds, reading it costs one bounded response, and every endpoint that returns a trip returns the same set of fields.

The one exception is the `trips` array of a **submission**, which reports the trip's identity only — `id`, `trip_reference`, `client_id`, `submitted_by_client_id`, `activity_ids`. A read returns those five fields plus the descriptive ones above, and a shared field means the same thing in both, so a submission response and a later read of the same trip never disagree.

***

## Addressing a trip by your own reference

Everywhere a trip is addressed, you can pass **either** SQUAKE's `id` (a UUID) **or** your own `trip_reference`:

```bash
# equivalent, assuming trip_reference "TRIP-EXAMPLE-002" belongs to this trip
GET /v2/travel-data/trips/7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47
GET /v2/travel-data/trips/TRIP-EXAMPLE-002
```

That means you do not have to store SQUAKE's IDs to read your data back — if you set `trip_reference` on ingestion, your own reference is enough. Activities, by contrast, are always addressed by their SQUAKE `id`, as listed in the trip's `activity_ids`.

***

## Getting the IDs from a submission

`POST /v2/travel-data` returns a `trips` array next to the flat `items`, with the ID of every trip the request persisted and the IDs of the activities written under it:

```json
{
  "carbon_quantity": 333.0,
  "carbon_unit": "kilogram",
  "items": [ ... ],
  "trips": [
    {
      "id": "7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47",
      "trip_reference": "TRIP-EXAMPLE-002",
      "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
      "submitted_by_client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
      "activity_ids": [
        "2b4d6f81-9c3e-4a57-b0d2-6e1f8a4c7b93",
        "5e1a9c34-7d62-4f08-b3a1-9c4e2d7f6b58",
        "c84f1d27-3e95-4b60-a7d8-2f1b9e6c4a03",
        "a1d3b5c7-2e94-4f68-9b0a-7c5d3e1f8a26"
      ]
    }
  ]
}
```

Three details worth knowing:

* **One entry per trip, not per payload entry.** Two payload entries sharing a `trip_reference` resolve to the same trip and are reported once.
* **`activity_ids` covers what&#x20;*****this*****&#x20;request wrote.** Re-using a `trip_reference` appends activities to an existing trip, so that trip holds more activities than the submission response lists. Read the trip to get the full list.
* **A submission echoes identity, not content.** The five fields above are all a `trips` entry carries — it does not repeat the trip name, dates, amount or cost center you just sent. Read the trip to get those back as SQUAKE stored them.

***

## Trip fields

| Field                    | Type                  | Description                                                                                                                                                      |
| ------------------------ | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                     | string (UUID)         | SQUAKE's identifier for the trip.                                                                                                                                |
| `trip_reference`         | string \| null        | Your own reference, echoed from ingestion. Usable in place of `id`.                                                                                              |
| `client_id`              | string (UUID)         | The client that **owns** the trip.                                                                                                                               |
| `submitted_by_client_id` | string (UUID) \| null | The client whose credentials **submitted** the trip. `null` for trips that did not arrive through `POST /v2/travel-data` (e.g. CSV imports or TMC integrations). |
| `activity_ids`           | array (UUID)          | IDs of the trip's activities, in ingestion order, across all activity types.                                                                                     |

`client_id` and `submitted_by_client_id` differ when you submit on behalf of a descendant client: the target client owns the trip, your credential is recorded as the submitter. See [Submitting on behalf of another client](/travel-data/create-travel-data-items.md#submitting-on-behalf-of-another-client).

**Reads return more.** On top of the five fields above, `GET /v2/travel-data/trips` and `GET /v2/travel-data/trips/{id}` return the trip as you described it on ingestion:

| Field              | Type                       | Description                                                                                                                                              |
| ------------------ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `trip_name`        | string \| null             | The trip's name, echoed from ingestion.                                                                                                                  |
| `trip_purpose`     | string \| null             | The trip's purpose, echoed from ingestion.                                                                                                               |
| `trip_status`      | string \| null             | The status the source reported (e.g. `completed`). Free-form — SQUAKE neither constrains nor normalizes it.                                              |
| `booking_provider` | string \| null             | The provider the trip was booked through, echoed from ingestion.                                                                                         |
| `start_date_utc`   | string (date-time) \| null | Start of the trip, in UTC. Ingestion accepts a date (`2026-03-10`); reads return a date-time (`2026-03-10T00:00:00Z`).                                   |
| `end_date_utc`     | string (date-time) \| null | End of the trip, in UTC, same format.                                                                                                                    |
| `amount_in_cents`  | integer \| null            | The booking's own amount, in the minor unit of `currency` (`10000` is `100.00 USD`).                                                                     |
| `currency`         | string \| null             | 3-letter ISO 4217 code of `amount_in_cents`.                                                                                                             |
| `cost_center`      | object \| null             | The cost center the trip is booked against, as `{ "name", "purpose", "email" }`. The key is always present; it is `null` for a trip booked against none. |

These fields are echoed as stored, so a field you did not send on ingestion reads back as `null`. Two values SQUAKE keeps internally are deliberately not here: the amount converted into your base currency for reporting, and the cost center's department and internal id.

***

## List trips

### `GET /v2/travel-data/trips`

Returns your stored trips as a bare array, most recently ingested first. Trips from every source are listed — API submissions, CSV imports, and TMC integrations alike.

### Pagination

| Parameter | Description                                    |
| --------- | ---------------------------------------------- |
| `page`    | Page number, starting at 1.                    |
| `items`   | Trips per page. Defaults to 20, capped at 100. |

Pagination metadata is returned in the response headers:

| Header         | Meaning                                                         |
| -------------- | --------------------------------------------------------------- |
| `Current-Page` | The page returned.                                              |
| `Page-Items`   | Trips per page.                                                 |
| `Total-Pages`  | Total number of pages.                                          |
| `Total-Count`  | Total number of trips.                                          |
| `Link`         | RFC 8288 links to the `first`, `prev`, `next`, and `last` page. |

### Example

```bash
curl --request GET "https://api.sandbox.squake.earth/v2/travel-data/trips?page=1&items=20" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

```json
[
  {
    "id": "7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47",
    "trip_reference": "TRIP-EXAMPLE-002",
    "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
    "submitted_by_client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
    "trip_name": "Example business trip to London",
    "trip_purpose": "Customer workshop",
    "trip_status": "completed",
    "booking_provider": "Example TMC",
    "start_date_utc": "2026-03-10T00:00:00Z",
    "end_date_utc": "2026-03-12T00:00:00Z",
    "amount_in_cents": 248500,
    "currency": "EUR",
    "cost_center": {
      "name": "Example Cost Center",
      "purpose": "Sales",
      "email": "cost-center@example.com"
    },
    "activity_ids": [
      "2b4d6f81-9c3e-4a57-b0d2-6e1f8a4c7b93",
      "5e1a9c34-7d62-4f08-b3a1-9c4e2d7f6b58",
      "c84f1d27-3e95-4b60-a7d8-2f1b9e6c4a03",
      "a1d3b5c7-2e94-4f68-9b0a-7c5d3e1f8a26"
    ]
  },
  {
    "id": "0e5c3a91-6d78-4f21-8b4e-5a2d9c1f7b60",
    "trip_reference": "TRIP-EXAMPLE-001",
    "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
    "submitted_by_client_id": null,
    "trip_name": null,
    "trip_purpose": null,
    "trip_status": null,
    "booking_provider": null,
    "start_date_utc": "2026-02-04T00:00:00Z",
    "end_date_utc": null,
    "amount_in_cents": null,
    "currency": null,
    "cost_center": null,
    "activity_ids": ["d3c7b9a5-1f48-4e02-9a6d-8b5c3f1e7d24"]
  }
]
```

The second trip shows what a sparsely described source looks like: every field it did not carry reads back as `null`, and the keys are still there.

**Multi-client accounts.** If submitting on behalf of other clients is enabled for you, the list spans the authenticated client and all of its descendants — never a parent, a sibling, or an unrelated client. Read `client_id` on each trip to see which client owns it. Without that capability, you only ever see your own trips.

***

## Retrieve a single trip

### `GET /v2/travel-data/trips/{id}`

```bash
curl --request GET "https://api.sandbox.squake.earth/v2/travel-data/trips/TRIP-EXAMPLE-002" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

```json
{
  "id": "7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47",
  "trip_reference": "TRIP-EXAMPLE-002",
  "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
  "submitted_by_client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
  "trip_name": "Example business trip to London",
  "trip_purpose": "Customer workshop",
  "trip_status": "completed",
  "booking_provider": "Example TMC",
  "start_date_utc": "2026-03-10T00:00:00Z",
  "end_date_utc": "2026-03-12T00:00:00Z",
  "amount_in_cents": 248500,
  "currency": "EUR",
  "cost_center": {
    "name": "Example Cost Center",
    "purpose": "Sales",
    "email": "cost-center@example.com"
  },
  "activity_ids": [
    "2b4d6f81-9c3e-4a57-b0d2-6e1f8a4c7b93",
    "5e1a9c34-7d62-4f08-b3a1-9c4e2d7f6b58",
    "c84f1d27-3e95-4b60-a7d8-2f1b9e6c4a03",
    "a1d3b5c7-2e94-4f68-9b0a-7c5d3e1f8a26"
  ]
}
```

A single trip read and a trip in the list return the same fields — the list is the same shape, paginated.

***

## List the activities of a trip

### `GET /v2/travel-data/trips/{trip_id}/activities`

Returns every activity of the trip, in ingestion order, each with its traveler and the calculations persisted for it. A trip is a single booking, so the list is bounded and returned in full — this endpoint isn't paginated.

```bash
curl --request GET "https://api.sandbox.squake.earth/v2/travel-data/trips/TRIP-EXAMPLE-002/activities" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

```json
[
  {
    "id": "2b4d6f81-9c3e-4a57-b0d2-6e1f8a4c7b93",
    "type": "flight",
    "trip_id": "7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47",
    "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
    "external_reference": "ACTIVITY-FLIGHT-OUTBOUND",
    "origin": "BER",
    "destination": "LHR",
    "traveler": {
      "name": "Jane Doe",
      "email": "jane.doe@example.com",
      "traveler_type": "employee"
    },
    "calculations": [
      {
        "id": "3f2a1c8e-5d47-4b91-a0c3-1e8b7d6f4a20",
        "methodology": "TIM",
        "methodology_version": "3.0.0",
        "co2_in_grams": 142600.0,
        "audit": { "id": "0194d6b4-8711-7873-899d-c8133cd742f8" }
      }
    ]
  },
  {
    "id": "5e1a9c34-7d62-4f08-b3a1-9c4e2d7f6b58",
    "type": "hotel",
    "trip_id": "7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47",
    "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
    "external_reference": "ACTIVITY-HOTEL-001",
    "traveler": {
      "name": "Jane Doe",
      "email": "jane.doe@example.com",
      "traveler_type": "employee"
    },
    "calculations": [
      {
        "id": "8b6d4f20-9a17-4c53-b8e1-3d7a5c2f9e14",
        "methodology": "DEFRA",
        "methodology_version": "2026",
        "co2_in_grams": 36800.0,
        "audit": null
      }
    ]
  }
]
```

The example is truncated to two of the trip's four activities. Note that the hotel stay has no `origin`/`destination` keys at all — see [Keys that depend on the activity type](#keys-that-depend-on-the-activity-type).

### Activity fields

| Field                | Type           | Description                                                                                                                                                  |
| -------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`                 | string (UUID)  | Identifier of the activity, as listed in the trip's `activity_ids`.                                                                                          |
| `type`               | string         | `flight`, `hotel`, `car`, or `train`.                                                                                                                        |
| `trip_id`            | string (UUID)  | The trip this activity belongs to.                                                                                                                           |
| `client_id`          | string (UUID)  | The client that owns the activity — always the owner of its trip.                                                                                            |
| `external_reference` | string \| null | Your own reference, echoed from ingestion.                                                                                                                   |
| `origin`             | string \| null | Where the activity started, echoed from ingestion in the format you sent it (airport code, address, UN/LOCODE, lat/long). **`flight`, `car`, `train` only.** |
| `destination`        | string \| null | Where it ended, same format as `origin`. **`flight`, `car`, `train` only.**                                                                                  |
| `fuel_type`          | string \| null | The fuel the activity was calculated with, echoed from ingestion. Accepted values depend on the methodology. **`car` and `train` only.**                     |
| `traveler`           | object \| null | Who travelled, as `{ "name", "email", "traveler_type" }`. Always present; `null` for an activity submitted without a traveler.                               |
| `calculations`       | array          | One entry per methodology calculated for this activity, oldest first.                                                                                        |

### Keys that depend on the activity type

Route and fuel are only stored for the activity types that have them, and a key a type cannot have is **omitted rather than returned as `null`**:

| Type     | `origin` / `destination` | `fuel_type` |
| -------- | ------------------------ | ----------- |
| `flight` | ✅                        | —           |
| `car`    | ✅                        | ✅           |
| `train`  | ✅                        | ✅           |
| `hotel`  | —                        | —           |

So read `type` first, and treat a missing key as "not applicable to this type" rather than "no value". `traveler`, by contrast, is present on every activity type — a `null` there means the activity was submitted without a traveler, which is common for CSV and TMC rows.

### Traveler fields

| Field           | Type           | Description                                                                                                                                                                     |
| --------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`          | string \| null | Name of the traveler, echoed from ingestion.                                                                                                                                    |
| `email`         | string \| null | Email of the traveler, echoed from ingestion and lower-cased. SQUAKE matches travelers on this within a client, so two activities for the same person return the same traveler. |
| `traveler_type` | string \| null | `employee`, `contractor`, or `guest`.                                                                                                                                           |

The traveler's department, your external employee id and SQUAKE's internal traveler id are not part of this response.

### Calculation fields

| Field                 | Type           | Description                                                                                                            |
| --------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `id`                  | string (UUID)  | Identifier of the calculation.                                                                                         |
| `methodology`         | string         | The methodology this calculation ran under (e.g. `TIM`, `DEFRA`).                                                      |
| `methodology_version` | string \| null | Published version of that methodology for this activity type. `null` for methodologies that are not versioned.         |
| `co2_in_grams`        | number         | Emissions in **grams** of CO₂ equivalent.                                                                              |
| `audit`               | object \| null | The audit log this calculation produced, as `{ "id": "..." }`, or `null` for an activity submitted without audit mode. |

> ⚠️ **Note the unit.** `co2_in_grams` is in grams, while `POST /v2/travel-data` and the calculation endpoints report `carbon_quantity` in kilograms by default.

**Reading the full audit log.** `audit` carries only the ID — pass it to [`/v2/audits/{id}`](/audits/specific-audit-log.md) for the immutable record of the request, response, distances, and emission factors behind the calculation.

**Routing legs are not listed.** For a `flight` activity submitted with `routing` (e.g. `BER-FRA-JFK`), the individual legs are internal segments: the routed activity carries the itinerary total, and legs appear neither in `activity_ids` nor in this list. Addressing a leg ID directly returns `404`.

***

## Retrieve a single activity

### `GET /v2/travel-data/trips/{trip_id}/activities/{activity_id}`

Activities are always addressed through their trip, so both identifiers are required.

```bash
curl --request GET "https://api.sandbox.squake.earth/v2/travel-data/trips/TRIP-EXAMPLE-002/activities/2b4d6f81-9c3e-4a57-b0d2-6e1f8a4c7b93" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

The response is a single activity object, in the shape shown above — including its `traveler` and, where the type has them, `origin`, `destination` and `fuel_type`.

***

## Additional methodologies

If your account is configured with more than one methodology for an activity type, SQUAKE persists **one calculation per methodology**. The flat `items` array of a submission only reports the primary methodology — the others are readable here:

```json
{
  "id": "c84f1d27-3e95-4b60-a7d8-2f1b9e6c4a03",
  "type": "car",
  "trip_id": "7c9e6f2a-4b81-4d3e-9a52-1f0c8b3d5e47",
  "client_id": "4fb3ec7a-92cb-471f-b75f-c3fe7c2a34d5",
  "external_reference": "ACTIVITY-CAR-001",
  "origin": "London Heathrow Airport, United Kingdom",
  "destination": "Canary Wharf, London, United Kingdom",
  "fuel_type": "hev",
  "traveler": {
    "name": "Jane Doe",
    "email": "jane.doe@example.com",
    "traveler_type": "employee"
  },
  "calculations": [
    {
      "id": "6a2e8c40-7b19-4d35-9f68-1c4b7e2a5d93",
      "methodology": "DEFRA",
      "methodology_version": "2026",
      "co2_in_grams": 14200.0,
      "audit": null
    },
    {
      "id": "f5b1d873-2c60-4e97-a1d4-8b3f6c9e2074",
      "methodology": "US-EPA",
      "methodology_version": "2026",
      "co2_in_grams": 15100.0,
      "audit": null
    }
  ]
}
```

***

## Delete a trip

### `DELETE /v2/travel-data/trips/{id}`

Deletes the trip and everything hanging off it — all of its activities, routing legs included, and their calculations. Responds with `204 No Content` and an empty body. Like the reads, it accepts a `trip_reference` in place of the `id`.

```bash
curl --request DELETE "https://api.sandbox.squake.earth/v2/travel-data/trips/TRIP-EXAMPLE-002" \
  --header "Authorization: Bearer $ACCESS_TOKEN"
```

Three things to keep in mind:

* **Audit logs are kept.** They are an immutable record of what was calculated, so deleting a trip does not remove the audit logs its calculations produced.
* **Reporting lags a delete.** Dashboards and reporting views refresh periodically, so a deleted trip can still appear in them until the next refresh.
* **This cannot be undone.** Re-submitting the trip to `POST /v2/travel-data` restores the data, but recalculates its emissions and creates new IDs.

***

## Errors

| Status  | Meaning                                                  |
| ------- | -------------------------------------------------------- |
| **204** | Delete succeeded — empty body.                           |
| **401** | Missing or invalid API key.                              |
| **404** | `travel_data_not_found` — see below. Nothing is deleted. |
| **500** | Internal server error.                                   |

Every miss on these endpoints collapses into the same response:

```json
{
  "errors": [
    {
      "code": "travel_data_not_found",
      "detail": "The requested travel data does not exist or is not accessible."
    }
  ]
}
```

You get it when the trip does not exist, when it belongs to a client you cannot reach, when the identifier is neither a known trip `id` nor a known `trip_reference`, and when the activity belongs to a different trip or is a routing leg. A trip you cannot access is deliberately indistinguishable from one that does not exist.

The trip **list** is the exception: it never 404s on an empty result — a client with no reachable trips gets `200` and `[]`.

***

## Implementation notes

**Set `trip_reference` on ingestion and you never need to store SQUAKE's IDs.** Your own reference addresses the trip on every read and on delete. Activity IDs, however, only come from SQUAKE — take them from the submission response or from a trip read.

**Reconcile through the trip, not the submission response.** The `trips` array of a submission reports only the identity of what that request wrote. For the complete picture of a trip — its stored attributes, its cost center, and activities added by earlier or later submissions — read the trip.

**Branch on `type` before reading an activity's route.** `origin`, `destination` and `fuel_type` are absent, not `null`, for the types that do not have them, so a parser that assumes a fixed key set will break on the first hotel stay.

**Use the activities endpoint for anything beyond the primary methodology.** Additional methodologies and audit references are not in the flat `items` array of a submission; they are here.

**Reads are eventually visible in reporting, deletes too.** These endpoints read the stored records directly and are immediately consistent; dashboards and reporting views refresh on a schedule.

***

## Related

* [Create Travel Data Items](/travel-data/create-travel-data-items.md) — ingest trips and activities.
* [Retrieve a specific Audit log](/audits/specific-audit-log.md) — the full record behind a calculation's `audit.id`.
