Hotel PMS Integration Guide: Mapping Your Data to Seam

Last updated: December 13, 2025

Overview

When integrating Seam into your hotel PMS, you need to map your existing resources (properties, rooms, bookings) to Seam's resources (Connected Accounts, Spaces, Access Grants). Seam makes this easy by allowing you to tag each Seam resource with your own internal IDs using resource keys.

This guide shows you how to map:

  • Hotel properties → Seam Connected Accounts (using customer_key)

  • Hotel rooms → Seam Spaces (using space_key)

  • Guest records → Seam User Identities (using user_identity_key)

  • Guest bookings → Seam Access Grants (using access_grant_key)

Once mapped, you can retrieve Seam resources directly using your PMS IDs, making integration seamless.


Step 1: Map Hotel Properties to Seam Connected Accounts

Each hotel property in your PMS needs to connect their access control system to Seam. When you create a Connect Webview for a property, you tag it with your PMS property ID using customer_key. This creates a permanent link between your property and their Seam Connected Account.

How to Map Properties

When setting up a new hotel property in your system, create a Connect Webview tagged with your property ID:

seam.connect_webviews.create(
  accepted_providers=["salto", "assa_abloy_visionline", "dormakaba_oracode"],
  customer_key="hotel-property-123"  # Your PMS property ID
)

Send this Connect Webview to the hotel. When they complete authentication, Seam automatically copies the customer_key to their Connected Account. Now you can always find their Seam account using your property ID.

Retrieving Mapped Properties

Retrieve all Connected Accounts for a specific property using your PMS property ID:

connected_accounts = seam.connected_accounts.list(
  customer_key="hotel-property-123"
)

Then retrieve devices or access control systems depending on what the hotel connected:

For consumer smart locks (August, Yale, etc.):

devices = seam.devices.list(
  connected_account_id=account.connected_account_id
)

For access control systems (Salto, ASSA ABLOY, etc.):

# Get the access control system
acs_systems = seam.acs.systems.list(
  connected_account_id=account.connected_account_id
)

# Get all doors/entrances in the system
acs_entrances = seam.acs.entrances.list(
  acs_system_id=acs_system.acs_system_id
)

Step 2: Map Hotel Rooms to Seam Spaces

After a hotel connects their access control system, you need to map each room in your PMS to a Seam Space. A Space represents a physical location (like a hotel room) and can have one or more doors/entrances.

How to Map Rooms

For each room in your PMS, create a Space tagged with your room ID:

seam.spaces.create(
  name="Room 304",
  acs_entrance_ids=[door_entrance_id],
  space_key="property-123-room-304"  # Your PMS room ID
)

The space_key links the Seam Space to your room record. You can now reference this room using your existing room ID whenever you need to grant access.

For multi-door rooms (like suites), include multiple entrance IDs:

seam.spaces.create(
  name="Presidential Suite 1200",
  acs_entrance_ids=[main_door_id, bedroom_door_id],
  space_key="property-123-suite-1200"
)

Retrieving Mapped Rooms

Retrieve a Space directly using your PMS room ID:

room_space = seam.spaces.get(
  space_key="property-123-room-304"
)

Step 3: Create User Identities for Guests

Before creating access grants, you need to create a User Identity for each guest. User Identities represent the people receiving access and are especially important for mobile keys, which need to be tied to a specific person.

How to Map Guest Records to User Identities

Create a User Identity tagged with your guest ID using user_identity_key:

user_identity = seam.user_identities.create(
  user_identity_key="guest-12345",  # Your PMS guest ID
  full_name="Jane Smith",
  email_address="jane.smith@example.com",
  phone_number="+1-415-555-0123"
)

Recommendation: Use your internal guest ID directly as the user_identity_key. This makes it simple to retrieve the User Identity later:

user_identity = seam.user_identities.get(
  user_identity_key="guest-12345"  # Your PMS guest ID
)

Mobile Keys vs. Physical Cards

For mobile keys: Always create a unique User Identity for each guest, as mobile keys are delivered to their personal device via email or SMS.

For plastic cards: We recommend:

  • Reuse a generic User Identity for all guests in the same reservation (e.g., use your booking ID as the user_identity_key)

Since plastic cards aren't tied to a device, the User Identity is primarily for record-keeping rather than credential delivery.


Step 4: Create Access Grants for Guest Bookings

When a guest checks in, you create Access Grants that grant them access to their room. A single booking can have multiple Access Grants - for example, one for a plastic card and another for a mobile key. Tag each Access Grant with your booking ID using reservation_key so you can retrieve all access grants for a booking.

How to Map Bookings

At check-in, create an Access Grant tagged with your booking ID:

# Create mobile key access grant
mobile_grant = seam.access_grants.create(
  user_identity_id=guest_user_identity_id,
  starts_at="2025-12-15T15:00:00.000Z",
  ends_at="2025-12-18T11:00:00.000Z",
  space_ids=[room_space_id],
  requested_access_methods=[{"mode": "mobile_key"}],
  reservation_key="booking-78901"  # Your PMS booking ID
)

# Create card access grant for the same booking
card_grant = seam.access_grants.create(
  user_identity_id=booking_user_identity_id,
  starts_at="2025-12-15T15:00:00.000Z",
  ends_at="2025-12-18T11:00:00.000Z",
  space_ids=[room_space_id],
  requested_access_methods=[{"mode": "card"}],
  reservation_key="booking-78901"  # Same booking ID
)

The reservation_key links all Access Grants to your booking record. Access automatically expires at checkout time based on ends_at.

Retrieving All Access Grants for a Booking

Retrieve all Access Grants for a booking using your PMS booking ID:

access_grant = seam.access_grants.list(
  reservation_key="booking-789456"
)

# Returns all access grants for this booking (mobile key, card, etc.)

How Resource Keys Work

When you create Seam resources, you tag them with your PMS IDs using resource keys. Seam stores these keys, allowing you to retrieve Seam resources directly using your existing identifiers.

What gets stored in Seam:

  • customer_key - Your property ID

  • space_key - Your room ID

  • user_identity_key - Your guest ID

  • access_grant_key - Your booking ID

How to retrieve using your IDs:

# Find a property's connected accounts using your property ID
accounts = seam.connected_accounts.list(
  customer_key="hotel-property-123"  # Your PMS property ID
)

# Find a room using your room ID
room = seam.spaces.get(
  space_key="property-123-room-304"  # Your PMS room ID
)

# Find a booking's access grant using your booking ID
grant = seam.access_grants.get(
  access_grant_key="booking-789456"  # Your PMS booking ID
)

Since Seam stores your IDs as resource keys, you don't need to maintain a separate mapping table. Just use your existing PMS IDs when calling Seam's API.


Complete Workflow Examples

Check-in with Physical Key (Encoder)

# 1. Create user identity (per-booking for plastic cards)
user_identity = seam.user_identities.create(
  user_identity_key="booking-78901",  # Use booking ID for plastic cards
  full_name=guest_name
)

# 2. Find the room and create access grant with your booking ID
room = seam.spaces.get(space_key=f"room-1234"). # Your PMS room ID

grant = seam.access_grants.create(
  user_identity_id=user_identity.user_identity_id,
  starts_at=checkin_datetime,
  ends_at=checkout_datetime,
  space_ids=[room.space_id],
  requested_access_methods=[{"mode": "card"}],
  reservation_key="booking-78901"  # Your PMS booking ID
)

# 3. Retrieve the card access method from the grant
access_methods = seam.access_methods.list(
  access_grant_id=grant.access_grant_id
)

card_method = next(am for am in access_methods if am.mode == "card")

# 4. Encode the physical key at front desk
seam.acs.encoders.encode_card(
  acs_credential_id=card_method.acs_credential_id,
  acs_encoder_id=front_desk_encoder_id
)

Check-in with Mobile Key

# 1. Create or retrieve the user identity for the guest
user_identity = seam.user_identities.create(
  user_identity_key="guest-12345",  # Your PMS guest ID
  full_name=guest_name,
  email_address=guest_email,
  phone_number=guest_phone
)

# 2. Find the room Space using your PMS room ID
room = seam.spaces.get(space_key=f"room-1234")  # Your PMS room ID

# 3. Create access grant tagged with your PMS booking ID
grant = seam.access_grants.create(
  user_identity_id=user_identity.user_identity_id,
  starts_at=checkin_datetime,
  ends_at=checkout_datetime,
  space_ids=[room.space_id],
  requested_access_methods=[{"mode": "mobile_key"}],
  reservation_key="booking-78901"  # Your PMS booking ID
)

# 4. Retrieve the mobile key access method from the grant
access_methods = seam.access_methods.list(
  access_grant_id=grant.access_grant_id
)

mobile_key = next(am for am in access_methods if am.mode == "mobile_key")

# 5. Send guest the mobile key URL
send_sms(guest_phone, mobile_key.instant_key_url)

Early Check-out

# Find all access grants for the booking and revoke them
grants = seam.access_grants.list(reservation_key=f"booking-12345")

for grant in grants:
  seam.access_grants.delete(access_grant_id=grant.access_grant_id)

Looking Up Guest Access During Stay

# Guest reports they can't get into their room - look up by booking ID
grant = seam.access_grants.get(access_grant_key=f"booking-1234")

# Check grant time frame
print(f"Active: {grant.starts_at} to {grant.ends_at}")

# Check status of issued access methods
access_methods = seam.access_methods.list(access_grant_id=grant.access_grant_id)

for method in access_methods:
  print(f"{method.mode}: {method.status}")
  # Status could be: "issued", "unissued", "issuing", etc.

Best Practices for Resource Mapping

Use Your Internal IDs Directly

Use your existing PMS identifiers directly as resource keys:

  • customer_key: Your property ID (e.g., "property-456")

  • space_key: Your room ID (e.g., "room-304")

  • user_identity_key: Your guest ID (e.g., "guest-12345")

  • access_grant_key: Your booking ID (e.g., "booking-78901")

This creates a direct mapping between your PMS identifiers and Seam resources.

Create Spaces Once, Reference Many Times

Map rooms to Spaces once when setting up a property:

# Do this once during property setup
for room in property.rooms:
  seam.spaces.create(
    name=f"Room {room.number}",
    acs_entrance_ids=[room.door_id],
    space_key=f"property-{property.id}-room-{room.number}"
  )

Then reference the Space using space_key for every booking:

# Do this at every check-in
room = seam.spaces.get(space_key=f"property-{property_id}-room-{room_number}")
# Create access grant referencing this Space...

Handle Multi-Property Integrations

For PMS systems serving multiple hotel properties:

  1. Create separate Connect Webviews for each property with unique customer_key

  2. Always filter operations by customer_key to keep properties isolated

  3. Store the customer_key to property_id mapping in your database

# When querying devices for a specific property
accounts = seam.connected_accounts.list(customer_key=f"hotel-property-{property_id}")

Additional Resources


Need Help?

If you have questions about implementing this data model or need assistance with your specific use case, contact Seam support (support@seam.co) or your solutions engineer.