APIs behind the Quick Book flow for booking a conference room (or bookable private office) from the listing screen.
Intended audience: web frontend team integrating the Quick Book flow.
Authorization header (same as all other authenticated endpoints).application/jsonyyyy-MM-ddTHH:mm (no seconds, no timezone) — e.g. 2026-07-01T10:00yyyy-MM-dd HH:mm (space, not T) — e.g. 2026-07-01 10:00Every endpoint wraps its payload in a standard envelope:
{
"message": "string | null",
"data": { "...": "endpoint-specific payload, may be null on failure" }
}
The Quick Book UI is the same in both cases, but the API it calls depends on whether the product requires payment:
| Condition | API called | Next step |
|---|---|---|
| Payment not required | POST /checkout/api/v1/quick-book (§1) |
Booking is created immediately → confirmation screen |
| Payment required | POST /checkout/api/v1/cart (§2) |
A cart is created → redirect to the cart / payment flow |
Both paths are reachable from the Quick Book UI — a payment-required product does not call /quick-book at all; it goes through cart creation.
is_payment_required flagThe branch is decided by a boolean flag the backend returns, is_payment_required:
data.is_payment_required), returned by the listing endpoints:POST /catalogue/api/v1/products/room-listPOST /catalogue/api/v1/products/bpo-listboolean, nullable. When absent/null, the client treats it as false (i.e. defaults to the direct /quick-book path).Client flow (for reference): the listing response's is_payment_required is carried on the product-listing model and read at swipe/book time (e.g. productListing.isPaymentRequired ?? false), then passed into the book action as the isPaymentRequired argument. That value is what the branch at space_listing_bloc.dart:767 (if (event.isPaymentRequired)) switches on:
is_payment_required |
Branch |
|---|---|
false (or null) |
§1 — POST /checkout/api/v1/quick-book |
true |
§2 — POST /checkout/api/v1/cart |
Books the product immediately for the given time window. No cart, no payment.
POST /checkout/api/v1/quick-book
| Field | Type | Required | Description |
|---|---|---|---|
product_uid |
string | ✅ | Room/product identifier |
product_type |
string | ✅ | "CONFERENCE_ROOM" for quick book |
start_time |
string | ✅ | Booking start, yyyy-MM-ddTHH:mm |
end_time |
string | ✅ | Booking end, yyyy-MM-ddTHH:mm (= start + duration) |
slots |
array | ❌ | Only for multi-date bookings. Each item: { "start_time": "...", "end_time": "..."? } (end_time optional). Omit for a standard single conference-room booking. |
{
"product_uid": "room-123",
"product_type": "CONFERENCE_ROOM",
"start_time": "2026-07-01T10:00",
"end_time": "2026-07-01T10:30"
}
200{
"message": null,
"data": { "order_uid": "ORD-789456123" }
}
| Field | Type | Description |
|---|---|---|
data.order_uid |
string | Created booking/order ID. Use it for the confirmation screen and later lookups. |
409 Conflict); message carries a user-displayable reason. Recommended UX: prompt the user to pick another slot.data null on a 2xx → treat as failure ("Something went wrong").When the product requires payment, Quick Book does not call /quick-book. Instead it creates a cart and hands off to the cart / payment flow. Same endpoint for both product types — only the request body differs.
POST /checkout/api/v1/cart
| Field | Type | Required | Description |
|---|---|---|---|
building_code |
string | ✅ | Building identifier |
cart_items |
array | ✅ | One item per room booking (below) |
cart_items[].product_uid |
string | ✅ | Room/product identifier |
cart_items[].product_type |
string | ✅ | "CONFERENCE_ROOM" |
cart_items[].product_pricing_uid |
string | ✅ | Pricing identifier for the product |
cart_items[].start_time |
string | ✅ | yyyy-MM-ddTHH:mm |
cart_items[].end_time |
string | ✅ | yyyy-MM-ddTHH:mm |
applied_offers |
array | ❌ | Optional. Each item: { "code": "PROMO20" } |
{
"building_code": "BLR-01",
"cart_items": [
{
"product_uid": "room-123",
"product_type": "CONFERENCE_ROOM",
"product_pricing_uid": "pricing-456",
"start_time": "2026-07-01T10:00",
"end_time": "2026-07-01T10:30"
}
],
"applied_offers": [{ "code": "PROMO20" }]
}
Used when product_type is "BOOKABLE_PO". Instead of a single start/end, it carries a quantity and a list of day slots.
| Field | Type | Required | Description |
|---|---|---|---|
building_code |
string | ✅ | Building identifier |
cart_items |
array | ✅ | One item (below) |
cart_items[].product_uid |
string | ✅ | Product identifier |
cart_items[].product_type |
string | ✅ | "BOOKABLE_PO" |
cart_items[].product_pricing_uid |
string | ✅ | Pricing identifier |
cart_items[].quantity |
integer | ✅ | Number of days/slots booked (= slots.length) |
cart_items[].slots |
array | ✅ | Each item: { "start_time": "..." } (end_time optional) |
applied_offers |
array | ❌ | Optional. Each item: { "code": "PROMO20" } |
{
"building_code": "BLR-01",
"cart_items": [
{
"product_uid": "po-789",
"product_type": "BOOKABLE_PO",
"product_pricing_uid": "pricing-999",
"quantity": 2,
"slots": [
{ "start_time": "2026-07-01" },
{ "start_time": "2026-07-02" }
]
}
]
}
200 (both 2a and 2b){
"message": "",
"data": {
"cart_uid": "CART-XYZ789",
"blocks": [ { "...": "render blocks: building, cart items, price summary, etc." } ]
}
}
| Field | Type | Description |
|---|---|---|
data.cart_uid |
string | Cart ID. Pass to the cart / payment screen and to cart update calls. |
data.blocks |
array | Ordered UI blocks describing the cart (building, line items, price summary…). |
message in the envelope for display.Used within the quick-book flow to hydrate the room card / slot-selection screen before booking, and to read is_payment_required (which decides §1 vs §2). This is a shared catalogue endpoint, not quick-book-specific.
GET /catalogue/api/v1/products/{product_uid}/details
| Param | In | Type | Required | Description |
|---|---|---|---|---|
product_uid |
path | string | ✅ | Room ID |
start_time |
query | string | ✅ | yyyy-MM-dd HH:mm |
duration |
query | integer | ✅ | Duration in minutes (e.g. 30 for a half-hour slot) |
Example:
GET /catalogue/api/v1/products/room-123/details?start_time=2026-07-01%2010:00&duration=30
200{
"message": "",
"data": {
"product_uid": "room-123",
"product_type": "CONFERENCE_ROOM",
"building": { "...": "building details" },
"product_details": { "...": "space details: name, floor, capacity, amenities, images …" },
"is_payment_required": false,
"price_details": { "...": "pricing" },
"is_favorite": false
}
}
| Field | Type | Description |
|---|---|---|
data.product_uid |
string | Room ID |
data.product_type |
string | Product type |
data.building |
object | Building info (name, address, coordinates) |
data.product_details |
object | Space details — name, floor, capacity, amenities, image URLs, etc. |
data.is_payment_required |
boolean | Decides the booking path: false → §1 quick-book, true → §2 cart |
data.price_details |
object | Pricing breakdown |
data.is_favorite |
boolean | Whether the current user has favorited the room |
building,product_details, andprice_detailsare large nested objects; only their top-level keys are listed here. Ask if the frontend team needs the full expanded schema of any of them.