You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/capability-guides/customer-portals/integrate-customer-portal-into-your-application.md
+176Lines changed: 176 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,3 +48,179 @@ Use the `create_portal` endpoint to generate Customer Portals programmatically.
48
48
* Use your own IDs: Use `space_key` values that match your internal identifiers.
49
49
* Session lifetime: All portal links expire after 7 days. Generate a new portal programmatically each time a customer needs access.
50
50
51
+
***
52
+
53
+
## Embedding the Customer Portal as an iFrame
54
+
55
+
The Seam Customer Portal is a hosted, pre-authenticated interface for managing devices, access codes, reservations, and more. Instead of sharing a magic link with your end-users, you can embed the portal directly inside your own application using an iFrame. This gives your users a seamless experience without leaving your product.
56
+
57
+
### How it works
58
+
59
+
When you create a customer portal via the API, Seam returns a `magic_link` URL. This URL can be loaded in a standard HTML `<iframe>`. The portal is fully authenticated through a token embedded in the URL — no additional login is required from the end-user.
60
+
61
+
Portal links expire after **7 days**. Your backend should generate a fresh link when rendering the page, or when the current link is close to expiring.
62
+
63
+
### Step 1: Create a portal with `is_embedded: true`
64
+
65
+
Call the `/customers/create_portal` endpoint from your backend with the `is_embedded` flag set to `true`. This tells the portal to render in a layout optimized for iFrame embedding (no unnecessary navigation that would conflict with your app's own UI).
66
+
67
+
```bash
68
+
curl -X POST https://connect.getseam.com/customers/create_portal \
Use the `magic_link.url` as the `src` attribute of an iFrame in your frontend. The portal handles authentication automatically via the token in the URL.
In practice, your backend generates the `magic_link.url` and passes it to your frontend, which sets it as the iFrame `src`. Don't hardcode the URL — it contains a session token that expires.
125
+
126
+
### Step 3: Refresh the link before it expires
127
+
128
+
Portal links are valid for 7 days. If your user keeps a page open for a long time, the embedded portal will eventually expire. Handle this by:
129
+
130
+
1. **Generating a fresh link on each page load.** This is the simplest approach. Each time your user navigates to the page containing the portal, your backend calls `/customers/create_portal` and returns a new URL.
131
+
2. **Tracking expiration client-side.** Store the `expires_at` timestamp and proactively refresh the iFrame `src` before it expires.
132
+
133
+
You can also use the `/customers/open_portal` endpoint, which reuses an existing portal session if it hasn't expired yet, and creates a new one if it has.
134
+
135
+
### Configuring which features are visible
136
+
137
+
The `features` object in the request body controls which sections of the portal your customer sees. Each feature can be included or excluded:
For example, if your product only needs reservation management, you can exclude everything else:
148
+
149
+
```json
150
+
{
151
+
"features": {
152
+
"connect": { "exclude": true },
153
+
"manage": {
154
+
"exclude": false,
155
+
"exclude_reservation_management": false,
156
+
"exclude_staff_management": true
157
+
},
158
+
"organize": { "exclude": true },
159
+
"configure": { "exclude": true }
160
+
}
161
+
}
162
+
```
163
+
164
+
### Embedding a single reservation view (deep links)
165
+
166
+
If you want to embed a portal that shows a single reservation — for example, inside a reservation detail page in your PMS — use the `/customers/reservations/create_deep_link` endpoint instead.
167
+
168
+
```bash
169
+
curl -X POST https://connect.getseam.com/customers/reservations/create_deep_link \
170
+
-H "Authorization: Bearer ${SEAM_API_KEY}" \
171
+
-H "Content-Type: application/json" \
172
+
-d '{
173
+
"customer_key": "my-customer-123",
174
+
"reservation_key": "res-456"
175
+
}'
176
+
```
177
+
178
+
This returns a `deep_link.url` that you embed the same way. The portal navigates directly to the reservation page with the navigation UI hidden, so it feels like a native part of your application. Deep links automatically set `is_embedded: true` and `navigation_mode: "restricted"`.
179
+
180
+
### Localization
181
+
182
+
Set the `locale` parameter when creating the portal to display it in a different language:
183
+
184
+
* `en-US` (default)
185
+
* `pt-PT` — Portuguese
186
+
* `fr-FR` — French
187
+
* `it-IT` — Italian
188
+
* `es-ES` — Spanish
189
+
190
+
```json
191
+
{
192
+
"is_embedded": true,
193
+
"locale": "fr-FR",
194
+
"customer_data": { "..." }
195
+
}
196
+
```
197
+
198
+
### Branding and customization
199
+
200
+
If you have a customization profile set up (configured through the Seam Console), pass the `customization_profile_id` when creating the portal to apply your branding — colors, logos, and other visual settings.
**Do I need to set any special headers or CSP rules on my side?** No. The portal is designed to be embedded and does not set `frame-ancestors` restrictions. As long as your own site doesn't block iFrames in its Content Security Policy, it will work out of the box.
213
+
214
+
**Can my user interact with the portal inside the iFrame?** Yes. The portal is fully interactive — users can connect accounts, view device status, manage reservations, copy access codes, and everything else the portal supports. Adding `allow="clipboard-write"` to your iFrame tag enables the copy-to-clipboard functionality for access codes.
215
+
216
+
**What happens when the portal link expires?** The portal will show an error state. Your application should detect this (either by tracking the `expires_at` timestamp or by listening fora page errorin the iFrame) and generate a fresh link.
217
+
218
+
**Can I scope the portal to specific properties or devices?** Yes. Pass `customer_resources_filters` when creating the portal to filter which resources are visible based on their `custom_metadata`. For example, you could show only properties in a specific region or managed by a specific team.
0 commit comments