Documentation / Guides
Room attributes
Extract room details for badges, filters and comparisons, with source evidence.
Request attributes
Add "include": ["attributes"] to either existing mapping request shape. Combine it with "hierarchy" or "sent" when needed. Each offer gains roomAttributes, under roomRates[], groups[].rooms[] and rooms[].rates[].
Extraction reads the original room name, room-specific description, beds, view and smoking status. It does not overwrite those fields or change room names, assignments, grouping, prices, IDs or booking data. Extraction runs only when you request attributes or variants.
{
"hotelId": "your-hotel-id",
"mode": "standard",
"mergePolicy": "standard",
"include": ["attributes"],
"roomRates": [{
"index": 0,
"roomName": "Deluxe Room, 1 King Bed, Balcony",
"description": "This room measures 42 sqm and has a private bathroom."
}]
}
Available fields
| Fields | Values |
|---|---|
bedKind, bedBasis, bedCount, bedrooms | Main bedding and bedroom count. A bed implied by a room-type word ("Double Room", "Twin Room") is read as that bed, read against the hotel's other room names; bedBasis says whether the bed was stated or implied by the room_type. A choice of beds ("Double or King") is bedAssignment: "conditional". |
bedAssignment, sofaBed | Explicit guarantee/conditional wording; sofa-bed presence. |
view, viewName, viewExtent, landmark | Stated room view: view is a category for filters (sea, beach, city, garden, pool, park, courtyard, mountain, lake, river, bay, harbour, water, panoramic, street, golf, resort, landmark or other) and viewName the view as written ("Burj Khalifa View", "Sky View"); partial/full extent. Nearby sights are not room views. |
accommodationType, smokingAllowed, accessibility | Unit type and explicit smoking/accessibility information. Generic accessibility does not promise any particular accessible feature. |
outdoor, pool | Balcony, terrace or patio; private pool or shared-pool access. A pool view is not pool access. |
sizeSqm, sizeSqft | Numeric room area in the unit actually supplied. No unit conversion, approximate size or range is invented. |
bathroomCount, bathroomPrivacy, bathroomFeatures | Explicit count, private/shared, and features such as bathtub or roll-in shower. |
kitchen, connectingRooms, loungeAccess | Kitchen/kitchenette/explicit absence, connecting rooms, lounge access. “Club room” alone does not promise lounge access; adjoining is not assumed to mean internally connecting. |
floor, buildingWing | Explicit floor number or high/low/ground/top/basement, and the stated building/wing label. |
Coverage is strongest for explicit English wording. Unknown or unsupported names, languages and ambiguous descriptions remain unknown. Extraction is an interpretation of supplier text, not a hotel-verified amenity guarantee.
Read results
Cached results return immediately. New source text returns status: "pending", an attributeId and statusUrl. Bed, bed count, bedrooms, view, view extent, outdoor space and accessibility are read during the mapping call, so a record whose other fields are still being read arrives as status: "partial" with those facts already in place. Poll that URL using the same bearer key; the response is {"roomAttributes": ...}. Respect Retry-After. Polling does not call the model again or consume mapping quota.
{
"status": "complete",
"facts": {
"bedKind": {"value": "king", "evidence": [{"source": "roomName", "quote": "Deluxe Room, 1 King Bed, Balcony"}]},
"sizeSqm": {"value": 42, "evidence": [{"source": "description", "quote": "This room measures 42 sqm and has a private bathroom."}]}
},
"alternatives": [],
"conflicts": []
}
Illustrative excerpt; the full response also includes version, cache state, unknown fields, warnings and status references. complete means processing finished, even if some fields are unknown. partial includes a warning about bounded/omitted inputs. unavailable, failed, timeout and limit_exceeded are not successful empty extractions. No confidence percentage or repeated basis field is returned.
Results survive restarts and expire after 30 days. Changed source text, supplier, hotel, model or extraction rules create a new ID; prices, offer codes and input ordering do not. Keep the ID attached to its originating offer. A new mapping/batch request may retry a failure after 30 seconds; after three attempts the backoff is one hour. GET polling never retries. Expired and other-account IDs return 404.
Use in your UI
Render badges and filters from facts. Missing values are unknown, not false. Show explicit alternatives as alternatives and do not select one side of a conflict. Never copy facts from the cheapest or richest offer onto another offer. Promote a fact to a shared room card only when every relevant offer supports the same value.
Keep room-mapping similarity separate from attribute extraction; it is not the accuracy of a bed or view fact. Display extracted text as text, not HTML. Supplier-provided metadata remains alongside the extracted facts for inspection.
Select room variants
Add "include": ["variants", "hierarchy"] on the same mapping endpoint. variants also requests attribute extraction. The optional hierarchy organizes browsing; roomVariants.rooms[] references existing room cards by roomId, with selections underneath them. For example, one Deluxe card may have King / sea view, Twin / sea view, King / city view and unspecified selections.
Each variant has rateIds pointing to the original offers, plus stated attributes, unknownAttributes and reviewReasons. Choose an original rate to book. Variants never cross room-card boundaries. Matching attribute profiles do not verify that the upstream category mapping is correct. Prices, cancellation terms and meal plans remain offer-specific.
Unknown facts do not match known ones. Conflicts, alternatives, mixed bedding, conditional beds, incomplete extraction and unresolved categories keep their offers separate. We do not supply a missing bed count, view or benefit from another offer or from the category title. Named landmarks enter the profile only when extraction supports a room view, not proximity.
Use sharedAttributes for facts stated by every offer in a card. Use availableOptions to show which values are available and on which rate IDs. These are interpretations of supplier evidence, not independent guarantees. Full source quotes remain in each rate's roomAttributes.
Uncached extraction returns roomVariants.status: "pending" with temporarily isolated offers. Poll roomVariants.statusUrl using the same key and replace the entire variant view for that request. Polling reads existing extraction jobs and does not remap, call the model or consume mapping quota. Fetch individual attribute status URLs if you also need updated source quotes. The variant URL works while that request log is retained. If unfinished extraction expires, its offers remain isolated with unavailable evidence. Variant IDs can change as evidence completes or rules change; retain original rate IDs.
metrics.browsingReduction and metrics.variantReduction both use input rateCount as their denominator. The former measures room-card compression; the latter measures attribute-profile compression. Neither measures correct room equivalence or accuracy. Existing mapping counts and reduction fields are unchanged.
Batch processing
Include the same option in each JSONL record. The batch worker waits for extraction and returns a retryable record error if it fails or exceeds the deadline. Partial bounded results are explicitly marked. Completed source records are cached, so retrying a hotel reuses completed extraction work.
Use batches to prepare attributes before shopping traffic. Live mapping enqueues uncached work and does not wait for the extraction model. Storage and pending-work limits may return limit_exceeded; retain the original offer and retry later.
Batches also accept include: ["variants"] and wait for extraction before building the variant view. Batch variant status URLs are null because the completed view is returned in the result download. Partial extraction stays explicit and isolated.