OpenRoomIDAn open identifier for accommodation units

Implementation guide

This page is for the engineer wiring roomID into a hotel website, a booking engine, or a PMS export. Each block below is complete: paste it into the page head, replace the example values with your own, and you are done. Identifiers come from the registrar; see the registry policy if your property does not have them yet.

The pattern in all four blocks is the same one: identifier is a schema.org PropertyValue whose propertyID is roomID for a unit or roomID:property for a property, and whose value is the identifier itself.

A room page

Put this on the page that describes one physical room. The sameAs link to the resolver lets any consumer of your markup verify the identifier against the registry.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HotelRoom",
  "name": "Room 1412",
  "url": "https://www.example-hotel.com/rooms/1412",
  "identifier": {
    "@type": "PropertyValue",
    "propertyID": "roomID",
    "value": "7QM4KX92-1412-B"
  },
  "containedInPlace": {
    "@type": "Hotel",
    "name": "Example Hotel",
    "identifier": {
      "@type": "PropertyValue",
      "propertyID": "roomID:property",
      "value": "7QM4KX92"
    }
  },
  "sameAs": "https://openroomid.org/7QM4KX92-1412-B"
}
</script>

A hotel page

Put this on the property's main page. Listing units in containsPlace is optional; the property identifier is the part that matters. Two units are shown as examples of the shape.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Hotel",
  "name": "Example Hotel",
  "url": "https://www.example-hotel.com",
  "identifier": {
    "@type": "PropertyValue",
    "propertyID": "roomID:property",
    "value": "7QM4KX92"
  },
  "sameAs": "https://openroomid.org/7QM4KX92",
  "containsPlace": [
    {
      "@type": "HotelRoom",
      "name": "Room 1412",
      "identifier": {
        "@type": "PropertyValue",
        "propertyID": "roomID",
        "value": "7QM4KX92-1412-B"
      }
    },
    {
      "@type": "HotelRoom",
      "name": "Room 1414",
      "identifier": {
        "@type": "PropertyValue",
        "propertyID": "roomID",
        "value": "7QM4KX92-1414-A"
      }
    }
  ]
}
</script>

An offer attached to a unit

A rate belongs to your markup and your systems, never to the registry. This block shows the join: the Offer carries your price, and itemOffered.identifier pins it to the exact unit, so a consumer of the offer knows precisely which room the price is for.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Offer",
  "itemOffered": {
    "@type": "HotelRoom",
    "name": "Room 1412",
    "identifier": {
      "@type": "PropertyValue",
      "propertyID": "roomID",
      "value": "7QM4KX92-1412-B"
    }
  },
  "price": "189.00",
  "priceCurrency": "USD",
  "availabilityStarts": "2026-09-12",
  "availabilityEnds": "2026-09-13",
  "seller": {
    "@type": "Hotel",
    "name": "Example Hotel",
    "identifier": {
      "@type": "PropertyValue",
      "propertyID": "roomID:property",
      "value": "7QM4KX92"
    }
  }
}
</script>

Carrying the identifier into booking

The potentialAction pattern advertises a booking URL that carries the identifier as a rid query parameter. A system that selected a specific unit upstream can hand the selection to your booking flow without losing it. The {checkin_date} and {checkout_date} placeholders follow the EntryPoint template convention.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HotelRoom",
  "name": "Room 1412",
  "identifier": {
    "@type": "PropertyValue",
    "propertyID": "roomID",
    "value": "7QM4KX92-1412-B"
  },
  "potentialAction": {
    "@type": "ReserveAction",
    "target": {
      "@type": "EntryPoint",
      "urlTemplate": "https://book.example-hotel.com/reserve?rid=7QM4KX92-1412-B&checkin={checkin_date}&checkout={checkout_date}",
      "actionPlatform": "https://schema.org/DesktopWebPlatform"
    },
    "result": {
      "@type": "LodgingReservation",
      "name": "Reservation for room 1412"
    }
  }
}
</script>

Rules worth knowing