StructurrAI
API Reference

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

Real-time mapping updates
Standardised hotels across all major suppliers
Incremental added / updated / deleted sync APIs
Room mapping with explainable extractions

Endpoint groups

Geography2 endpoints

Look up the country and city codes that every other endpoint expects.

Hotel Mapping2 endpoints

Bulk-fetch canonical hotels and their enriched static content for a list of cities.

Hotel Sync3 endpoints

Sync canonical inventory incrementally. Pull newly added, updated, or deleted hotels since a given date.

Room Mapping1 endpoint

Resolve a list of supplier room descriptions to StructurrAI canonical room codes.

Authentication

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.

01

Receive your API key

Issued by the StructurrAI team after onboarding. Long-lived, one per account.

02

api-key header

api-key: <your_api_key> on every request. Missing or invalid returns 401.

03

Response envelope

All responses wrap in { success, message, data, errors }. HTTP status is the source of truth.

Base URL
https://api.structurrai.com
Auth header (every request)
api-key: <your_api_key>
Scroll down for every API, or jump straight to a section using the sidebar.

Geography

Look up the country and city codes that every other endpoint expects.

Fetch Countries

GET/api/v2/countriesOpen in Postman

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

No parameters required.

Response

Response fields
  • 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

GET/api/v2/citiesOpen in Postman

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

Parameters
  • 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

Response fields
  • 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 Sync

Sync canonical inventory incrementally. Pull newly added, updated, or deleted hotels since a given date.

Fetch Added Hotels

GET/api/v1/addedhotelsOpen in Postman

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

Parameters
  • 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

Response fields
  • 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

GET/api/v1/updatedhotelsOpen in Postman

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

Parameters
  • 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

Response fields
  • 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

GET/api/v1/deletedhotelsOpen in Postman

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

Parameters
  • 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

Response fields
  • 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

POST/api/v2/room-mappingsOpen in Postman

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

Parameters
  • 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.

Request body
{
  "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.

Response fields
  • 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.