Updated 12 Nov 2026

Pattern: create a booking safely

Developers (API)REST API v1

Every booking made in your system must also be written to Effective Tours as a reservation, because availability is computed from units and reservations. There is no operation that pushes availability. This pattern shows how to write a reservation so that a timeout or a retry never creates a second one. Read Integration patterns first for the shared principles.

Write calls are real. There is no sandbox: a reservation goes straight into the calendar and updates the connected channels. Test with dates far in the future, create only a few bookings, cancel each one right after (see Pattern: modify and cancel), and connect OTAs only after the integration works.

Responsibility (ruling R4). A reservation written through the API does not run the follow-up actions of a reservation entered in the Effective Tours interface: no guest voucher or confirmation e-mail, and no owner notification. Your system is responsible for those communications.

Steps

1. Choose the room or the rate

You book either a specific room (room_id, which wins when supplied) or a room type (rate_id with no room_id, and the server assigns an available room of that type). Take the ids from your mapping table (Pattern: map rooms and rates). Read them again if you are unsure. See GET /hotels/{id}/rooms and GET /hotels/{id}/rates. Here {id} is the hotel id.

curl "https://api.effectivetours.com/v1/hotels/{id}/rooms" \
  -H "Authorization: Bearer $ET_API_KEY"

Example response (abbreviated: one room shown):

[
  {
    "id": 2001,
    "name": "Double Room 1",
    "sgl": false,
    "dbl": true,
    "tpl": false,
    "apartment": false,
    "is_virtual": false,
    "rates": [
      {
        "id": 3001,
        "name": "Standard rate",
        "food": "RO"
      }
    ]
  }
]
curl "https://api.effectivetours.com/v1/hotels/{id}/rates" \
  -H "Authorization: Bearer $ET_API_KEY"

Example response (abbreviated: one rate shown):

[
  {
    "id": 3001,
    "name": "Standard rate",
    "food": "RO",
    "sgl": false,
    "dbl": true,
    "tpl": false,
    "full": false,
    "connections": {}
  }
]

2. Create the reservation with a reference

Put your own unique booking id in reference. The spec says: when a non-empty reference is supplied and a live reservation already exists for that (company, reference), the existing reservation is returned with status 200 instead of creating a duplicate, and a replay never double-books. Another company's reservation with the same reference is never returned. accommodation is sgl, dbl, tpl or full (lower case; full is the whole unit). The OpenAPI document types it as a plain string and lists no values; any other value is refused with 422. See POST /hotels/{hotel_id}/reservations.

Request body and call:

curl "https://api.effectivetours.com/v1/hotels/{hotel_id}/reservations" \
  -X POST \
  -H "Authorization: Bearer $ET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"room_id": 2001, "accommodation": "dbl", "checkin": "2027-06-10", "checkout": "2027-06-12", "adults": 2, "children": 0, "is_accepted": false, "reference": "PMS-2027-0001", "first_name": "Jane", "last_name": "Example", "email": "[email protected]", "price": "250.00"}'

Example response (status 201 for a new reservation; abbreviated):

{
  "id": 4001,
  "checkin": "2027-06-10",
  "checkout": "2027-06-12",
  "is_accepted": false,
  "adults": 2,
  "children": 0,
  "is_fake": false,
  "room": {
    "id": 2001,
    "name": "Double Room 1",
    "sgl": false,
    "dbl": true,
    "tpl": false,
    "apartment": false,
    "is_virtual": false
  },
  "rate": {
    "id": 3001,
    "name": "Standard rate",
    "food": "RO"
  },
  "channel": null,
  "first_name": "Jane",
  "last_name": "Example",
  "price": "250.00",
  "revenue": null,
  "comment": "",
  "reference_code": "PMS-2027-0001"
}

Save the returned id next to your own booking id.

3. Handle the refusals

400 means the room is not available for the period, and 409 means no room of the requested type is available for the dates (when you book by rate_id, detail is a list). Neither creates a reservation. Offer the guest other dates or another room type. Do not retry the same request in a loop. See the table at the end of the page.

4. Read the reservation back

After a timeout or any doubt, read the reservation by id, or list the window and look for your reference_code. See GET /hotels/{hotel_id}/reservations/{id}.

curl "https://api.effectivetours.com/v1/hotels/{hotel_id}/reservations/{id}" \
  -H "Authorization: Bearer $ET_API_KEY"

Example response (abbreviated):

{
  "id": 4001,
  "checkin": "2027-06-10",
  "checkout": "2027-06-12",
  "is_accepted": false,
  "adults": 2,
  "children": 0,
  "reference_code": "PMS-2027-0001"
}

5. Accept the booking

is_accepted is the acceptance status. Set it with PATCH when your system confirms the booking. Only the company that owns the reservation's room (the hotel owner) may update a reservation; for any other company it answers 404. The body carries the reservation id, which must match the id in the URL. Send only the fields you change. See PATCH /hotels/{hotel_id}/reservations/{reservation_id}.

curl "https://api.effectivetours.com/v1/hotels/{hotel_id}/reservations/{reservation_id}" \
  -X PATCH \
  -H "Authorization: Bearer $ET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": 4001, "is_accepted": true}'

Example response (abbreviated):

{
  "id": 4001,
  "checkin": "2027-06-10",
  "checkout": "2027-06-12",
  "is_accepted": true,
  "adults": 2,
  "children": 0,
  "reference_code": "PMS-2027-0001"
}

Retry rules

  • Retry a create only with the same reference. A new reference on a retry can book twice.
  • Retry only after a timeout, a network error or 503. After 400 or 409 change the request instead.
  • Keep your booking id and the Effective Tours id together, so you can cancel by either.

Related method page: Reservations.

What can go wrong

StatusBodyWhat to do
400{"detail":"Room is not available for this period"}The room is taken for these dates. Choose other dates or another room.
409detail is a list (auto-assign by rate_id)No room of the requested type is available for the dates. Offer other dates.
409{"error":"company_moved"}Note the key is error, not detail. The spec does not describe it further: stop retrying and contact us through the contact form.
403{"detail":"You are not allowed to access this hotel"}Your key has no write access to this hotel.
404{"detail":"Hotel not found"}The hotel id is wrong or not accessible.
404{"detail":"Reservation not found"}On PATCH or GET: the reservation is not there, or it is not yours to see or change.
410{"detail":"Requested HotelID: <id> not found."}The hotel was permanently removed.
422standard validation errorFix the body (a room, rate, date or guest field).
401{"detail":"Invalid API key"}Check the key.
503{"detail":"Authentication backend unavailable"}Read first (step 4); repeat the create with the same reference only if nothing was created.
429not specifiedThere is no published rate limit. Back off.