Skip to content
OpenAppPhysical access, simplified
Login

Create a time-bound guest invitation via API

Time-bound guest access lets visitors open a door or gate only during a stay — typical for short-term rentals, hotels, and event hosts. OpenApp models this as an access invite tied to one or more access portals (lobby QR, garage entry, and so on).

This guide is for integrators and agents connecting a PMS/VRMS or custom booking system to OpenApp. Guests consume invites through public routes documented in Public Access. For sector framing, see Model by sector (hotel and STR rows).

ValueSource
API keyCreate an API key
Organization idDashboard or GET /orgs
Virtual Access integration idDashboard → Integrations
Portal id(s)Organization resources → Portals — select your Virtual Access integration, open a portal (lobby / garage); Resource id on the Metadata tab

POST /integrations/{integration_id}/access-invites creates a link the guest can claim. portal_ids must include at least one portal that grants portal_open.

Bound guest access in one of these ways (see create_integration_access_invite):

Send kind: share for a short-term invitation (TTL + max uses, no photo or schedules). Omit kind or send invitation for a planned guest visit. Shares default to 1 use when max_uses is omitted. See Shares.

StyleFieldsTypical use
Absolutevalid_from + valid_to (RFC 3339 UTC)PMS check-in / check-out dates (example below)
Relativeexpires_in (e.g. 1h, 1w, 365d, P1D)Window length from the resolved start — RFC 5545 §3.3.6 (ISO 8601 P/PT durations); compact tokens such as 2h30m are also accepted — see Send guest invitations
Multi-windowschedulesSeveral entries; each supports absolute times or relative starts_in / expires_in

Start time: When you omit the start, the window opens immediately — the server sets valid_from to now (request time). Use valid_from (RFC 3339) for a fixed check-in, or starts_in inside schedules for a relative delay (e.g. 1h, P1D); valid_from and starts_in are mutually exclusive on each entry.

End time: valid_to and expires_in are mutually exclusive — provide one. expires_in is measured from the resolved start (including now when no start was specified).

The curl and Python examples below use absolute stay dates — the usual shape for hotel and STR bookings.

Limit sharing without adding guest friction

Section titled “Limit sharing without adding guest friction”

An access invite can limit two different things:

  • max_devices limits the number of unique guest browsers/devices that can register the invitation. The public web app creates a persistent browser identifier in localStorage, so the same device can keep using the invite without consuming another slot. A device that is already registered does not consume a second slot.
  • max_uses limits invite redemptions/usages independently of the device count. Use this when the booking or access policy should cap total use; use max_devices when the goal is to stop a forwarded link from being shared with an unbounded number of people.

For a family, group, or shared accommodation booking, set max_devices from the expected occupancy—for example, 4 for two adults and two children. Choose max_uses separately based on how many total openings/redemptions the access policy permits. Omit either field (or send JSON null where supported) for no limit.

If the device limit is reached, the guest receives a generic capacity message and the invitation is not usable from a new device. This behavior is suitable for hotels, short-term rentals, serviced apartments, events, offices, and other PMS/VRMS-backed guest flows; the sharing system remains the source of the occupancy decision.

SDK

created = await client.integrations.create_access_invite(
integration_id,
portal_ids=[portal_id],
name="Guest — June stay",
valid_from="2026-06-01T15:00:00Z",
valid_to="2026-06-05T11:00:00Z",
max_uses=30,
)
invite_token = created["invite_token"]

For copy-paste programs in every shipped language, see Send guest invitations below.

HTTP API (curl)

Terminal window
export OPENAPP_API_BASE='https://api.openapp.house/api/v1'
export OPENAPP_API_KEY='v1_openapp_YOUR_SECRET'
export OPENAPP_ORG_ID='01HORG00000000000000000000'
export INTEGRATION_ID='01HINTEGRATION00000000000000'
export PORTAL_ID='01HPORTAL000000000000000000'
curl -sS -X POST \
-H "Authorization: Bearer ${OPENAPP_API_KEY}" \
-H "Content-Type: application/json" \
-H "X-Org: ${OPENAPP_ORG_ID}" \
-d '{
"portal_ids": ["'"${PORTAL_ID}"'"],
"name": "Guest — June stay",
"valid_from": "2026-06-01T15:00:00Z",
"valid_to": "2026-06-05T11:00:00Z",
"max_uses": 30
}' \
"${OPENAPP_API_BASE}/integrations/${INTEGRATION_ID}/access-invites"

A successful response includes invite_token and invite_link_id. Build the guest URL per your deployment (public invite routes use the token in the path — see get_public_invite).

Python (HTTP API)

import os
import httpx
async with httpx.AsyncClient() as http:
resp = await http.post(
f"{os.environ['OPENAPP_API_BASE']}/integrations/{integration_id}/access-invites",
headers={
"authorization": f"Bearer {os.environ['OPENAPP_API_KEY']}",
"content-type": "application/json",
"x-org": org,
},
json={
"portal_ids": [os.environ["PORTAL_ID"]],
"name": "Guest — June stay",
"valid_from": "2026-06-01T15:00:00Z",
"valid_to": "2026-06-05T11:00:00Z",
"max_uses": 30,
},
)
created = resp.json()
invite_token = created["invite_token"]

After the guest opens the link:

  1. GET /public/access/invites/{inviteToken} — invite payload and grants.
  2. POST .../claim — associate the invite with the device/browser.
  3. POST .../execute with grant_id — open the door (or start a session).

See Public Access for curl and SDK examples across languages.

Use PUT /integrations/{id}/access-invites/{invite_link_id} to disable (is_enabled: false) or narrow validity. DELETE removes the invite permanently. Examples live under Integrations — access invites.

For a copy-paste program that creates a one-hour invite and prints the guest URL to share, see Send guest invitations.

Wire create/update to booking webhooks — pattern in Integrate OpenApp with your existing software.


← Integrate existing software · Virtual intercom flow →