StructurrAI Documentation
Programmatic access to the StructurrAI canonical hotel and room mapping catalogue. Pull static inventory, sync incremental changes, and resolve supplier room descriptions to canonical room codes. One api-key header authenticates every call.
What you can do
Endpoint groups
Look up the country and city codes that every other endpoint expects.
Bulk-fetch canonical hotels and their enriched static content for a list of cities.
Sync canonical inventory incrementally. Pull newly added, updated, or deleted hotels since a given date.
Resolve a list of supplier room descriptions to StructurrAI canonical room codes.
From your API key to your first API call in three steps.
Your api_key authenticates every endpoint on this page. Send it in theapi-keyheader and you’re live.
Receive your API key
Issued by the StructurrAI team after onboarding. Long-lived, one per account.
api-key header
api-key: <your_api_key> on every request. Missing or invalid returns 401.
Response envelope
All responses wrap in { success, message, data, errors }. HTTP status is the source of truth.
https://api.structurrai.comapi-key: <your_api_key>Geography
Look up the country and city codes that every other endpoint expects.
Fetch Countries
Returns every country StructurrAI has hotels in, along with the StructurrAI country_code that every other endpoint expects. Country codes follow the SI-{ISO2} format, for example SI-IN for India or SI-AE for the United Arab Emirates. Call this once on first integration to discover the regions available to your account.
Request
Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text. Useful for log lines.
- data[]array of objects
One entry per supported country.
- data[].country_codestring
StructurrAI country code in the form SI-{ISO2}, e.g. "SI-IN" for India or "SI-AE" for the UAE. Pass this to /api/v2/cities (as the country_id query parameter).
- data[].country_namestring
Display name of the country in English.
- errorsarray
Empty on success. On failure, contains a list of human-readable error messages.
Fetch Cities
Returns every city StructurrAI maps within a country. Each city has a city_code that the hotel-search and hotel-sync endpoints accept. Use this after /countries to build your destination picker or to seed a city-by-city sync.
Request
- country_idrequiredstringquery
StructurrAI country code (in SI-{ISO2} format) returned by /api/v2/countries. Examples: SI-IN, SI-AE, SI-GB. The endpoint also accepts country_code as an alias if your client prefers that key name.
country_id=SI-IN
Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text.
- data.country_idstring
The country code you sent in the request, echoed back.
- data.country_namestring
Display name of the country in English.
- data.cities[]array of objects
One entry per city StructurrAI maps in this country.
- data.cities[].city_codestring
StructurrAI city code in the form STR-{ISO2}-{number}, e.g. "STR-IN-0607" for Mumbai or "STR-AE-0001" for Dubai. Pass this to /hotelsearch and /hotelstaticdata.
- data.cities[].citystring
Display name of the city in English.
- data.cities[].country_codestring
StructurrAI country code, repeated for convenience when consuming a flat list.
- data.cities[].country_namestring
Display name of the country, repeated for convenience.
- errorsarray
Empty on success.
Hotel Mapping
Bulk-fetch canonical hotels and their enriched static content for a list of cities.
Hotel Search by Cities
Returns every StructurrAI hotel in the requested cities, plus the supplier IDs each one is mapped to (HotelBeds, TBO, Agoda, etc.). One round trip can pull thousands of hotels across up to 20 cities at once. Use this to build your destination inventory in bulk before fetching static content or running availability lookups.
Request
- standardized_city_codesrequiredarray of stringsbody
A list of 1 to 20 StructurrAI city codes (e.g. ["STR-AE-0001", "STR-IN-0607"] for Dubai and Mumbai). Discover available codes via /api/v2/cities. Each code maps to one canonical city in the StructurrAI catalogue. Requests with more than 20 codes return 400.
{
"standardized_city_codes": ["STR-AE-0001", "STR-IN-0607"]
}Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text.
- data[]array of objects
One entry per StructurrAI hotel in the requested cities.
- data[].standardized_hotel_idstring
The canonical StructurrAI hotel id. Use this everywhere you need to identify the hotel.
- data[].standardized_hotel_namestring
Cleaned canonical hotel name.
- data[].standardized_addressstring
Cleaned canonical hotel address.
- data[].standardized_citystring
City name in StructurrAI canonical form.
- data[].latitudenumber
Geocoded latitude. Null if the hotel has not been geocoded yet.
- data[].longitudenumber
Geocoded longitude. Null if the hotel has not been geocoded yet.
- data[].last_updatedstring (timestamp)
ISO timestamp of the most recent change to this hotel.
- data[].standardized_city_codestring
StructurrAI city code that this hotel sits in (e.g. STR-AE-0001).
- data[].standardized_country_codestring
StructurrAI country code that this hotel sits in (e.g. SI-AE).
- data[].provider_details[]array of objects
Every supplier the hotel is mapped to. Each entry has supplier_name, supplier_id, hotel_name (raw supplier name), address, supplier_city_code, supplier_city, and supplier_country_code.
- errorsarray or null
Null on success.
Hotel Static Data
Returns enriched content for every StructurrAI hotel in the requested cities: hotel name and address, geo coordinates, description, image URLs (hero plus gallery), star rating, review rating, check-in/check-out times, nearby attractions, amenities, and facilities. Use this to hydrate a search-results page or property-detail UI without a separate call per hotel.
Request
- standardized_city_codesrequiredarray of stringsbody
A list of 1 to 20 StructurrAI city codes (e.g. ["STR-IN-0607"] for Mumbai). Same code set as /hotelsearch.
{
"standardized_city_codes": ["STR-IN-0607"]
}Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text.
- data[]array of objects
One enriched static-content record per StructurrAI hotel in the requested cities.
- data[].standardized_hotel_idstring
The canonical StructurrAI hotel id. Same identifier as standardized_hotel_id returned by /hotelsearch.
- data[].standardised_hotel_namestring
Cleaned canonical hotel name. Note: spelled "standardised" (British spelling) in this endpoint, unlike most other endpoints which use "standardized".
- data[].standardised_addressstring
Cleaned canonical hotel address. Note: British spelling here too.
- data[].city_codestring
StructurrAI city code (e.g. STR-IN-0607). Same identifier as standardized_city_code elsewhere.
- data[].descriptionstring
Marketing description suitable for a property-detail page. May be empty when copy is not yet available.
- data[].latitudenumber
Geocoded latitude.
- data[].longitudenumber
Geocoded longitude.
- data[].hero_image_urlstring
Primary hero image URL. Use this as the lead visual.
- data[].image_urlsarray of strings
Additional gallery image URLs. May be empty.
- data[].star_ratingnumber
Official hotel star rating, typically an integer from 1 to 5. Null when the rating is not available.
- data[].review_ratingobject
Aggregated guest review rating. Contains `score` (number, e.g. 8.4 on a 0–10 scale), `scale` (number, e.g. 10), and `review_count` (integer). Null when no reviews are available.
- data[].check_in_timestring (HH:mm)
Earliest standard check-in time at the property, in 24-hour HH:mm format (e.g. "15:00"). Null when not published.
- data[].check_out_timestring (HH:mm)
Latest standard check-out time at the property, in 24-hour HH:mm format (e.g. "11:00"). Null when not published.
- data[].nearby_attractionsarray of objects
Notable points of interest near the property. Each entry has `name` (string), `distance_km` (number), and `category` (string, e.g. "Landmark", "Airport", "Beach"). May be empty.
- data[].amenitiesarray of strings
In-room and guest amenities (e.g. "Free Wi-Fi", "Air Conditioning", "Mini Bar"). May be empty.
- data[].facilitiesarray of strings
Property-level facilities (e.g. "Swimming Pool", "Gym", "Spa", "Restaurant", "Parking"). May be empty.
- errorsarray or null
Null on success.
Hotel Sync
Sync canonical inventory incrementally. Pull newly added, updated, or deleted hotels since a given date.
Fetch Added Hotels
Returns hotels newly mapped on or after a given date, along with each linked supplier hotel. Pass the date of your last successful sync run to pull only the delta. No need to re-fetch the full catalogue. Run this nightly or hourly depending on how fresh your inventory needs to be.
Request
- last_updated_daterequiredstring (YYYY-MM-DD)query
Inclusive lower bound for the date filter, in ISO YYYY-MM-DD format. The response includes hotels added on or after this date. Pass the date of your last successful sync to fetch only newly added inventory.
last_updated_date=2025-09-24 - pageoptionalintegerquery
Page number for paginating through large result sets. Starts at 1.
page=1 - offsetoptionalintegerquery
Page size: how many hotels to return per page. Combine with page to walk through the full result set.
offset=50
Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text.
- data.last_updated_datestring
The date you sent in the request, echoed back so you can confirm the bound the response was filtered with.
- data.mapped_hotels[]array of objects
One entry per added hotel. May be empty if no hotels were added since the requested date.
- data.mapped_hotels[].standardized_hotel_idstring
The canonical StructurrAI hotel id. Use this everywhere you need to identify the hotel.
- data.mapped_hotels[].standardized_hotel_namestring
Cleaned canonical hotel name.
- data.mapped_hotels[].standardized_addressstring
Cleaned canonical hotel address.
- data.mapped_hotels[].standardized_citystring
City name in StructurrAI canonical form.
- data.mapped_hotels[].latitudenumber
Geocoded latitude. Null if the hotel has not been geocoded yet.
- data.mapped_hotels[].longitudenumber
Geocoded longitude. Null if the hotel has not been geocoded yet.
- data.mapped_hotels[].last_updatedstring (timestamp)
ISO timestamp of when this hotel was added.
- data.mapped_hotels[].standardized_city_codestring
StructurrAI city code (e.g. STR-AE-0001). Same identifier returned by /api/v2/cities.
- data.mapped_hotels[].standardized_country_codestring
StructurrAI country code (e.g. SI-AE). Same identifier returned by /api/v2/countries.
- data.mapped_hotels[].provider_details[]array of objects
Every supplier the hotel is mapped to. Each entry has supplier_name, supplier_id, hotel_name (raw supplier name), address, supplier_city_code, supplier_city, and supplier_country_code.
- errorsarray or null
Null on success.
Fetch Updated Hotels
Returns hotels whose canonical attributes (name, address, geo, supplier mappings) changed on or after a given date. Pair this with /addedhotels and /deletedhotels in a daily sync job to keep your local copy of the StructurrAI catalogue current.
Request
- last_updated_daterequiredstring (YYYY-MM-DD)query
Inclusive lower bound for the date filter, in ISO YYYY-MM-DD format. The response includes hotels updated on or after this date.
last_updated_date=2025-09-24
Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text.
- data.last_updated_datestring
The date you sent in the request, echoed back.
- data.mapped_hotels[]array of objects
Same shape as /addedhotels: standardized_hotel_id, standardized_hotel_name, standardized_address, standardized_city, latitude, longitude, last_updated, standardized_city_code, standardized_country_code, provider_details[]. Updated values reflect the current canonical state, not the prior one.
- errorsarray or null
Null on success.
Fetch Deleted Hotels
Returns the IDs of hotels that StructurrAI deactivated or removed on or after a given date. The payload is intentionally minimal — only the hotel id is returned, since the canonical record and its supplier mappings are gone. Use this in your sync job to retire stale rows from your inventory before serving search results.
Request
- last_updated_daterequiredstring (YYYY-MM-DD)query
Inclusive lower bound for the date filter, in ISO YYYY-MM-DD format. The response includes hotels deleted on or after this date.
last_updated_date=2025-09-24 - pageoptionalintegerquery
Page number for paginating through large result sets. Starts at 1.
page=1 - offsetoptionalintegerquery
Page size: how many hotel ids to return per page.
offset=50
Response
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text.
- data.last_updated_datestring
The date you sent in the request, echoed back.
- data.mapped_hotels[]array of objects
One entry per deleted hotel. Only the hotel id is returned.
- data.mapped_hotels[].standarized_hotel_idstring
The canonical StructurrAI hotel id of the deleted hotel. Note: this field is spelled "standarized" (without the second "d") in the wire response — keep that exact key when reading. Match this against your local catalogue and remove the corresponding row.
- errorsarray or null
Null on success.
Room Mapping
Resolve a list of supplier room descriptions to StructurrAI canonical room codes.
Extract Room Mappings
Different suppliers describe the same physical room differently. "Deluxe King with City View" on HotelBeds, "Deluxe King City View" on TBO, "Dlx King CV" on a third supplier. This endpoint takes those raw, supplier-specific room descriptions, extracts the structured attributes (category, bed type, view, amenities, bed count, boolean flags, etc.), and groups them under a single canonical StructurrAI room code. Use it to: deduplicate rooms across suppliers before showing them in a search UI; build a single price-comparison row per canonical room; seed an inventory store keyed by canonical room code instead of free-text supplier strings. The API returns one entry per canonical room. Each entry carries the structured attributes plus a list of every input room (with its original index, and — when supplied — supplier_name and hotel_id) that was clustered into that group. Important: a single API call must contain rooms belonging to one unique hotel. Send a separate request per hotel — mixing rooms from multiple hotels in one call is not supported and will produce incorrect groupings.
Request
- roomsrequiredarray of objectsbody
The list of supplier rooms to map. Send at least 1 room. The maximum is 20 when sync is true, 100 when sync is false (see sync below). Each object has the four fields documented underneath.
Object fields- namerequiredstring
The exact room description as it appears in the supplier's inventory. This is the raw text the API extracts attributes from. Pass it verbatim, no manual cleanup or normalization needed. Examples: "Deluxe King Room with City View, Non-Smoking", "Superior Double - Sea View", "Standard Twin Room". Any non-empty string is accepted. Longer, more descriptive strings tend to produce more accurate mappings because the extractor has more signal to work with.
- hotel_idoptionalstring
Optional. The StructurrAI hotel id (NVA_hotel_id) the room belongs to. When provided, the value flows through unchanged into the response so you can re-attribute mapped rooms back to the hotel they came from. Pass it as a string even if the underlying id is numeric. Because a single call should contain rooms from one unique hotel, you may either send the same hotel_id on every room or omit it entirely.
- supplier_nameoptionalstring
Optional. The supplier the room came from, for example "HotelBeds", "TBO", or "Agoda". Use a stable identifier per supplier across calls. When provided, the response carries supplier_name verbatim, so downstream consumers can re-attribute each grouped room back to its origin. Omit when you do not need supplier attribution in the response.
- indexrequiredinteger
A unique sequential identifier for this room within the request. Must be 1 for the first room, 2 for the second, and so on up to N for the last. Strictly ascending, no gaps, no duplicates. Requests where indexes are missing, repeated, or out of order are rejected with 400. Why: index is your handle for correlating request rooms with response groups. Every room in the response carries its original index, so you can stitch the mapped output back to your original input list without depending on the room name (which may have been reformatted) or on the position in the response array (which is reordered by clustering).
- syncoptionalbooleanbody
Processing mode. When true, the batch is processed inline. The request blocks while extraction runs, and the response returns once mapping is complete. Faster end-to-end, but capped at 20 rooms per call. Recommended for interactive flows like a real-time UI lookup. When false (default), the batch is enqueued for the background worker. Cached rooms are mapped immediately. Uncached ones are fetched asynchronously and may not appear in the very first response. The response carries whatever is available now, plus the cached results. Capped at 100 rooms per call. Recommended for nightly batch jobs and bulk inventory loads.
- skip_ftoptionalbooleanbody
Skip the fine-tuned extraction step. Defaults to false. When false (default), rooms that the base extractor is uncertain about are routed through the fine-tuned model for a more accurate mapping. Each result carries a fine_tuned_status field indicating whether the fine-tuned step was triggered. When true, the fine-tuned step is bypassed for every room. The response is faster but accuracy may be lower on edge cases. Use this only when latency matters more than precision (e.g. quick previews) or when you are deliberately benchmarking the base extractor.
{
"rooms": [
{ "name": "Deluxe Room, 1 King Bed (City View)", "index": 1, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed (City View),NonSmoking", "index": 2, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed (Family),NonSmoking", "index": 3, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed (Grand),NonSmoking", "index": 4, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed (High Floor),NonSmoking", "index": 5, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed (with sofa bed)", "index": 6, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed (with sofa bed),NonSmoking", "index": 7, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed, Balcony", "index": 8, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed, Balcony,NonSmoking", "index": 9, "hotel_id": "9054312", "supplier_name": "tbo" },
{ "name": "Deluxe Room, 1 King Bed, Bay View,NonSmoking", "index": 10, "hotel_id": "9054312", "supplier_name": "tbo" }
],
"sync": true,
"skip_ft": false
}Response
data.results contains one entry per canonical room group. Each entry carries the structured attributes plus a rooms[] array listing every input room that was clustered into that group. To stitch results back to your input list, look up by the index field.
- successboolean
True when the call completed without error.
- messagestring
Human-readable status text. Useful for log lines.
- data.hotel_idinteger
Currently a placeholder reserved for future use. Always returns 0. The real hotel_id for each grouped room is on data.results[].rooms[].hotel_id.
- data.results[]array of objects
One entry per canonical room group. The number of entries depends on how many distinct rooms StructurrAI detected in your input.
- data.results[].structurrai_room_codestring
The canonical room id assigned by StructurrAI. Stable across calls. Use this as the primary key when storing or pricing rooms.
- data.results[].room_namestring
The cleaned canonical room name (e.g. "Deluxe King Room"). Distilled from the supplier descriptions.
- data.results[].type_of_accomodationstring
The kind of unit. Typical values: "Room", "Suite", "Villa", "Apartment".
- data.results[].room_categorystring
The quality tier extracted from supplier text (e.g. "Standard", "Superior", "Deluxe", "Premium", "Executive").
- data.results[].bed_typestring
The bed configuration (e.g. "King", "Queen", "Twin", "Double"). Null when the supplier text did not specify a bed type.
- data.results[].view_typestring
The view descriptor (e.g. "City View", "Sea View", "Pool View", "Garden View"). Null when no view was specified.
- data.results[].bed_countstring
Number of beds in the room, returned as a string (e.g. "1", "2", or "1 or 2" when the supplier description was non-numeric).
- data.results[].bedroom_countinteger or null
Number of separate bedrooms in the unit. Relevant for suites, villas, and apartments. Null when the supplier text did not specify.
- data.results[].family_roomboolean
True when the unit is marketed as a family room.
- data.results[].family_suiteboolean
True when the unit is marketed as a family suite.
- data.results[].family_villaboolean
True when the unit is marketed as a family villa.
- data.results[].guest_roomboolean
True when the unit is explicitly described as a guest room.
- data.results[].master_suiteboolean
True when the unit is a master suite.
- data.results[].business_classboolean
True when the room is a business-class / executive-class unit.
- data.results[].duplexboolean
True when the unit is a duplex (two-storey).
- data.results[].connecting_roomsboolean
True when the unit is offered as a connecting / inter-connecting room.
- data.results[].balconyboolean
True when the room has a balcony.
- data.results[].terrace_accessboolean
True when the room has terrace access.
- data.results[].pool_accessboolean
True when the room has direct pool access (e.g. swim-up or private pool).
- data.results[].spaboolean
True when the room includes in-room spa features or spa-suite access.
- data.results[].jacuzziboolean
True when the room features a jacuzzi, hot tub, or whirlpool bath.
- data.results[].saunaboolean
True when the room has an in-room sauna.
- data.results[].kitchenetteboolean
True when the room has a kitchenette or full kitchen.
- data.results[].bathtubboolean
True when the room has a bathtub (as opposed to shower-only).
- data.results[].barboolean
True when the room includes a wet bar / in-room bar.
- data.results[].living_roomboolean
True when the unit has a separate living room area.
- data.results[].club_lounge_accessboolean
True when the booking includes club lounge / executive lounge access.
- data.results[].high_floorboolean
True when the room is explicitly on a high floor.
- data.results[].low_floorboolean
True when the room is explicitly on a low floor.
- data.results[].windowlessboolean
True when the room has no window (interior / inside room).
- data.results[].smoking_allowedboolean
True when smoking is allowed in the room. False indicates a non-smoking room.
- data.results[].extra_bedboolean
True when the rate includes an extra bed / rollaway.
- data.results[].room_descriptionstring or null
Long-form description of the room, when available. Null when no description was extracted.
- data.results[].room_size_sqmnumber or null
Room size in square metres. Null when the supplier text did not specify.
- data.results[].room_size_sqftnumber or null
Room size in square feet. Null when the supplier text did not specify.
- data.results[].image_urlsarray of strings
Image URLs for the canonical room, when available. May be empty.
- data.results[].rooms[]array of objects
Every input room from your request that was clustered into this canonical group. Iterate this array to know which of your inputs map to this canonical code.
- data.results[].rooms[].indexinteger
The original index field you sent in the request. Use this to correlate the response group back to a specific row in your input array.
- data.results[].rooms[].room_namestring
The exact room description you sent in the request. Returned verbatim.
- data.results[].rooms[].hotel_idstring
The hotel_id you sent in the request. Returned verbatim.
- data.results[].rooms[].supplier_namestring
The supplier_name you sent in the request. Returned verbatim.
- data.results[].fine_tuned_statusstring
Trace of how the canonical mapping was produced. Values: "fine_tuned_not_triggered" (the base extractor was confident — no fine-tuned call was made), "fine_tuned_triggered_responded" (the base extractor deferred and the fine-tuned model produced the answer). Useful when debugging unexpected groupings or comparing extractor coverage. Always "fine_tuned_not_triggered" when the request set skip_ft = true.
- errorsarray of strings or null
Null on success. On failure, contains a list of human-readable error messages.
Need help?
Reach the integrations team at vasu.goenka@structurrai.com for API access, schema questions, or onboarding support.