@pilot-status/embed SDK.
Shared prerequisites (Chat + Connect)
- Tenant API key (
ps_, tenant-scoped) — generated in Profile → API. It never leaves your backend. (A number-scoped key can only embed its own number.) - SDK —
<script src="https://embed.pilotstatus.com.br/embed.js">ornpm i @pilot-status/embed; callPilotStatus.init(). allowedOrigins— when minting the Chat token, list the exact origins (scheme://host[:port], 1–20) allowed to embed.- Token per surface — Chat uses
POST /v1/embed/sessions(surface: "chat", a short-lived JWT kept in memory). Connect usesPOST /v1/numbers/remote-pairing(a pairing token in the URL — see Embed the Connect Page). - Renewal — Chat token TTL is 15 min with a sliding refresh window; on full expiry the SDK calls
onSessionExpired.
Chat flow
One-time setup
Your backend lists numbers with
GET /v1/numbers (x-api-key) and stores the map customer → [whatsappNumberIds].Mint a token on each page load
Your frontend asks your backend for a token; the backend calls:Response
201: { token, surface, whatsappNumberIds, allowedOrigins, expiresAt }. The backend forwards only the JWT to the frontend.postMessage protocol (parent ↔ iframe)
Envelope:{ source: "pilot-status-embed", v: 1, type, payload }. Messages without that source are ignored; the origin is validated on both sides.
| Step | Who | Message |
|---|---|---|
| A | SDK (parent) | creates <iframe src="chat.pilotstatus.com.br/?parentOrigin=<origin>"> (sandbox allow-scripts allow-same-origin allow-forms allow-popups) |
| B | iframe → parent | ready (SDK validates origin === chat.pilotstatus.com.br) |
| C | SDK → iframe | init{ token, locale, theme } (iframe validates origin === parentOrigin) |
| D | iframe | keeps the token in memory only — never in URL/localStorage |
| E | iframe → parent | resize{height}, chat:unread-count{count}, chat:conversation-opened{conversationId}, session-expired |
| — | SDK → iframe | set-theme{theme}, set-locale{locale} at runtime |
Security model
x-api-keylives only on your backend; the browser only ever handles the short-lived JWT.- The JWT is hard-scoped to its
whatsappNumberIds— the chat routes re-check on every request (defense in depth). - Token in memory only, ~15 min TTL with sliding refresh;
allowedOriginspins who may embed; postMessage origin is validated on both sides.