# Book a ticket

Workflow
## Create the reservation

Creating a reservation temporarily holds an offer, guaranteeing its availability and price for a limited time.

### Request Body - Ticket/Session association

To create the reservation, you can use
the [POST /v1/booking/reservations/_bulk](/openapi/bookingreservation/api_v1bookingreservations_bulk_post)
endpoint by passing the following JSON body:

```json
{
  "items": [
    {
      "quantity": 1,
      "offer": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894",
      "ticketSessions": [
        {
          "ticket": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/0194ac40-fda7-78c1-8fcb-26fc2e2612d4"
        },
        {
          "ticket": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be",
          "session": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be/sessions/337177bc-e513-444f-bcee-49a3e25b48a3"
        }
      ]
    }
  ]
}
```

For the first ticket there is no session to choose we just need to pass the ticket iri.

For the second ticket we choose the session `337177bc-e513-444f-bcee-49a3e25b48a3` that occurs at `2025-06-07T20:00:00+02:00`.

### Request

```bash
curl --request POST \
  --url https://api.demo.korusticket.com/v1/booking/reservations/_bulk \
  -H 'accept: application/ld+json' \
  -H 'Authorization: Bearer {{YOUR_JWT_TOKEN}}' \
  -H 'Accept-Language: fr' \
  -d '{"items":[{"quantity":1,"offer":"/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894","ticketSessions":[{"ticket":"/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/0194ac40-fda7-78c1-8fcb-26fc2e2612d4"},{"ticket":"/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be","session":"/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be/sessions/337177bc-e513-444f-bcee-49a3e25b48a3"}]}]}'
```

### Response

```json
{
  "@context": {
    "@vocab": "https://api.demo.korusticket.com/docs.jsonld#",
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "reservations": "CreateReservationBulkOutput/reservations",
    "failedReservations": "CreateReservationBulkOutput/failedReservations"
  },
  "@type": "CreateReservationBulkOutput",
  "@id": "/.well-known/genid/78651cc4640b9253b7c0",
  "reservations": [
    {
      "@id": "/v1/booking/reservations/35e72d9b-0fdc-44e3-869c-e1781c14418e",
      "@type": "BookingReservation",
      "expired": false,
      "id": "35e72d9b-0fdc-44e3-869c-e1781c14418e",
      "createdAt": "2025-01-29T07:55:53+00:00",
      "totalAmountInclTax": "80.00",
      "totalAmountExclTax": "75.83",
      "expiresAt": "2025-01-29T08:10:53+00:00",
      "items": [
        {
          "@type": "ReservationItem",
          "@id": "/.well-known/genid/dbb1fda993fdc977bbab",
          "unitAmountInclTax": "80.00",
          "unitAmountExclTax": "75.83",
          "offer": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894",
          "product": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/products/0194abfe-1c04-7ade-9bc3-dbcfefb12652",
          "offerTickets": [
            {
              "@type": "ReservationItemOfferTicket",
              "@id": "/.well-known/genid/6fef51eaef68c943a2de",
              "ticket": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/0194ac40-fda7-78c1-8fcb-26fc2e2612d4"
            },
            {
              "@type": "ReservationItemOfferTicket",
              "@id": "/.well-known/genid/567f51eaef68c943aaa",
              "ticket": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be",
              "session": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be/sessions/337177bc-e513-444f-bcee-49a3e25b48a3"
            }
          ]
        }
      ],
      "organization": "/v1/ticketing/organizations/0194abdc-3a79-7ec3-b1b9-a1f291de587d",
      "order": null
    }
  ],
  "failedReservations": []
}
```

The response contains two arrays :

- the `“reservations”` array contains the successful reservations
- the `"failedReservations"` array contains offers that failed to be reserved


The `"expiresAt"` indicates when the reservation expires. After this timestamp, the offer will be released and the
reservation will become invalid for booking.

## Create the Order

To finalize the booking, call the [POST /v1/booking/orders/_bulk](/openapi/bookingorder/api_v1bookingorders_bulk_post)
endpoint. This converts reservations into actual bookings in
the ticket issuer's system. Make this call only after confirming that the customer's payment was successful.

To create the order, call the endpoint with the previously created reservation IDs and customer information. You must
also include your own reference ID in the `"externalReference"` field (required, max length 255 characters).

```json
{
  "reservations": [
    "/v1/booking/reservations/0194b10f-3ddd-70a5-a96a-d1026cd42746"
  ],
  "customer": {
    "firstname": "John",
    "lastname": "Doe",
    "email": "john.doe@gmail.com",
    "phone": "0612345678",
    "country": "FR",
    "language": "fr"
  },
  "externalReference": "CUSTOM_BOOKING_REF_NUMBER_003"
}
```

### Request

Execute the request as follows:

```bash
curl --request POST \
  --url https://api.demo.korusticket.com/v1/booking/orders/_bulk \
  -H 'accept: application/ld+json' \
  -H 'Authorization: Bearer {{YOUR_JWT_TOKEN}}' \
  -d '{"reservations":["/v1/booking/reservations/0194b10f-3ddd-70a5-a96a-d1026cd42746"],"customer":{"firstname":"John","lastname":"Doe","email":"john.doe@gmail.com","phone":"0612345678","country":"FR","language":"fr"}}'
```

### Response

```json
{
  "@context": {
    "@vocab": "https://api.demo.korusticket.com/docs.jsonld#",
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "orders": "CreateOrderBulkOutput/orders"
  },
  "@type": "CreateOrderBulkOutput",
  "@id": "/.well-known/genid/ca4347e0ca0909425dee",
  "orders": [
    {
      "@id": "/v1/booking/orders/0194b132-448c-7d1b-bb13-f8e09ae5c18f",
      "@type": "BookingOrder",
      "id": "0194b132-448c-7d1b-bb13-f8e09ae5c18f",
      "createdAt": "2025-01-29T08:34:09+00:00",
      "organization": "/v1/organizations/0194abdc-3a79-7ec3-b1b9-a1f291de587d",
      "reference": "KT-ORD-6799E80128885",
      "externalReference": "CUSTOM_BOOKING_REF_NUMBER_003",
      "totalAmountInclTax": "80.00",
      "totalAmountExclTax": "75.83",
      "reservation": "/v1/booking/reservations/0194b10f-3ddd-70a5-a96a-d1026cd42746",
      "customer": [],
      "items": [
        {
          "@type": "OrderItem",
          "@id": "/.well-known/genid/fc26307a17a3ad7720bc",
          "unitAmountInclTax": "80.00",
          "unitAmountExclTax": "75.83",
          "product": "/v1/ticketing/catalogs/0194d07e-aa37-7171-820c-712e91552451/products/0194abfe-1bdb-7b12-af59-ad81ae443689",
          "tickets": [
            {
              "@type": "ReservationItemOfferTicket",
              "@id": "/.well-known/genid/6fef51eaef68c943a2de",
              "ticket": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/0194ac40-fda7-78c1-8fcb-26fc2e2612d4",
              "voucher": null,
              "occursAt": null,
              "requiredBeneficiaryFields": [],
              "beneficiary": null,
              "beneficiaryDesignationDeadline": null,
              "beneficiaryAmendable": true,
              "status": "validated",
              "seating": null
            },
            {
              "@type": "ReservationItemOfferTicket",
              "@id": "/.well-known/genid/567f51eaef68c943aaa",
              "ticket": "/v1/ticketing/catalogs/0194abdc-3a71-72b0-a9b9-89d4be0cd73e/offers/0194ac40-fda7-78c1-8fcb-26fc2df25894/tickets/7522b8de-37a2-458d-b099-6d515b0739be",
              "voucher": "8553501100013199",
              "occursAt": "2025-06-07T20:00:00+02:00",
              "requiredBeneficiaryFields": [],
              "beneficiary": null,
              "beneficiaryDesignationDeadline": "2025-12-31T18:30:00+01:00",
              "beneficiaryAmendable": true,
              "status": "validated",
              "seating": {
                "@type": "TicketSeating",
                "@id": "/.well-known/genid/af3f16442024ed4d37cb",
                "seatNumber": "227",
                "level": "EST/INT-127-128-129-130-131",
                "row": "26",
                "stand": "EST",
                "stair": "131",
                "gate": "V"
              }
            }
          ]
        }
      ],
      "documents": [
        "/v1/booking/orders/0194b132-448c-7d1b-bb13-f8e09ae5c18f/documents/0194b132-449c-79cd-9da1-50be439b6e9d"
      ]
    }
  ]
}
```

In the response you can see the following fields:

- `"reference"` is the Korus Ticket API internal order reference
- `“externalReference”` is your own order reference. You can call
the [POST v1/booking/orders/_bulk](/openapi/bookingorder/api_v1bookingorders_bulk_post) endpoint multiple times with
the same value in the `“externalReference”` field to group all orders in the same booking.
- `"items”`  contains the detail of reserved products and their prices as well as tickets and associated sessions
- `“documents”` lists the available order documents. These are typically the customer's tickets for the Event. You will
need to call
the [PATCH /v1/booking/orders/{orderId}/documents](/openapi/bookingorderdocument/api_v1bookingorders_orderiddocuments_id_patch)
endpoint to get the document's public URL.


## Expired Reservation error

If one or more reservations passed to
the [POST v1/booking/orders/_bulk](/openapi/bookingorder/api_v1bookingorders_bulk_post) endpoint are expired, you will get
an HTTP 422 response
with the following violations:

```json
{
  "@context": "/contexts/ConstraintViolationList",
  "@id": "/validation_errors/d53a91b0-def3-426a-83d7-269da7ab4200",
  "@type": "ConstraintViolationList",
  "status": 422,
  "violations": [
    {
      "propertyPath": "reservations[0].expired",
      "message": "La réservation a expiré",
      "code": "d53a91b0-def3-426a-83d7-269da7ab4200"
    }
  ],
  "detail": "reservations[0].expired: La réservation a expiré",
  "description": "reservations[0].expired: La réservation a expiré",
  "type": "/validation_errors/d53a91b0-def3-426a-83d7-269da7ab4200",
  "title": "An error occurred"
}
```

## Get an `OrderDocument` download Url

To access orders documents, including events tickets, please refer to [this section](/how-to/get-order-documents).