Login codes and sessions
Your server makes a one-time login code. The embed trades it for a session and keeps that session fresh by itself.
This page needs your own installation with an Embed license.
From your page to a session
Four parties take part. Your partner key never leaves your server, and the session never leaves the frame.
- 1mount() opens the frame and checks this page may show itGET /api/embed/v1/bootstrap (Your page to GoRunner)
- 2getCode() asks your server for a login code (Your page to Your server)
- 3Your server asks for a code, with your partner keyPOST /api/embed/v1/login-codes (Your server to GoRunner)
- 4A login code: one use, 60 secondsgrl_… (GoRunner to Your server)
- 5Your server hands the page the code, and only the code (Your server to Your page)
- 6The SDK passes the code into the frame (Your page to GoRunner frame)
- 7The frame trades the code for a sessionPOST /api/embed/v1/sessions (GoRunner frame to GoRunner)
- 8A session, held in memory for 30 minutesgri_… (GoRunner to GoRunner frame)
- 9Ready: mount() resolves and the customer sees GoRunner (GoRunner frame to Your page)
- Your page → GoRunner mount() opens the frame and checks this page may show itGET /api/embed/v1/bootstrap
- Your page → Your server getCode() asks your server for a login code
- Your server → GoRunner Your server asks for a code, with your partner keyPOST /api/embed/v1/login-codes
- GoRunner → Your server A login code: one use, 60 secondsgrl_…
- Your server → Your page Your server hands the page the code, and only the code
- Your page → GoRunner frame The SDK passes the code into the frame
- GoRunner frame → GoRunner The frame trades the code for a sessionPOST /api/embed/v1/sessions
- GoRunner → GoRunner frame A session, held in memory for 30 minutesgri_…
- GoRunner frame → Your page Ready: mount() resolves and the customer sees GoRunner
Login codes
Your server makes a code with Make a login code, naming the person, their account and their role: viewer, operator or editor. The first code for a new account or person creates them.
A code starts with grl_, works once, and runs out after 60 seconds. Never log it. One person may get 20 codes a minute.
Sessions
The frame holds its session (gri_…) in memory, never in a cookie. It lasts 30 minutes and is never extended: a renewal is a new session. Each browser tab has its own, so two tabs can be in two accounts. Only hashes of codes and sessions are kept.
Renewal
Five minutes before a session ends, the frame swaps it for a new one, and the customer notices nothing.
- By itself
- For 12 hours after the login code, the frame renews its own session (
POST /api/embed/v1/sessions/current/renew). The new one keeps the person, account, workspace, role, every switch turned off, the key and the page. The old one ends (replaced). Your server isn’t asked. - Through your page
- After the 12 hours, the SDK calls your
getCodewith the reasonrenew. So does a refused renewal: a suspended account, a Platform preview, a key revoked or past its rotation, or a website no longer allowed for the account. A tab that slept past its renewal asks too, and a reloaded frame asks withreload. - On time
- Each session carries
renewAfterandrenewInSeconds. The frame counts the seconds, so a wrong device clock still renews on time. - Limits
- At most 4 renewals a minute from one login code (
EMBED_RENEW_RATE_LIMIT, Rate limits). A self-hosted installation can set the 12 hours from 1 to 24 (EMBED_SESSION_MAX_HOURS). - Older installations
- Before v2026.10.4 the frame never renews by itself: it asks your page every 25 minutes.
When a session ends
The server ends a session early with a reason (details.reason). Your page never sees most reasons: the SDK asks your getCode for a new code, and the customer notices nothing. What your page sees, and the reasons behind it:
- A new
getCodecall - With the reason
reneworexpired, and no event. Ended byexpired,replaced,role_changed,account_suspended,account_resumedorrevoked. access_ended- One fatal
errorevent; the embed closes for good. Ended byaccess_removed,account_deleted,workspace_deletedorwebsite_removed. licenceorunavailable- One fatal
errorevent: the license lost Embed, or the installation’s sign-in is off. Ended bynot_licensedorsign_in_off. - Nothing
- The frame signed itself out, on
unmount()or an account switch:ended.
For what each code means for your page, see The error event.
A request with an ended session answers 401 EMBED_SESSION_ENDED, the reason in details.reason, and an open stream closes with it. not_licensed and sign_in_off answer 403 EMBED_NOT_AVAILABLE. An embed session is refused everywhere outside the embed’s own routes (403 EMBED_NOT_ALLOWED).
A suspended account is the one renewal your page hears about. Once the new session finds the account suspended, the embed sends an error event with code: "account_suspended" and fatal: false. The customer can still read everything.
Related
- Quick startA partner key, a login-code route and the embed in a page · 15 min
- SDKgetCode, events and errors
- SecurityKeys, websites and what never reaches the browser
Checked against 12d85b3b