curl "$UNIFYSTAYS_BASE_URL/hotels/book/ubk_CrSjBQebS4fq/confirm-hold" \
-X POST \
-H "content-type: application/json" \
-H "x-api-key: $UNIFYSTAYS_API_KEY" \
-d '{
"accepted_offer_id": "off_65db5f20d91b47d3a73d834dfa44c50e"
}'
{
"contract_version": "2",
"success": true,
"message": "Booking request accepted and is being processed.",
"data": {
"booking_id": "ubk_CrSjBQebS4fq",
"accepted_offer_id": "off_65db5f20d91b47d3a73d834dfa44c50e",
"status": "PROCESSING",
"is_terminal": false,
"provider": {
"code": "TRIPJACK",
"booking_id": "TJS123456789",
"booking_code": null,
"hotel_confirmation_number": null,
"hotel_confirmation_status": null,
"hotel_confirmation_note": null,
"hotel_contact_phone": null,
"hotel_contact_name": null
},
"next_poll_after_ms": 5000,
"processing_reason": "SUPPLIER_CONFIRMATION_PENDING",
"action_required": false,
"available_actions": ["GET_STATUS", "GET_DETAILS"],
"review_expires_at": "2026-09-14T12:27:00.000Z",
"hold_deadline_at": "2026-09-20T18:29:59.000Z",
"created_at": "2026-09-14T12:12:11.000Z",
"updated_at": "2026-09-16T08:00:10.000Z"
}
}
Confirm Hold
Confirm a TripJack held booking before its supplier deadline.
curl "$UNIFYSTAYS_BASE_URL/hotels/book/ubk_CrSjBQebS4fq/confirm-hold" \
-X POST \
-H "content-type: application/json" \
-H "x-api-key: $UNIFYSTAYS_API_KEY" \
-d '{
"accepted_offer_id": "off_65db5f20d91b47d3a73d834dfa44c50e"
}'
{
"contract_version": "2",
"success": true,
"message": "Booking request accepted and is being processed.",
"data": {
"booking_id": "ubk_CrSjBQebS4fq",
"accepted_offer_id": "off_65db5f20d91b47d3a73d834dfa44c50e",
"status": "PROCESSING",
"is_terminal": false,
"provider": {
"code": "TRIPJACK",
"booking_id": "TJS123456789",
"booking_code": null,
"hotel_confirmation_number": null,
"hotel_confirmation_status": null,
"hotel_confirmation_note": null,
"hotel_contact_phone": null,
"hotel_contact_name": null
},
"next_poll_after_ms": 5000,
"processing_reason": "SUPPLIER_CONFIRMATION_PENDING",
"action_required": false,
"available_actions": ["GET_STATUS", "GET_DETAILS"],
"review_expires_at": "2026-09-14T12:27:00.000Z",
"hold_deadline_at": "2026-09-20T18:29:59.000Z",
"created_at": "2026-09-14T12:12:11.000Z",
"updated_at": "2026-09-16T08:00:10.000Z"
}
}
booking_mode: "HOLD", wait for
ON_HOLD, confirm hold.
Holds exist only for TripJack offers. You can tell from the prebook response:
data.offer.lifecycle.available_booking_modes is ["INSTANT", "HOLD"],
hold_allowed is true, and hold_deadline shows until when the supplier lets
you hold. Every other offer lists only INSTANT.
The hold flow
Prebook and check the offer allows a hold
lifecycle.hold_allowed is
true and available_booking_modes contains HOLD.Create the booking as a hold
"booking_mode": "HOLD". It returns PROCESSING. A hold request whose
deadline is less than 2 days away goes to AWAITING_REVIEW instead.Wait for ON_HOLD
ON_HOLD (a booking.updated webhook announces it, or
poll Get Booking Status). Now
hold_deadline_at (UTC) is set, processing_reason is
HOLD_CONFIRMATION_REQUIRED, action_required is true and
available_actions contains CONFIRM_HOLD.Confirm before the deadline
accepted_offer_id. The booking moves
to PROCESSING, then CONFIRMED.hold_deadline_at. TripJack may cancel an unconfirmed hold
automatically after the deadline. Do not rely on the hold lasting longer.Request
curl "$UNIFYSTAYS_BASE_URL/hotels/book/ubk_CrSjBQebS4fq/confirm-hold" \
-X POST \
-H "content-type: application/json" \
-H "x-api-key: $UNIFYSTAYS_API_KEY" \
-d '{
"accepted_offer_id": "off_65db5f20d91b47d3a73d834dfa44c50e"
}'
| Field | Where to get it | How to use it |
|---|---|---|
booking_id (path) | data.booking_id from Create Booking. | A booking whose status is ON_HOLD. |
accepted_offer_id | data.accepted_offer_id of the booking (same as the prebook offer_id). | Must equal the booking’s accepted offer, otherwise ACCEPTED_OFFER_MISMATCH. Unknown body fields are rejected. |
Response
{
"contract_version": "2",
"success": true,
"message": "Booking request accepted and is being processed.",
"data": {
"booking_id": "ubk_CrSjBQebS4fq",
"accepted_offer_id": "off_65db5f20d91b47d3a73d834dfa44c50e",
"status": "PROCESSING",
"is_terminal": false,
"provider": {
"code": "TRIPJACK",
"booking_id": "TJS123456789",
"booking_code": null,
"hotel_confirmation_number": null,
"hotel_confirmation_status": null,
"hotel_confirmation_note": null,
"hotel_contact_phone": null,
"hotel_contact_name": null
},
"next_poll_after_ms": 5000,
"processing_reason": "SUPPLIER_CONFIRMATION_PENDING",
"action_required": false,
"available_actions": ["GET_STATUS", "GET_DETAILS"],
"review_expires_at": "2026-09-14T12:27:00.000Z",
"hold_deadline_at": "2026-09-20T18:29:59.000Z",
"created_at": "2026-09-14T12:12:11.000Z",
"updated_at": "2026-09-16T08:00:10.000Z"
}
}
booking.confirmed webhook or poll
Get Booking Status until the status is
CONFIRMED, then issue the voucher. Do not call confirm-hold again for an
uncertain outcome; it is verified automatically.
Outcomes
| Response | Booking status | Meaning | Client action |
|---|---|---|---|
200 | PROCESSING or CONFIRMED | The supplier accepted the confirmation, or its answer is uncertain (timeout, network error, supplier 5xx). | Wait for booking.updated / booking.confirmed webhooks or poll GET /hotels/book/{booking_id}. Do not call confirm-hold again; an uncertain outcome is reconciled automatically. |
409 HOLD_CONFIRMATION_REJECTED | ON_HOLD | The supplier definitively refused the confirmation (for example a TripJack 4xx). Nothing was confirmed and the hold is unchanged. | Treat the confirmation as failed (for example release any amount charged for it). The hold can still be confirmed again before hold_deadline_at or cancelled. |
409 ACCEPTED_OFFER_MISMATCH, HOLD_NOT_ALLOWED, HOLD_DEADLINE_EXPIRED, HOLD_CONFIRMATION_FAILED | unchanged | The request was refused before reaching the supplier. | Fetch the booking before retrying. |
PROCESSING or CONFIRMED
(with the right accepted_offer_id) is harmless: it returns the current state
and does not send a second confirmation.
A HOLD_CONFIRMATION_REJECTED response is also announced as a
booking.updated webhook moving the booking from PROCESSING back to
ON_HOLD. Its details include the supplier’s HTTP status:
{
"code": "HOLD_CONFIRMATION_REJECTED",
"message": "TripJack did not accept the hold confirmation; the hold is unchanged.",
"details": {
"booking_id": "ubk_CrSjBQebS4fq",
"status": "ON_HOLD",
"supplier": "TRIPJACK",
"supplier_http_status": 403,
"supplier_error_code": null,
"retryable": false
}
}
Error codes
| Code (HTTP) | Meaning | What to do |
|---|---|---|
BOOKING_NOT_FOUND (404) | No such booking in your organization. | Check the booking_id. |
ACCEPTED_OFFER_MISMATCH (409) | accepted_offer_id is not the one stored with this booking. | Read it from the booking and resend. |
HOLD_NOT_ALLOWED (409) | The booking is not an active hold (not ON_HOLD, or not a TripJack hold). | Read the booking status; do not retry. |
HOLD_DEADLINE_EXPIRED (409) | hold_deadline_at has passed. | The hold can no longer be confirmed. Check the status; create a new booking if the guest still wants the room. |
HOLD_CONFIRMATION_FAILED (409) | The hold has no supplier booking reference yet. | Read the booking again; contact support if it persists. |
HOLD_CONFIRMATION_REJECTED (409) | Supplier refused the confirmation. | See the table above. |
HOTEL_MAPPING_UNVERIFIED, HOTEL_MAPPING_CHECK_PENDING (409) | The supplier’s hotel listing failed or is still in verification. | Retry shortly for PENDING; contact support for UNVERIFIED. |
PROVIDER_OPERATION_NOT_SUPPORTED (501) | Hold confirmation is unavailable for this supplier. | Contact support. |
If you do nothing (the hold lapses)
You do not have to confirm. If the guest does not pay, leave the hold alone, or cancel it yourself while it isON_HOLD (CANCEL is in available_actions;
see Cancellation Quote and
Cancel Booking). After hold_deadline_at the
supplier may cancel it, and confirm-hold returns HOLD_DEADLINE_EXPIRED. Keep
checking the booking status for the final state; never show a guest a held
booking as confirmed.
This follows TripJack’s hold-then-confirm process. See the
TripJack API documentation.Authorizations
Environment-specific API key created in the Unifystays portal
Headers
Hotel API contract version. Optional: 2 is the current version and the default.
2 Path Parameters
Unifystays booking ID (ubk_...) of a booking whose status is ON_HOLD and whose available_actions contains CONFIRM_HOLD.
"ubk_eGQ0dW9uV1Vi"
Body
The accepted offer ID stored with this held booking. Prevents confirming a different revision accidentally.
Response
The confirmation was accepted (status PROCESSING, then CONFIRMED) or its outcome is uncertain and is being verified (PROCESSING). Do not call confirm-hold again; wait for booking webhooks or poll Get Booking Status. A booking that is already PROCESSING or CONFIRMED returns its current state.
Response contract version. Always "2".
"2"
false only when the booking status is FAILED. true for every other status, including AWAITING_REVIEW and PROCESSING, which are not confirmations. Read data.status for the real state.
true
Human-readable summary for logs and support; for FAILED it carries the reason. Do not parse it; use data.status.
"Booking request accepted and is being processed."
The booking's current state.
Show child attributes
Show child attributes