Hotel guides

Booking statuses

Creating a booking starts a process that doesn't always finish in one request. The booking's state tells you where it is and what, if anything, you need to do.

States at a glance

StateMeaningWhat to do
confirmedBooked and confirmed.Show the confirmation; fetch the voucher.
supplier_pendingConfirmation still in progress. Credit is reserved for a paid booking; a hold that is still pending has nothing paid yet.Check again every 15 s (below). Don't book again.
heldRoom reserved without payment until a deadline.Pay before order.held.paymentDeadline, or cancel.
failedNot booked. Nothing is charged.Price-check and try again with a new idempotency key.
manual_reviewOur operations team needs to finish this booking by hand.Don't rebook. We'll resolve it and update the state.
cancel_requestedA cancellation is in progress.Wait. It moves to cancelled, to manual_review if it can't be completed automatically, or back to confirmed.
cancelledCancelled.Nothing, unless a refund is due.
refund_pendingCancelled; a refund is being processed.Nothing.
refundedCancelled and refunded.Nothing.

You may briefly see price_checked or credit_approved on a booking that is still being created. Treat them like supplier_pending. New states may be added; treat any state you don't recognise as pending and check again.

What POST /bookings returns

The create call returns 201 with the booking's ID, your reference and its state:

Response · 201
{ "data": { "bookingId": "66f1d2c4e4b0c1d2e3f4b010", "orderRef": "RV-2026-4CD5ADB2", "state": "confirmed" }, "meta": {}, "error": null }

Store bookingId (for API calls) and orderRef (the reference people use — quote it to our support team) against your own order before doing anything else with the response.

Waiting for confirmation

Most bookings confirm inside the create call. Some inventory confirms asynchronously, and a flight that is paid but not yet ticketed waits for its tickets; those return supplier_pending. Ask for an update with POST /bookings/:id/refresh-status, which checks with the inventory source and returns the latest state:

Polling
async function waitForConfirmation(bookingId) {
  // Check every 15 s for up to 10 minutes.
  for (let tries = 0; tries < 40; tries++) {
    const { data } = await call('POST', '/bookings/' + bookingId + '/refresh-status');
    if (data.state !== 'supplier_pending') return data.state;
    await sleep(15_000);
  }
  return 'supplier_pending'; // keep checking GET /bookings/:id in the background
}
  • Poll every 15 seconds for up to 10 minutes. Many pending bookings settle within a few minutes, but some take longer.
  • If it is still pending after that, tell the traveller confirmation is on its way and keep checking GET /bookings/:id every few minutes. If it is still pending close to travel, email support with the orderRef.
  • The API doesn't send webhooks. The booking's agent also gets an email when it is confirmed or fails — for bookings made with an API key, that is the admin who created the key. Travellers aren't emailed automatically.

Reading a booking

Request · cURL
curl "https://api.roaveagents.com/api/v1/bookings/66f1d2c4e4b0c1d2e3f4b010" \
  -H "X-API-Key: $ROAVE_API_KEY"
Response · 200 (abridged)
{
  "data": {
    "order": {
      "orderRef": "RV-2026-4CD5ADB2",
      "state": "confirmed",
      "paymentMethod": "credit",
      "totalSell": { "amountMinor": 51120, "currency": "USD" },
      "travelers": [ ... ]
    },
    "lineItems": [
      {
        "productType": "hotel",
        "state": "confirmed",
        "supplierConfirmationId": "4471902",
        "sell": { "amountMinor": 51120, "currency": "USD" },
        "details": { "hotelConfirmationRef": "88213540", ... }
      }
    ],
    "cancellationPolicy": { "refundable": true, "deadlines": [ ... ] },
    "earnings": { ... }
  },
  "meta": {},
  "error": null
}

A booking is an order with one or more lineItems. For hotels, supplierConfirmationId is the booking reference with the inventory source. The property's own number — the one front desks recognise — is in the line item's details.hotelConfirmationRef, or details.hotelConfirmationRefs with one entry per room. If our operations team records a number, it appears as the line item's hotelConfirmationNumber. The simplest way to show it is the voucher's hotelConfirmationNumber, which resolves all of these. The hotel's number can arrive some time after the booking confirms, so read it again closer to arrival if it's missing.

Failed bookings

A failed booking was declined — most often because the room sold out between price-check and booking. Nothing is charged. order.failureReason, when present, is a short machine code such as supplier_rejected — log it, but don't parse it or show it to travellers; it doesn't carry the inventory source's reason, and other values may appear. The quote goes back to price-checked, so you can:

  1. price-check the same quote again (or pick another rate if it's gone), then
  2. book with a new Idempotency-Key. Reusing the old key replays the failure.

Manual review

manual_review means the outcome needs a person: the inventory source gave an ambiguous answer, or a cancellation couldn't be completed automatically — most flight cancellations land here. Our operations team resolves these. Don't create a replacement booking — you could end up with two. If the traveller is travelling soon, email support@roaveagents.com with the orderRef.

Holds

A hold reserves a hotel room now and lets you pay later — useful while a client decides. Send hold: true when you book:

POST /bookings body
{
  "quoteId": "66f1c0b8e4b0c1d2e3f4a7a2",
  "paymentMethod": "credit",
  "hold": true,
  "travelers": [
    { "firstName": "Anna", "lastName": "Smith", "email": "anna.smith@example.com", "phone": "+447700900123", "roomIndex": 0 },
    { "firstName": "Ben", "lastName": "Smith", "roomIndex": 0 }
  ]
}
  • Hotels only, and only on fully refundable rates whose free-cancellation deadline is still in the future. Otherwise you get 400 hold_not_eligible.
  • The booking comes back held. order.held.paymentDeadline is 24 hours before the free-cancellation deadline.
  • Pay before the deadline with POST /bookings/:id/pay. The agent on the booking gets reminder emails as it approaches.
  • Unpaid holds are cancelled automatically once the payment deadline passes, so the room is released before any cancellation charge applies. Paying after the deadline is refused.
Pay for a hold
curl -X POST "https://api.roaveagents.com/api/v1/bookings/66f1d2c4e4b0c1d2e3f4b010/pay" \
  -H "X-API-Key: $ROAVE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 2f5a1d8e-3c4b-4e6f-8a9b-7c1d2e3f4a5b" \
  -d '{ "paymentMethod": "credit" }'

Listing bookings

GET /bookings lists every booking your agency has made, newest first. Filter with state (confirmed, held, cancelled, failed), trip (upcoming, traveling, past), status (active, cancelled) and q (reference, guest or hotel name). See the reference for every option.

A trip filter on its own leaves out cancelled bookings — including those being cancelled or refunded. To list cancelled trips, add status=cancelled or state=cancelled.

Request · cURL
curl "https://api.roaveagents.com/api/v1/bookings?state=confirmed&trip=upcoming&limit=50" \
  -H "X-API-Key: $ROAVE_API_KEY"