# B2B Seat Fulfilment API

URL: https://all-ancillaries-9z82vkas5-britoncos-projects.vercel.app/docs/b2b-fulfilment
Updated: 2026-04-23

Server-to-server API for fulfilling seat selections against an existing booking.

# B2B Seat Fulfilment API

Trigger seat fulfilment for one or more passengers on a PNR without using
the AllAncillaries UI. Send us a JSON payload describing the seats you
want assigned and we respond with whether **none, some or all** of those
seats were successfully fulfilled.

This endpoint uses the **same authentication** as the encrypted seatmap
checkout link API. If you already have a partner integration that
generates seatmap links, you can re-use the same `api_key` / `api_secret`.

---

## Endpoint

```
POST https://<your-allancillaries-host>/api/v1/fulfil-seats
Content-Type: application/json
Authorization: Bearer <token>
```

Tokens are obtained from `POST /generate-bearer-token` using your brand
`api_key` and `api_secret`. Tokens are valid for 24 hours by default.

---

## Request payload

| Field       | Type            | Required | Notes                                                                                  |
| ----------- | --------------- | -------- | -------------------------------------------------------------------------------------- |
| `pnr`       | string          | yes      | The booking reference, e.g. `"ABC123"`.                                                |
| `seats`     | array of object | yes      | One entry per seat you want assigned. Must contain at least one seat.                  |
| `lastName`  | string          | no       | Last name of the booking. Stored against the transaction record for traceability.      |
| `targetCity`| string          | no       | Overrides the servicing office the booking is actioned against. Defaults to the booking's own. |

Each `seats[]` entry:

| Field            | Type   | Required | Notes                                                              |
| ---------------- | ------ | -------- | ------------------------------------------------------------------ |
| `passengerName`  | string | yes\*    | Full passenger name as it appears in the PNR, e.g. `"John Smith"`. |
| `seatNumber`     | string | yes      | Seat designation, e.g. `"12A"`.                                    |
| `segmentNumber`  | string | yes      | Segment number on the PNR (e.g. `"1"`) **or** a carrier+flight-number string (e.g. `"AV312"`). |
| `nameNumber`     | string | no       | Sabre name number (e.g. `"1.1"`). Skips lookup if supplied.        |

\* Either `passengerName` or `nameNumber` must be present.

### Example request

```json
{
  "pnr": "ABC123",
  "lastName": "SMITH",
  "seats": [
    {
      "passengerName": "John Smith",
      "seatNumber": "12A",
      "segmentNumber": "1"
    },
    {
      "passengerName": "Jane Smith",
      "seatNumber": "12B",
      "segmentNumber": "1"
    }
  ]
}
```

You can also identify segments by carrier + flight number instead of a positional index:

```json
{
  "pnr": "ABC123",
  "lastName": "ANDERSON",
  "seats": [
    {
      "passengerName": "Rebecca Anderson",
      "seatNumber": "12C",
      "segmentNumber": "AV312"
    },
    {
      "passengerName": "Rebecca Anderson",
      "seatNumber": "22K",
      "segmentNumber": "AV522"
    }
  ]
}
```

---

## Response

The HTTP status code reflects the fulfilment outcome:

| Status | Meaning                                       |
| ------ | --------------------------------------------- |
| `200`  | All requested seats were successfully fulfilled. |
| `207`  | Some seats fulfilled, some failed.            |
| `422`  | None of the requested seats were fulfilled.   |
| `400`  | Payload was missing required fields.          |
| `401`  | Missing or invalid bearer token.              |
| `502`  | Sabre fulfilment call raised an exception.    |

### Example success response (`200`)

```json
{
  "success": true,
  "outcome": "all_fulfilled",
  "transaction_id": "B2B-7K2H9XQM4N3D",
  "pnr": "ABC123",
  "brand": "examplebrand",
  "target_city": "XXXX",
  "summary": {
    "requested": 2,
    "fulfilled": 2,
    "failed": 0,
    "outcome": "all_fulfilled"
  },
  "fulfilled_seats": [
    {"passengerName": "John Smith", "seatNumber": "12A", "segmentNumber": "1", "status": "fulfilled"},
    {"passengerName": "Jane Smith", "seatNumber": "12B", "segmentNumber": "1", "status": "fulfilled"}
  ],
  "failed_seats": [],
  "billing": {
    "currency": "AUD",
    "ratePerFulfilledSeat": 1.5,
    "billableSeats": 2,
    "billableAmount": 3.0
  }
}
```

### Example partial response (`207`)

```json
{
  "success": true,
  "outcome": "partially_fulfilled",
  "transaction_id": "B2B-7K2H9XQM4N3D",
  "summary": {"requested": 2, "fulfilled": 1, "failed": 1, "outcome": "partially_fulfilled"},
  "fulfilled_seats": [
    {"passengerName": "John Smith", "seatNumber": "12A", "segmentNumber": "1", "status": "fulfilled"}
  ],
  "failed_seats": [
    {
      "passengerName": "Jane Smith",
      "seatNumber": "12B",
      "segmentNumber": "1",
      "status": "failed",
      "reason": "Flight under airport control - seat could not be assigned",
      "errorType": "AIRPORT_CONTROL"
    }
  ],
  "billing": {"currency": "AUD", "ratePerFulfilledSeat": 1.5, "billableSeats": 1, "billableAmount": 1.5}
}
```

---

## Billing

* Settlement is **post-paid**, invoiced monthly.
* You are billed **AUD $1.50** for **each successfully fulfilled seat**.
* Failed seats are recorded in our database for transparency but are
  **not billable**.
* Each call returns a `billing` block summarising the billable amount
  for that transaction so you can reconcile internally.

Every transaction is stored in our database with:

* a unique `transaction_id` (returned in the response),
* per-seat `TransactionItem` rows describing exactly what was requested,
* per-seat `Fulfillment` rows recording success or failure with the
  underlying reason. This keeps the audit trail clear regardless of
  whether the request fully, partially or completely failed.

---

## Python snippet

A copy-paste ready Python example is available at:

```
public_docs/python/fulfil_seats_example.py
```

It performs the bearer token exchange and a single fulfilment call, and
prints the per-seat results.
