Installed app
Sellers can install the chat as an app at https://app.mondochat.io/frame/?app=<appId>&mode=app and get web push. The embed offers it to them. Buyers and guests stay in the embed.
Before you start
Section titled “Before you start”- A role with
seller: trueinroles. Only a member of such a role gets the install offer. - An https page on your site that signs the member in. It becomes
pwa.login_url. - A square PNG icon of at least 512 px, edge to edge, with the art inside the centre 80% circle because Android crops it to its shape.
- The app’s server secret, to sign app links.
-
Turn it on in the settings.
pwa.enabledis off by default.{"pwa": {"enabled": true,"name": "Example chat","icon_url": "https://www.example.com/chat-icon.png","login_url": "https://www.example.com/chat-app?lang={lang}"}}nameis 1 to 45 characters and is the name under the icon.enabled: truewithoutnameandicon_url, or anhttp://login_url, answers 422 on save.{lang}inlogin_urlbecomes the language the app shows.pwa.push_previewmakes notifications show the message preview instead of “New message”. See the settings reference. -
Let sellers find it. With
pwa.enabled, the embed offers a seller a dismissible Get the app card at the top of the inbox, and a Get the app row in settings that needsworkspace.inbound. Tapping it opens the installed-app page in a new window, already signed in. Your page does nothing and receives no event. -
Build the app link page at
pwa.login_url. A signed-in app can lose its sign-in: it was unused for 30 days, the user logged out, or an iPhone copied no cookies. Its Sign in button openspwa.login_urlin the same window. Your page signs the member in if needed and answers 302 to a fresh app link. The app link is the client token with headertyp: app+jwtand a requiredjti.expis at most 600 seconds afteriat. It goes in the fragment, never the query:const iat = Math.floor(Date.now() / 1000)const claims = { iss: APP_ID, sub: user.id, name: user.name, role: user.role, jti: randomUUID(), iat, exp: iat + 300 }const body = `${b64url(JSON.stringify({ alg: 'HS256', typ: 'app+jwt' }))}.${b64url(JSON.stringify(claims))}`const token = `${body}.${createHmac('sha256', SECRET).update(body).digest('base64url')}`res.redirect(302, `https://app.mondochat.io/frame/?app=${APP_ID}&mode=app#token=${token}`)b64url,APP_IDandSECRETare as in the Node server of the quickstart. The link works once. It signs the app in for 30 days from last use. The app removes the fragment from its address before any request. With nologin_urlset, a signed-out app asks the seller to open the chat on your site and tap Get the app again. -
End access when a member loses it. Delete all of a user’s devices:
Terminal window curl -X DELETE https://app.mondochat.io/v1/server/users/bob/devices \-H "Authorization: Bearer $MONDOCHAT_SERVER_SECRET" -H "Mondochat-App-Id: $MONDOCHAT_APP_ID"The call answers 204, or 404 for an unknown user. See Revoke devices. Each install is a device that signs in with an HttpOnly cookie. Bans, deleting the user and setting
pwa.enabledto false also end access. A user can log out in the app’s settings, which deletes that device. -
Know what push sends. The worker sends one notification for the first message a seller has not seen in a conversation while she is away. mondochat holds one VAPID key per environment, so you configure nothing. The manifest is served for each app by
GET /v1/apps/{app_id}/manifest.webmanifest.
Check it works
Section titled “Check it works”- A seller sees the Get the app card in the embed. Tapping it opens the app in a new window, signed in.
- Opening your
login_urlwhile signed in to your site lands the app signed in. - After step 4, the device no longer signs in and its sessions stop refreshing within 15 minutes.
When it fails
Section titled “When it fails”| Symptom | Cause |
|---|---|
| The app shows that it is not available, with no retry | pwa.enabled is off. Device routes answer 403 policy_denied with reason pwa. Stored devices work again once it is turned on. |
| Device routes answer 503 | The push key on mondochat’s side is missing or not valid. |
| The Sign in button loads a page that asks to open the chat on your site | pwa.login_url is not set. |
| An app link answers 401 | It was used before, has no jti, has another typ, belongs to another app, or is a guest token. |
POST /v1/session refuses the app link |
App links work only for the installed-app sign-in, and the installed-app sign-in refuses a plain client token. |
| 429 on opening the app from the chat | A user gets 5 app tickets per 10 minutes. |
Limits
Section titled “Limits”- A device lasts 30 days from last use, and a user has at most 10 devices: the least recently used is dropped.
- The one-time ticket the chat gives a seller lasts 120 seconds, and it is never given to a session that came from the app itself.
- An app link lives at most 600 seconds and works once.
- A seller who loses access stops refreshing within one session lifetime of 15 minutes.
- The installed-app routes under
/v1/deviceare for the app itself and are not in the API reference. They accept no cross-origin calls.