# API reference

Base URL: `https://quickota.com/api/v1`. Paths below are relative to the base URL.
Every request needs `Authorization: Bearer <key>`. Successful bodies are `{ "data": …, "meta": { "requestId", "livemode" } }`; errors are problem+json with a `code`.

## Flight bookings

### `POST /flights/bookings`

Holds an offer: the airline reserves the seats and the booking becomes
`held` until `deadlines.holdExpiresAt`. Nothing is charged yet.
Requires an `Idempotency-Key`; retry with the same key after a
timeout to get the same booking back.

**Scope:** `flights:book`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `Idempotency-Key` | header | string | yes | Unique value (UUID) per operation; send the same value when retrying. See the Idempotency guide. |

Request body:

```json
{
  "offerId": "string",
  "passengers": [
    {
      "type": "string",
      "gender": "string",
      "firstName": "string",
      "lastName": "string",
      "birthDate": "2026-12-01",
      "nationality": "string",
      "document": {
        "type": "string",
        "number": "string",
        "issuingCountry": "string",
        "expiryDate": "2026-12-01",
        "issueDate": "2026-12-01"
      }
    }
  ],
  "contact": {
    "name": "string",
    "email": "ali@example.com",
    "phone": "string"
  },
  "agencyReference": "string"
}
```

| Field | Type | Description |
|---|---|---|
| `passengers` *(required)* | PassengerV1[] | Passengers in the same counts and types as the search. The first adult is the lead passenger. |
| `agencyReference` | string | Your own reference (e.g. your order number), up to 64 characters. Echoed back everywhere and searchable. |

Response `201`:

```json
{
  "data": {
    "id": "string",
    "bookingNumber": "string",
    "agencyReference": "string",
    "status": "string",
    "isFinal": true,
    "pendingReason": "string",
    "statusReason": "string",
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "deadlines": {
      "holdExpiresAt": "2026-12-01T08:30:00Z",
      "voidUntil": "2026-12-01T08:30:00Z"
    },
    "pollAfterSeconds": 0,
    "pnr": "string",
    "ticketNumbers": [
      "string"
    ],
    "price": {
      "amountDue": {
        "amount": "string",
        "currency": "string"
      },
      "suggestedRetail": {
        "amount": "string",
        "currency": "string"
      },
      "commission": {
        "amount": "string",
        "currency": "string"
      },
      "cancellationFee": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFees": [
        {
          "type": "string",
          "name": "string",
          "perPassenger": {},
          "total": {}
        }
      ]
    },
    "slices": [
      {
        "origin": "string",
        "destination": "string",
        "departureAt": "2026-12-01T08:30:00Z",
        "arrivalAt": "2026-12-01T08:30:00Z",
        "stops": 0,
        "durationMinutes": 0,
        "segments": [
          {
            "marketingCarrier": "string",
            "flightNumber": "string",
            "operatingCarrier": "string",
            "origin": "string",
            "destination": "string",
            "departureAt": "2026-12-01T08:30:00Z",
            "arrivalAt": "2026-12-01T08:30:00Z",
            "cabin": "string",
            "bookingClass": "string"
          }
        ]
      }
    ],
    "passengers": [
      {
        "index": 0,
        "type": "string",
        "firstName": "string",
        "lastName": "string",
        "birthDate": "2026-12-01",
        "ticketNumber": "string",
        "state": "string"
      }
    ],
    "contact": {
      "name": "string",
      "email": "ali@example.com",
      "phone": "string"
    },
    "openServicingRequests": [
      {
        "id": "string",
        "requestNumber": "string",
        "type": "string",
        "status": "string",
        "quoteExpiresAt": "2026-12-01T08:30:00Z"
      }
    ],
    "openScheduleChanges": [
      {
        "id": "string",
        "requiresAcceptance": true,
        "receivedAt": "2026-12-01T08:30:00Z",
        "replyDeadline": "2026-12-01T08:30:00Z"
      }
    ],
    "createdAt": "2026-12-01T08:30:00Z",
    "ticketedAt": "2026-12-01T08:30:00Z",
    "cancelledAt": "2026-12-01T08:30:00Z",
    "lastEventAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /flights/bookings`

Lists bookings of this environment, newest first. `needsAction=true`
returns only bookings waiting on you: held (issue before the deadline),
issuing, a servicing quote to decide, or a schedule change to answer.

**Scope:** `flights:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `status` | query | string | no |  |
| `needsAction` | query | boolean | no |  |
| `agencyReference` | query | string | no |  |
| `pnr` | query | string | no |  |
| `createdFrom` | query | string (date-time) | no |  |
| `createdTo` | query | string (date-time) | no |  |
| `departureFrom` | query | string (date-time) | no |  |
| `departureTo` | query | string (date-time) | no |  |
| `page` | query | integer (int32) | no |  |
| `pageSize` | query | integer (int32) | no |  |

Response `200`:

```json
{
  "data": [
    {
      "id": "string",
      "bookingNumber": "string",
      "agencyReference": "string",
      "status": "string",
      "isFinal": true,
      "pnr": "string",
      "origin": "string",
      "destination": "string",
      "departureAt": "2026-12-01T08:30:00Z",
      "passengerCount": 0,
      "leadPassenger": "string",
      "amountDue": {
        "amount": "string",
        "currency": "string"
      },
      "holdExpiresAt": "2026-12-01T08:30:00Z",
      "createdAt": "2026-12-01T08:30:00Z"
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /flights/bookings/{id}`

The booking with its status, next actions, deadlines, passengers, tickets and open servicing.

**Scope:** `flights:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "bookingNumber": "string",
    "agencyReference": "string",
    "status": "string",
    "isFinal": true,
    "pendingReason": "string",
    "statusReason": "string",
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "deadlines": {
      "holdExpiresAt": "2026-12-01T08:30:00Z",
      "voidUntil": "2026-12-01T08:30:00Z"
    },
    "pollAfterSeconds": 0,
    "pnr": "string",
    "ticketNumbers": [
      "string"
    ],
    "price": {
      "amountDue": {
        "amount": "string",
        "currency": "string"
      },
      "suggestedRetail": {
        "amount": "string",
        "currency": "string"
      },
      "commission": {
        "amount": "string",
        "currency": "string"
      },
      "cancellationFee": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFees": [
        {
          "type": "string",
          "name": "string",
          "perPassenger": {},
          "total": {}
        }
      ]
    },
    "slices": [
      {
        "origin": "string",
        "destination": "string",
        "departureAt": "2026-12-01T08:30:00Z",
        "arrivalAt": "2026-12-01T08:30:00Z",
        "stops": 0,
        "durationMinutes": 0,
        "segments": [
          {
            "marketingCarrier": "string",
            "flightNumber": "string",
            "operatingCarrier": "string",
            "origin": "string",
            "destination": "string",
            "departureAt": "2026-12-01T08:30:00Z",
            "arrivalAt": "2026-12-01T08:30:00Z",
            "cabin": "string",
            "bookingClass": "string"
          }
        ]
      }
    ],
    "passengers": [
      {
        "index": 0,
        "type": "string",
        "firstName": "string",
        "lastName": "string",
        "birthDate": "2026-12-01",
        "ticketNumber": "string",
        "state": "string"
      }
    ],
    "contact": {
      "name": "string",
      "email": "ali@example.com",
      "phone": "string"
    },
    "openServicingRequests": [
      {
        "id": "string",
        "requestNumber": "string",
        "type": "string",
        "status": "string",
        "quoteExpiresAt": "2026-12-01T08:30:00Z"
      }
    ],
    "openScheduleChanges": [
      {
        "id": "string",
        "requiresAcceptance": true,
        "receivedAt": "2026-12-01T08:30:00Z",
        "replyDeadline": "2026-12-01T08:30:00Z"
      }
    ],
    "createdAt": "2026-12-01T08:30:00Z",
    "ticketedAt": "2026-12-01T08:30:00Z",
    "cancelledAt": "2026-12-01T08:30:00Z",
    "lastEventAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{id}/cancel`

Cancels a booking that has not been issued: the seats are released and
nothing is charged. Ticketed bookings are refunded or voided through a
post-booking request instead.

**Scope:** `flights:book`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |
| `Idempotency-Key` | header | string | no | Unique value (UUID) per operation; send the same value when retrying. See the Idempotency guide. |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "bookingNumber": "string",
    "agencyReference": "string",
    "status": "string",
    "isFinal": true,
    "pendingReason": "string",
    "statusReason": "string",
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "deadlines": {
      "holdExpiresAt": "2026-12-01T08:30:00Z",
      "voidUntil": "2026-12-01T08:30:00Z"
    },
    "pollAfterSeconds": 0,
    "pnr": "string",
    "ticketNumbers": [
      "string"
    ],
    "price": {
      "amountDue": {
        "amount": "string",
        "currency": "string"
      },
      "suggestedRetail": {
        "amount": "string",
        "currency": "string"
      },
      "commission": {
        "amount": "string",
        "currency": "string"
      },
      "cancellationFee": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFees": [
        {
          "type": "string",
          "name": "string",
          "perPassenger": {},
          "total": {}
        }
      ]
    },
    "slices": [
      {
        "origin": "string",
        "destination": "string",
        "departureAt": "2026-12-01T08:30:00Z",
        "arrivalAt": "2026-12-01T08:30:00Z",
        "stops": 0,
        "durationMinutes": 0,
        "segments": [
          {
            "marketingCarrier": "string",
            "flightNumber": "string",
            "operatingCarrier": "string",
            "origin": "string",
            "destination": "string",
            "departureAt": "2026-12-01T08:30:00Z",
            "arrivalAt": "2026-12-01T08:30:00Z",
            "cabin": "string",
            "bookingClass": "string"
          }
        ]
      }
    ],
    "passengers": [
      {
        "index": 0,
        "type": "string",
        "firstName": "string",
        "lastName": "string",
        "birthDate": "2026-12-01",
        "ticketNumber": "string",
        "state": "string"
      }
    ],
    "contact": {
      "name": "string",
      "email": "ali@example.com",
      "phone": "string"
    },
    "openServicingRequests": [
      {
        "id": "string",
        "requestNumber": "string",
        "type": "string",
        "status": "string",
        "quoteExpiresAt": "2026-12-01T08:30:00Z"
      }
    ],
    "openScheduleChanges": [
      {
        "id": "string",
        "requiresAcceptance": true,
        "receivedAt": "2026-12-01T08:30:00Z",
        "replyDeadline": "2026-12-01T08:30:00Z"
      }
    ],
    "createdAt": "2026-12-01T08:30:00Z",
    "ticketedAt": "2026-12-01T08:30:00Z",
    "cancelledAt": "2026-12-01T08:30:00Z",
    "lastEventAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /flights/bookings/{id}/documents/e-ticket`

The e-ticket (itinerary receipt) PDF, once the booking is ticketed.

**Scope:** `flights:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`: OK

### `GET /flights/bookings/{id}/events`

Everything that happened to the booking, oldest first.

**Scope:** `flights:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": [
    {
      "type": "string",
      "at": "2026-12-01T08:30:00Z",
      "actor": "string",
      "note": "string"
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{id}/issue`

Issues a held booking: the amount due is taken from your wallet and the
airline issues the tickets. The booking becomes `ticketed`, or
`issuing` when the airline confirms later — then wait for the
webhook or poll; never call issue again. Calling issue on a booking that
is already issuing or ticketed just returns it.

**Scope:** `flights:book`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |
| `Idempotency-Key` | header | string | yes | Unique value (UUID) per operation; send the same value when retrying. See the Idempotency guide. |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "bookingNumber": "string",
    "agencyReference": "string",
    "status": "string",
    "isFinal": true,
    "pendingReason": "string",
    "statusReason": "string",
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "deadlines": {
      "holdExpiresAt": "2026-12-01T08:30:00Z",
      "voidUntil": "2026-12-01T08:30:00Z"
    },
    "pollAfterSeconds": 0,
    "pnr": "string",
    "ticketNumbers": [
      "string"
    ],
    "price": {
      "amountDue": {
        "amount": "string",
        "currency": "string"
      },
      "suggestedRetail": {
        "amount": "string",
        "currency": "string"
      },
      "commission": {
        "amount": "string",
        "currency": "string"
      },
      "cancellationFee": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFees": [
        {
          "type": "string",
          "name": "string",
          "perPassenger": {},
          "total": {}
        }
      ]
    },
    "slices": [
      {
        "origin": "string",
        "destination": "string",
        "departureAt": "2026-12-01T08:30:00Z",
        "arrivalAt": "2026-12-01T08:30:00Z",
        "stops": 0,
        "durationMinutes": 0,
        "segments": [
          {
            "marketingCarrier": "string",
            "flightNumber": "string",
            "operatingCarrier": "string",
            "origin": "string",
            "destination": "string",
            "departureAt": "2026-12-01T08:30:00Z",
            "arrivalAt": "2026-12-01T08:30:00Z",
            "cabin": "string",
            "bookingClass": "string"
          }
        ]
      }
    ],
    "passengers": [
      {
        "index": 0,
        "type": "string",
        "firstName": "string",
        "lastName": "string",
        "birthDate": "2026-12-01",
        "ticketNumber": "string",
        "state": "string"
      }
    ],
    "contact": {
      "name": "string",
      "email": "ali@example.com",
      "phone": "string"
    },
    "openServicingRequests": [
      {
        "id": "string",
        "requestNumber": "string",
        "type": "string",
        "status": "string",
        "quoteExpiresAt": "2026-12-01T08:30:00Z"
      }
    ],
    "openScheduleChanges": [
      {
        "id": "string",
        "requiresAcceptance": true,
        "receivedAt": "2026-12-01T08:30:00Z",
        "replyDeadline": "2026-12-01T08:30:00Z"
      }
    ],
    "createdAt": "2026-12-01T08:30:00Z",
    "ticketedAt": "2026-12-01T08:30:00Z",
    "cancelledAt": "2026-12-01T08:30:00Z",
    "lastEventAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

## Flight servicing

### `POST /flights/bookings/{bookingId}/post-booking-requests`

Asks for a refund, void, no-show refund or date change. The request is
quoted by the ticketing desk; follow its status (or the
`flight.post_booking_request.updated` webhook) and accept or decline
the quote before it expires.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `Idempotency-Key` | header | string | yes | Unique value (UUID) per operation; send the same value when retrying. See the Idempotency guide. |

Request body:

```json
{
  "type": "string",
  "passengerIndexes": [
    0
  ],
  "sliceIndexes": [
    0
  ],
  "requestedDate": "2026-12-01",
  "note": "string"
}
```

| Field | Type | Description |
|---|---|---|
| `type` *(required)* | string | `refund`, `void`, `change_date`, `no_show_refund` or `other`. |
| `passengerIndexes` | integer (int32)[] | Indexes of the passengers concerned (from `passengers[].index`). Empty = all active passengers. |
| `sliceIndexes` | integer (int32)[] | Indexes of the slices concerned, for a partial refund or change. Empty = all. |
| `requestedDate` | string (date) | For `change_date`: the new travel date wanted. |

Response `201`:

```json
{
  "data": {
    "id": "string",
    "requestNumber": "string",
    "bookingId": "string",
    "type": "string",
    "status": "string",
    "isFinal": true,
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "passengerIndexes": [
      0
    ],
    "sliceIndexes": [
      0
    ],
    "quote": {
      "airlinePenalty": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFee": {
        "amount": "string",
        "currency": "string"
      },
      "fareDifference": {
        "amount": "string",
        "currency": "string"
      },
      "refundAmount": {
        "amount": "string",
        "currency": "string"
      },
      "collectAmount": {
        "amount": "string",
        "currency": "string"
      },
      "note": "string",
      "quotedAt": "2026-12-01T08:30:00Z",
      "expiresAt": "2026-12-01T08:30:00Z"
    },
    "outcome": {
      "refunded": {
        "amount": "string",
        "currency": "string"
      },
      "collected": {
        "amount": "string",
        "currency": "string"
      },
      "newPnr": "string",
      "newBookingId": "string",
      "executedAt": "2026-12-01T08:30:00Z"
    },
    "createdAt": "2026-12-01T08:30:00Z",
    "history": [
      {
        "type": "string",
        "at": "2026-12-01T08:30:00Z",
        "actor": "string",
        "note": "string"
      }
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /flights/bookings/{bookingId}/post-booking-requests`

All post-booking requests of the booking, newest first.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": [
    {
      "id": "string",
      "requestNumber": "string",
      "bookingId": "string",
      "type": "string",
      "status": "string",
      "isFinal": true,
      "nextActions": [
        {
          "action": "string",
          "method": "string",
          "href": "string",
          "deadline": "2026-12-01T08:30:00Z"
        }
      ],
      "passengerIndexes": [
        0
      ],
      "sliceIndexes": [
        0
      ],
      "quote": {
        "airlinePenalty": {
          "amount": "string",
          "currency": "string"
        },
        "serviceFee": {
          "amount": "string",
          "currency": "string"
        },
        "fareDifference": {
          "amount": "string",
          "currency": "string"
        },
        "refundAmount": {
          "amount": "string",
          "currency": "string"
        },
        "collectAmount": {
          "amount": "string",
          "currency": "string"
        },
        "note": "string",
        "quotedAt": "2026-12-01T08:30:00Z",
        "expiresAt": "2026-12-01T08:30:00Z"
      },
      "outcome": {
        "refunded": {
          "amount": "string",
          "currency": "string"
        },
        "collected": {
          "amount": "string",
          "currency": "string"
        },
        "newPnr": "string",
        "newBookingId": "string",
        "executedAt": "2026-12-01T08:30:00Z"
      },
      "createdAt": "2026-12-01T08:30:00Z",
      "history": [
        {
          "type": "string",
          "at": "2026-12-01T08:30:00Z",
          "actor": "string",
          "note": "string"
        }
      ]
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /flights/bookings/{bookingId}/post-booking-requests/{requestId}`

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `requestId` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "requestNumber": "string",
    "bookingId": "string",
    "type": "string",
    "status": "string",
    "isFinal": true,
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "passengerIndexes": [
      0
    ],
    "sliceIndexes": [
      0
    ],
    "quote": {
      "airlinePenalty": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFee": {
        "amount": "string",
        "currency": "string"
      },
      "fareDifference": {
        "amount": "string",
        "currency": "string"
      },
      "refundAmount": {
        "amount": "string",
        "currency": "string"
      },
      "collectAmount": {
        "amount": "string",
        "currency": "string"
      },
      "note": "string",
      "quotedAt": "2026-12-01T08:30:00Z",
      "expiresAt": "2026-12-01T08:30:00Z"
    },
    "outcome": {
      "refunded": {
        "amount": "string",
        "currency": "string"
      },
      "collected": {
        "amount": "string",
        "currency": "string"
      },
      "newPnr": "string",
      "newBookingId": "string",
      "executedAt": "2026-12-01T08:30:00Z"
    },
    "createdAt": "2026-12-01T08:30:00Z",
    "history": [
      {
        "type": "string",
        "at": "2026-12-01T08:30:00Z",
        "actor": "string",
        "note": "string"
      }
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{bookingId}/post-booking-requests/{requestId}/accept`

Accepts the quote: a refund is credited to your wallet, an amount to
collect is charged to it, and the desk executes the change with the airline.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `requestId` | path | string (uuid) | yes |  |
| `Idempotency-Key` | header | string | yes | Unique value (UUID) per operation; send the same value when retrying. See the Idempotency guide. |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "requestNumber": "string",
    "bookingId": "string",
    "type": "string",
    "status": "string",
    "isFinal": true,
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "passengerIndexes": [
      0
    ],
    "sliceIndexes": [
      0
    ],
    "quote": {
      "airlinePenalty": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFee": {
        "amount": "string",
        "currency": "string"
      },
      "fareDifference": {
        "amount": "string",
        "currency": "string"
      },
      "refundAmount": {
        "amount": "string",
        "currency": "string"
      },
      "collectAmount": {
        "amount": "string",
        "currency": "string"
      },
      "note": "string",
      "quotedAt": "2026-12-01T08:30:00Z",
      "expiresAt": "2026-12-01T08:30:00Z"
    },
    "outcome": {
      "refunded": {
        "amount": "string",
        "currency": "string"
      },
      "collected": {
        "amount": "string",
        "currency": "string"
      },
      "newPnr": "string",
      "newBookingId": "string",
      "executedAt": "2026-12-01T08:30:00Z"
    },
    "createdAt": "2026-12-01T08:30:00Z",
    "history": [
      {
        "type": "string",
        "at": "2026-12-01T08:30:00Z",
        "actor": "string",
        "note": "string"
      }
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{bookingId}/post-booking-requests/{requestId}/decline`

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `requestId` | path | string (uuid) | yes |  |

Request body:

```json
{
  "note": "string"
}
```

Response `200`:

```json
{
  "data": {
    "id": "string",
    "requestNumber": "string",
    "bookingId": "string",
    "type": "string",
    "status": "string",
    "isFinal": true,
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "passengerIndexes": [
      0
    ],
    "sliceIndexes": [
      0
    ],
    "quote": {
      "airlinePenalty": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFee": {
        "amount": "string",
        "currency": "string"
      },
      "fareDifference": {
        "amount": "string",
        "currency": "string"
      },
      "refundAmount": {
        "amount": "string",
        "currency": "string"
      },
      "collectAmount": {
        "amount": "string",
        "currency": "string"
      },
      "note": "string",
      "quotedAt": "2026-12-01T08:30:00Z",
      "expiresAt": "2026-12-01T08:30:00Z"
    },
    "outcome": {
      "refunded": {
        "amount": "string",
        "currency": "string"
      },
      "collected": {
        "amount": "string",
        "currency": "string"
      },
      "newPnr": "string",
      "newBookingId": "string",
      "executedAt": "2026-12-01T08:30:00Z"
    },
    "createdAt": "2026-12-01T08:30:00Z",
    "history": [
      {
        "type": "string",
        "at": "2026-12-01T08:30:00Z",
        "actor": "string",
        "note": "string"
      }
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{bookingId}/post-booking-requests/{requestId}/withdraw`

Withdraws a request that has not been accepted yet.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `requestId` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "requestNumber": "string",
    "bookingId": "string",
    "type": "string",
    "status": "string",
    "isFinal": true,
    "nextActions": [
      {
        "action": "string",
        "method": "string",
        "href": "string",
        "deadline": "2026-12-01T08:30:00Z"
      }
    ],
    "passengerIndexes": [
      0
    ],
    "sliceIndexes": [
      0
    ],
    "quote": {
      "airlinePenalty": {
        "amount": "string",
        "currency": "string"
      },
      "serviceFee": {
        "amount": "string",
        "currency": "string"
      },
      "fareDifference": {
        "amount": "string",
        "currency": "string"
      },
      "refundAmount": {
        "amount": "string",
        "currency": "string"
      },
      "collectAmount": {
        "amount": "string",
        "currency": "string"
      },
      "note": "string",
      "quotedAt": "2026-12-01T08:30:00Z",
      "expiresAt": "2026-12-01T08:30:00Z"
    },
    "outcome": {
      "refunded": {
        "amount": "string",
        "currency": "string"
      },
      "collected": {
        "amount": "string",
        "currency": "string"
      },
      "newPnr": "string",
      "newBookingId": "string",
      "executedAt": "2026-12-01T08:30:00Z"
    },
    "createdAt": "2026-12-01T08:30:00Z",
    "history": [
      {
        "type": "string",
        "at": "2026-12-01T08:30:00Z",
        "actor": "string",
        "note": "string"
      }
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /flights/bookings/{bookingId}/schedule-changes`

Airline schedule changes on the booking. Changes with `requiresAcceptance` need your reply before `replyDeadline`.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": [
    {
      "id": "string",
      "status": "string",
      "requiresAcceptance": true,
      "receivedAt": "2026-12-01T08:30:00Z",
      "replyDeadline": "2026-12-01T08:30:00Z",
      "original": [
        {
          "sliceIndex": 0,
          "airline": "string",
          "flightNumber": "string",
          "origin": "string",
          "destination": "string",
          "departureLocal": "2026-12-01T08:30:00Z",
          "arrivalLocal": "2026-12-01T08:30:00Z"
        }
      ],
      "changed": [
        {
          "sliceIndex": 0,
          "airline": "string",
          "flightNumber": "string",
          "origin": "string",
          "destination": "string",
          "departureLocal": "2026-12-01T08:30:00Z",
          "arrivalLocal": "2026-12-01T08:30:00Z"
        }
      ],
      "remark": "string",
      "repliedAt": "2026-12-01T08:30:00Z"
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{bookingId}/schedule-changes/{noticeId}/accept`

Accepts the new schedule on behalf of the passengers. To refuse it,
create a post-booking request (refund or date change) instead.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `noticeId` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "status": "string",
    "requiresAcceptance": true,
    "receivedAt": "2026-12-01T08:30:00Z",
    "replyDeadline": "2026-12-01T08:30:00Z",
    "original": [
      {
        "sliceIndex": 0,
        "airline": "string",
        "flightNumber": "string",
        "origin": "string",
        "destination": "string",
        "departureLocal": "2026-12-01T08:30:00Z",
        "arrivalLocal": "2026-12-01T08:30:00Z"
      }
    ],
    "changed": [
      {
        "sliceIndex": 0,
        "airline": "string",
        "flightNumber": "string",
        "origin": "string",
        "destination": "string",
        "departureLocal": "2026-12-01T08:30:00Z",
        "arrivalLocal": "2026-12-01T08:30:00Z"
      }
    ],
    "remark": "string",
    "repliedAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/bookings/{bookingId}/schedule-changes/{noticeId}/acknowledge`

Tells the airline you have seen a change that needs no acceptance.

**Scope:** `flights:post_booking`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `bookingId` | path | string (uuid) | yes |  |
| `noticeId` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "string",
    "status": "string",
    "requiresAcceptance": true,
    "receivedAt": "2026-12-01T08:30:00Z",
    "replyDeadline": "2026-12-01T08:30:00Z",
    "original": [
      {
        "sliceIndex": 0,
        "airline": "string",
        "flightNumber": "string",
        "origin": "string",
        "destination": "string",
        "departureLocal": "2026-12-01T08:30:00Z",
        "arrivalLocal": "2026-12-01T08:30:00Z"
      }
    ],
    "changed": [
      {
        "sliceIndex": 0,
        "airline": "string",
        "flightNumber": "string",
        "origin": "string",
        "destination": "string",
        "departureLocal": "2026-12-01T08:30:00Z",
        "arrivalLocal": "2026-12-01T08:30:00Z"
      }
    ],
    "remark": "string",
    "repliedAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

## Flight shopping

### `GET /flights/offers/{offerId}/fare-rules`

The fare's refund, change and no-show conditions, plus the airline's full rule text when available.

**Scope:** `flights:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `offerId` | path | string | yes |  |

Response `200`:

```json
{
  "data": {
    "offerId": "string",
    "refundable": true,
    "changeable": true,
    "cancelPenalty": {
      "amount": "string",
      "currency": "string"
    },
    "changePenalty": {
      "amount": "string",
      "currency": "string"
    },
    "penalties": [
      {
        "kind": "string",
        "condition": "string",
        "permitted": true,
        "amount": {
          "amount": "string",
          "currency": "string"
        },
        "percentOfFare": 0
      }
    ],
    "text": "string"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/offers/{offerId}/price`

Re-prices an offer with the airline right now. Call it before holding
when the search is more than a few minutes old or before showing your
customer the final price. When `priceChanged` is true the new price
replaces the old one for the hold.

**Scope:** `flights:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `offerId` | path | string | yes |  |

Response `200`:

```json
{
  "data": {
    "offerId": "string",
    "priceChanged": true,
    "previousTotal": {
      "amount": "string",
      "currency": "string"
    },
    "price": {
      "total": {
        "amount": "string",
        "currency": "string"
      },
      "suggestedRetail": {
        "amount": "string",
        "currency": "string"
      },
      "commission": {
        "amount": "string",
        "currency": "string"
      }
    },
    "taxes": {
      "amount": "string",
      "currency": "string"
    },
    "refundable": true,
    "changeable": true,
    "holdAvailableUntil": "2026-12-01T08:30:00Z",
    "baggage": [
      {
        "category": "string",
        "included": true,
        "pieces": 0,
        "weightKg": 0,
        "summary": "string"
      }
    ],
    "serviceFees": [
      {
        "type": "string",
        "name": "string",
        "perPassenger": {
          "amount": "string",
          "currency": "string"
        },
        "total": {
          "amount": "string",
          "currency": "string"
        }
      }
    ],
    "hasFlightHold": true
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /flights/search`

Searches every airline source available to your agency and returns
bookable offers, cheapest first. Each fare family of the same flights is
a separate offer. Offers expire (see `expiresAt`) — hold soon.

**Scope:** `flights:read`

Request body:

```json
{
  "slices": [
    {
      "origin": "string",
      "destination": "string",
      "departureDate": "2026-12-01"
    }
  ],
  "passengers": {
    "adults": 0,
    "children": 0,
    "infants": 0
  },
  "cabin": "string",
  "currency": "string",
  "nationality": "string",
  "domestic": true,
  "directOnly": true,
  "preferredAirline": "string",
  "maxResults": 0
}
```

| Field | Type | Description |
|---|---|---|
| `slices` *(required)* | SearchSliceV1[] | 1 slice for one-way, 2 for a return, up to 6 for multi-city. |
| `cabin` | string | `economy` (default), `premium_economy`, `business` or `first`. |
| `currency` | string | Currency to price in. Defaults to your wallet currency, else your agency's default currency; when neither is configured the search is refused and you must send one. |
| `nationality` | string | ISO 3166-1 alpha-2 nationality of the travellers, when fares depend on it. |
| `domestic` | boolean | True for a domestic trip (national IDs are then accepted as travel documents). |
| `preferredAirline` | string | Optional 2-letter airline code to prefer. |
| `maxResults` | integer (int32) | Most offers to return (1–200, default 50), cheapest first. |

Response `200`:

```json
{
  "data": {
    "offers": [
      {
        "offerId": "string",
        "expiresAt": "2026-12-01T08:30:00Z",
        "slices": [
          {
            "origin": "string",
            "destination": "string",
            "departureAt": "2026-12-01T08:30:00Z",
            "arrivalAt": "2026-12-01T08:30:00Z",
            "stops": 0,
            "durationMinutes": 0,
            "segments": [
              {}
            ]
          }
        ],
        "price": {
          "total": {},
          "suggestedRetail": {},
          "commission": {}
        },
        "fare": {
          "brandName": "string",
          "brandCode": "string",
          "cabin": "string",
          "refundable": true,
          "changeable": true,
          "baggage": [
            {}
          ]
        },
        "seatsLeft": 0
      }
    ],
    "warnings": [
      {
        "code": "string",
        "message": "string"
      }
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

## Webhooks

### `GET /webhook-deliveries`

Delivery attempts, newest first. Filter by `endpointId`, `eventId` or `status` (pending, succeeded, failed, cancelled).

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `endpointId` | query | string (uuid) | no |  |
| `eventId` | query | string (uuid) | no |  |
| `status` | query | string | no |  |
| `page` | query | integer (int32) | no |  |
| `pageSize` | query | integer (int32) | no |  |

Response `200`:

```json
{
  "data": [
    {
      "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "eventId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "endpointId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "eventType": "string",
      "status": "string",
      "attempts": 0,
      "nextAttemptAt": "2026-12-01T08:30:00Z",
      "lastAttemptAt": "2026-12-01T08:30:00Z",
      "lastStatusCode": 0,
      "lastError": "string",
      "lastResponseExcerpt": "string",
      "lastDurationMs": 0,
      "createdAt": "2026-12-01T08:30:00Z",
      "completedAt": "2026-12-01T08:30:00Z"
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /webhook-deliveries/{id}/retry`

Sends a delivery again now (e.g. after fixing your receiver). A failure starts a fresh retry schedule.

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "eventId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "endpointId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "eventType": "string",
    "status": "string",
    "attempts": 0,
    "nextAttemptAt": "2026-12-01T08:30:00Z",
    "lastAttemptAt": "2026-12-01T08:30:00Z",
    "lastStatusCode": 0,
    "lastError": "string",
    "lastResponseExcerpt": "string",
    "lastDurationMs": 0,
    "createdAt": "2026-12-01T08:30:00Z",
    "completedAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /webhook-endpoints`

Your webhook endpoints in this environment.

**Scope:** `webhooks:manage`

Response `200`:

```json
{
  "data": [
    {
      "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "url": "string",
      "description": "string",
      "eventTypes": [
        "string"
      ],
      "status": "string",
      "disabledReason": "string",
      "failingSince": "2026-12-01T08:30:00Z",
      "lastSuccessAt": "2026-12-01T08:30:00Z",
      "lastFailureAt": "2026-12-01T08:30:00Z",
      "secretRotating": true,
      "createdAt": "2026-12-01T08:30:00Z"
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /webhook-endpoints`

Registers an endpoint. The response contains the signing `secret`
— store it; it is used to verify the `TAM-Signature` header.

**Scope:** `webhooks:manage`

Request body:

```json
{
  "url": "string",
  "description": "string",
  "eventTypes": [
    "string"
  ],
  "enabled": true
}
```

| Field | Type | Description |
|---|---|---|
| `url` | string | Public `https://` URL that receives the events. |
| `description` | string | Optional note for yourself, e.g. "Production booking sync". |
| `eventTypes` | string[] | Event types to receive, or `["*"]` for all (including ones added later). |
| `enabled` | boolean | On update only: false pauses deliveries, true resumes them (also after an automatic disable). |

Response `201`:

```json
{
  "data": {
    "endpoint": {
      "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "url": "string",
      "description": "string",
      "eventTypes": [
        "string"
      ],
      "status": "string",
      "disabledReason": "string",
      "failingSince": "2026-12-01T08:30:00Z",
      "lastSuccessAt": "2026-12-01T08:30:00Z",
      "lastFailureAt": "2026-12-01T08:30:00Z",
      "secretRotating": true,
      "createdAt": "2026-12-01T08:30:00Z"
    },
    "secret": "string"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /webhook-endpoints/{id}`

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "url": "string",
    "description": "string",
    "eventTypes": [
      "string"
    ],
    "status": "string",
    "disabledReason": "string",
    "failingSince": "2026-12-01T08:30:00Z",
    "lastSuccessAt": "2026-12-01T08:30:00Z",
    "lastFailureAt": "2026-12-01T08:30:00Z",
    "secretRotating": true,
    "createdAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `PATCH /webhook-endpoints/{id}`

Changes the URL, description or event types (omitted fields keep their
value), or pauses/resumes the endpoint with `enabled`.

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Request body:

```json
{
  "url": "string",
  "description": "string",
  "eventTypes": [
    "string"
  ],
  "enabled": true
}
```

| Field | Type | Description |
|---|---|---|
| `url` | string | Public `https://` URL that receives the events. |
| `description` | string | Optional note for yourself, e.g. "Production booking sync". |
| `eventTypes` | string[] | Event types to receive, or `["*"]` for all (including ones added later). |
| `enabled` | boolean | On update only: false pauses deliveries, true resumes them (also after an automatic disable). |

Response `200`:

```json
{
  "data": {
    "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "url": "string",
    "description": "string",
    "eventTypes": [
      "string"
    ],
    "status": "string",
    "disabledReason": "string",
    "failingSince": "2026-12-01T08:30:00Z",
    "lastSuccessAt": "2026-12-01T08:30:00Z",
    "lastFailureAt": "2026-12-01T08:30:00Z",
    "secretRotating": true,
    "createdAt": "2026-12-01T08:30:00Z"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `DELETE /webhook-endpoints/{id}`

Deletes the endpoint; deliveries still waiting for it are cancelled.

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `204`: No Content

### `POST /webhook-endpoints/{id}/rotate-secret`

Issues a new signing secret. For 24 hours deliveries carry two `v1`
signatures (new and old secret), so you can deploy the new one without
losing events.

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "endpoint": {
      "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "url": "string",
      "description": "string",
      "eventTypes": [
        "string"
      ],
      "status": "string",
      "disabledReason": "string",
      "failingSince": "2026-12-01T08:30:00Z",
      "lastSuccessAt": "2026-12-01T08:30:00Z",
      "lastFailureAt": "2026-12-01T08:30:00Z",
      "secretRotating": true,
      "createdAt": "2026-12-01T08:30:00Z"
    },
    "secret": "string"
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `POST /webhook-endpoints/{id}/test`

Sends a `ping` event to this endpoint within a few seconds. Check the result with `GET /webhook-deliveries?eventId=…`.

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `202`:

```json
{
  "data": {
    "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "type": "string",
    "objectType": "string",
    "objectId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "createdAt": "2026-12-01T08:30:00Z",
    "status": "string",
    "payload": null
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /webhook-event-types`

Every event type you can subscribe to, with when it is sent.

**Scope:** `webhooks:manage`

Response `200`:

```json
{
  "data": [
    {
      "name": "string",
      "module": "string",
      "description": "string"
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /webhook-events`

Events raised in this environment, newest first (kept 30 days). Use it
to catch up after downtime: filter by `objectId` (a booking id) or `type`.

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `type` | query | string | no |  |
| `objectId` | query | string (uuid) | no |  |
| `page` | query | integer (int32) | no |  |
| `pageSize` | query | integer (int32) | no |  |

Response `200`:

```json
{
  "data": [
    {
      "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "type": "string",
      "objectType": "string",
      "objectId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
      "createdAt": "2026-12-01T08:30:00Z",
      "status": "string",
      "payload": null
    }
  ],
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /webhook-events/{id}`

**Scope:** `webhooks:manage`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `id` | path | string (uuid) | yes |  |

Response `200`:

```json
{
  "data": {
    "id": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "type": "string",
    "objectType": "string",
    "objectId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "createdAt": "2026-12-01T08:30:00Z",
    "status": "string",
    "payload": null
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

## Account

### `GET /account`

Returns the calling API key's id and scopes. Use it to check a key works.

**Scope:** `account:read`

Response `200`:

```json
{
  "data": {
    "agencyId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "keyId": "7c1e0a52-3d4f-4c1b-9a51-2f7d8e6b1c90",
    "scopes": [
      "string"
    ]
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /account/balance`

Your wallet balance — what issuing a booking can spend. Check it before
issuing to avoid `account.insufficient_balance`.

**Scope:** `account:read`

Response `200`:

```json
{
  "data": {
    "balance": "string",
    "available": "string",
    "currency": "string",
    "active": true
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

### `GET /account/usage`

Your API usage per day, your limits (rate, daily and monthly search
quotas) and your look-to-book standing.

**Scope:** `account:read`

| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| `days` | query | integer (int32) | no |  |

Response `200`:

```json
{
  "data": {
    "from": "2026-12-01",
    "to": "2026-12-01",
    "days": [
      {
        "date": "2026-12-01",
        "requests": 0,
        "searches": 0,
        "holds": 0,
        "booked": 0,
        "bookedOtherChannels": 0,
        "throttled": 0,
        "clientErrors": 0,
        "serverErrors": 0
      }
    ],
    "totalRequests": 0,
    "totalSearches": 0,
    "totalBooked": 0,
    "lookToBookRatio": 0,
    "maxLookToBookRatio": 0,
    "ratioWindowDays": 0,
    "breachStatus": 0,
    "restriction": 0,
    "isSuspended": true,
    "suspendedReason": "string",
    "requestsPerMinute": 0,
    "searchesPerDay": 0,
    "searchesToday": 0,
    "searchesPerMonth": 0,
    "searchesThisMonth": 0
  },
  "meta": {
    "requestId": "string"
  },
  "pagination": {
    "page": 0,
    "pageSize": 0,
    "total": 0,
    "hasMore": true
  }
}
```

