Guides/How to issue hotel key cards with an API

How to issue hotel key cards with an API

Seam lets your software issue hotel key cards: define the guest's access for their stay, write it onto plastic with the encoder at the desk, and the card opens the right doors until checkout, then stops on its own.
Quickstart

Issue a key card in 60 seconds

Three calls: the grant creates the credential, the encoder list finds the hardware at the desk, and the encode call puts the credential on plastic.
1# A two-night stay. In your PMS integration these come from the reservation.
2CHECK_IN=$(date -u +%Y-%m-%dT15:00:00Z)
3CHECK_OUT=$(date -u -v+2d +%Y-%m-%dT11:00:00Z 2>/dev/null || date -u -d '+2 days' +%Y-%m-%dT11:00:00Z)
4
5# 1. Grant card access to the room and the lobby for the stay.
6curl -X POST "https://connect.getseam.com/access_grants/create" \
7  -H "Authorization: Bearer $SEAM_API_KEY" \
8  -H "Content-Type: application/json" \
9  -d '{
10    "user_identity": {
11      "full_name": "Jane Doe",
12      "email_address": "jane@example.com"
13    },
14    "acs_entrance_ids": ["f74e4879-5991-4e2f-a368-888983dcfbfc"],
15    "requested_access_methods": [{ "mode": "card" }],
16    "starts_at": "'"$CHECK_IN"'",
17    "ends_at": "'"$CHECK_OUT"'"
18  }'
19
20# 2. Write the card access method onto a blank card with an encoder at the
21#    property. Get the access_method_id from /access_methods/list first.
22curl -X POST "https://connect.getseam.com/access_methods/encode" \
23  -H "Authorization: Bearer $SEAM_API_KEY" \
24  -H "Content-Type: application/json" \
25  -d '{
26    "access_method_id": "27d8ad77-55c2-4e20-b5b3-43555926f0e8",
27    "acs_encoder_id": "d2f5cb38-3f42-4c92-8f6a-4b8de32b6b45"
28  }'
Fastest path

Build it with your AI agent

Install the Seam plugin and your coding agent picks up three integration skills: Reservation Automations, Access Grants and Access Codes. It then writes the calls the way we would. Paste the prompt below and let it build.
  • Reservation AutomationsPush reservations to Seam and let it manage codes across the booking lifecycle.
  • Access GrantsPer-entrance, per-credential access: PIN codes, mobile keys and Instant Keys.
  • Access CodesDirect, manual control of individual time-bound codes on a specific device.

1. Install the plugin

/plugin marketplace add seamapi/seam-plugin
/plugin install seam@seamapi

The Claude Code install also adds our documentation MCP server, so the agent can look up endpoints and device capabilities while it works. Cursor, Codex and other agents get the skills through npx skills add and can add the MCP server there separately.

2. Paste this prompt

Using the Seam Access Grants skill, build key card issuance for my hotel app. In a sandbox workspace: create a user identity for a guest, create an access grant on the room and lobby entrances with requested_access_methods [{ mode: "card" }] for a two-night stay, list the encoders on the access system with /acs/encoders/list, then encode the card access method with /access_methods/encode and confirm is_issued flips to true. Finish with the express-checkout story: what happens to the card at ends_at, and how I re-encode the same plastic for the next guest.
Use cases

What you can build

  • Front desk software that cuts keys

    Check-in creates the grant and encodes the card in one flow, from your own UI. The desk agent taps one button; nobody re-types room numbers into the access system's console.

  • Kiosk and express check-in

    A kiosk with an encoder issues keys with no staff at all: the reservation lookup creates the grant, the kiosk encodes, the guest walks to the elevator. Late arrivals stop depending on the night shift.

  • Cards that expire with the stay

    The credential dies at ends_at whether or not the card comes back, and an extended stay is one update call, not a trip to the desk for new plastic. Lost cards are a deletion, not a re-key.

Walkthrough

How it works

  1. Create an Access Grant with a card access method

    The guest, the entrances their stay covers, and the window. Seam creates the card credential on the access system, and the access method comes back with is_issued false: the credential exists but is not on plastic yet. That false is your cue to encode.

    1const accessGrant = await seam.accessGrants.create({
    2  user_identity_id: guest.seamUserIdentityId,
    3  acs_entrance_ids: [room.entranceId, lobby.entranceId],
    4  requested_access_methods: [{ mode: "card" }],
    5  starts_at: reservation.checkIn,
    6  ends_at: reservation.checkOut,
    7})
    8
    9const [cardMethod] = await seam.accessMethods.list({
    10  access_grant_id: accessGrant.access_grant_id,
    11})
    12
    13// Not on plastic yet: is_issued stays false until a card is encoded.
    14console.log(cardMethod.is_issued) // false
  2. Find the encoder at the desk

    Encoders are devices on the access system. List them with /acs/encoders/list and let the desk agent pick theirs; a kiosk pins its own encoder id in config. Systems that assign credentials to pre-registered cards skip the encoder entirely, and the grant is the whole flow.

    1const encoders = await seam.acs.encoders.list({
    2  acs_system_id: reservation.acsSystemId,
    3})
    4
    5// A property usually has one per desk. Let the agent pick theirs.
    6const frontDesk = encoders[0]
  3. Encode the card

    Place a blank card on the encoder and call /access_methods/encode with the access method and the encoder. Confirm the result before handing plastic to a guest: is_issued flips to true once the write lands, and the common failures are a missing card on the encoder or a card type the system does not accept.

    1await seam.accessMethods.encode({
    2  access_method_id: cardMethod.access_method_id,
    3  acs_encoder_id: frontDesk.acs_encoder_id,
    4})
    5
    6// Confirm before handing the card over: poll the access method or listen
    7// for its webhook. is_issued true means the credential is on the plastic.
  4. Let checkout happen on its own

    No return step. The credential expires at ends_at, so an unreturned card is dead plastic, and revoking early is deleting the grant. Reuse returned cards by encoding a fresh access method onto them; one access method writes to one card, so each card gets its own.

    1// Checkout needs no API call: the card stops opening doors at ends_at,
    2// whether or not it comes back to the desk.
    3
    4// To reuse the plastic for the next guest, encode a new access method onto
    5// it. An access method is written to one card only, so each card gets its
    6// own, even for the same grant.
FAQ

Frequently asked questions

Do I need a card encoder?

For systems that write credentials onto blank cards, yes: Seam drives the encoder hardware the property already has. Other systems assign the credential to a card that is already registered, and no encoder is involved. The capability page lists which systems work which way.

Can one card open several doors?

Yes. Put every entrance on the Access Grant, or pass a space that covers them, and the card is encoded for all of them at once. Adding a door later updates the credential.

What happens to a card at checkout?

The credential expires with the grant, so the card stops opening doors at ends_at whether or not it comes back to the desk. Revoking early is a deletion, not a trip to the lock.

Can I reuse cards between guests?

Yes. Re-encode the card with the next guest's access method. What you cannot do is write one access method onto two cards: a second card for the same guest gets its own access method on the same grant.

How do I check what is on a card?

Scan it on the encoder. The scan returns the card's encoded parameters, which is how a desk agent answers "why does this card not work" without guessing: wrong stay, expired credential and blank card all read differently.

Which access systems does this work with?

Card-based hotel and multifamily systems including ASSA ABLOY Visionline and Salto Space, with the full list on the plastic-card capability page. Support is per system, so check the system behind your doors, not the lock brand on them.

Pricing
Ready to Scale With You
Seam lets developers and businesses connect apps to real-world IoT devices. The free trial is built for small teams to build and test, while enterprise pricing scales with the biggest device fleets out there.
Best Enterprise Solution
Custom Subscription for Your Business
Access tailored solutions, paying a fixed monthly rate that scales as you grow.
Enhanced Security
Beta Features Access
Dedicated Support Channel
Volume Discounts
No Usage Limits
Trusted by Over 1,000 Companies
Start Now
Try It for Free
Start with a free trial and explore the full API and related features.
Have questions? Talk to our team.
Chat with us to learn how Seam can power your access automation.
—“Discovering Seam was one of these Aha moments in the business. I couldn’t believe what I was seeing. I mean, it was exactly what we were looking for: a simple API that we could integrate and have access to all these devices in a matter of seconds.
François Gouelo
CEO, Enso Connect
Company
How many devices you need to connect?
Name
Email
How did you find us?
Comment
We usually answer within 24 hours.
One API for All Devices
Global Infrastructure for Controlling the Physical World
Seam makes controlling IoT devices seamless and programmable. Our teams operate globally,
enabling businesses of all sizes.
Smart Locks
Access Systems
Knowledge
Lock Capabilities
Thermostats
Sensors
© 2026 Seam Labs, Inc.