postMessage API between the parent window (your application) and the iframe (the TimelinesAI QR page). Partners use it to:
- Trigger flows programmatically (start QR generation, request a pairing code) without the user clicking inside the iframe.
- Receive raw payloads (QR data, pairing code) that can be rendered in the partner’s own UI, optionally with the iframe hidden entirely.
- Observe connection state and errors.
Prerequisite: your partner record must have your embedding domain(s) registered. Messages from origins not on the allowlist are silently ignored. See Embedding overview → Prerequisite.
Message direction summary
Inbound messages (parent → iframe)
Send messages to the iframe withiframe.contentWindow.postMessage(payload, targetOrigin). The iframe validates event.origin against your registered embedding domain before processing.
TIMELINES_START_QR
Starts QR-code generation. Equivalent to the user clicking the “Generate QR Code” button in the default UI.
TIMELINES_QR_CODE_DATA outbound events as QR codes are generated and rotated (~every 45 seconds while waiting for a scan).
TIMELINES_START_PHONE_LINKING
Requests an 8-digit pairing code for a specific phone number. Equivalent to the user typing their number into the phone-pairing form and clicking “Request pairing code”.
The iframe will dispatch
TIMELINES_PAIRING_CODE once the code is issued, then TIMELINES_QR_CONNECTED when the user enters it on their phone.
Outbound messages (iframe → parent)
Listen withwindow.addEventListener("message", handler). Always validate event.origin against https://app.timelines.ai before trusting the payload.
TIMELINES_QR_CODE_DATA
Fires every time a new QR code is generated, including rotations (~every 45 seconds while waiting for a scan). The data field is a base64-encoded SVG data URL — drop it directly into an <img> element, a CSS background-image, or any surface that accepts a data URL.
This event is dispatched only to partners that started the flow with
TIMELINES_START_QR. If you embed the iframe with the default UI and never send any inbound message, the QR is rendered inside the iframe instead and this event does not fire.TIMELINES_PAIRING_CODE
Fires when an 8-digit pairing code has been issued in response to TIMELINES_START_PHONE_LINKING.
TIMELINES_QR_CONNECTED
Fires once the WhatsApp account is successfully connected, regardless of whether the user used QR or phone pairing. The payload is empty.
TIMELINES_START_QR / TIMELINES_START_PHONE_LINKING message. Default-UI iframes that never send an inbound message still receive this event.
After this event the QR link is invalidated server-side. To check the connected account’s identifier and phone number, call the Public API or Get workspace details. Generating a new QR for the same user requires a fresh call to Generate QR code for user.
TIMELINES_ERROR
Fires on flow failures. The message field carries a human-readable description suitable for display.
Conditions that emit
TIMELINES_ERROR:
- QR-code mismatch on scan
- Server-side ban (account or device)
- WhatsApp logout (
logged_out,logged_out_client) - WhatsApp-side ban (
banned) - Account flagged for payment (
payment_required) - Pairing-code timeout (during the phone-linking flow)
- Pairing-code request failure (e.g. invalid phone number, blacklisted number)
End-to-end example: custom QR UI
Hide the iframe and render the QR code yourself. Thedata field is a ready-to-use SVG data URL — drop it into an <img>:
<img>:
End-to-end example: custom phone-pairing UI
Same skeleton, different inbound trigger and a different outbound event to handle:Implementation notes
- The iframe must be loaded (
loadevent fired) before the parent can send inbound messages. Sending earlier is a no-op. - Origin validation is exact. If your registered embedding domain is
https://app.example.com, sending fromhttps://www.app.example.comwill fail silently. Register every variant you embed from. TIMELINES_QR_CODE_DATAandTIMELINES_PAIRING_CODEare gated. They only fire once you’ve sentTIMELINES_START_QRorTIMELINES_START_PHONE_LINKINGrespectively. Default-UI partners who never send an inbound message will not receive these events — the QR / pairing code is rendered inside the iframe instead.TIMELINES_QR_CONNECTEDis not gated. It fires for any embedded session — both for partners using the default UI and for partners driving the flow withpostMessage— so you can always rely on it as a connection-success signal.- QR-code timeout has no outbound notification today. If you’ve hidden the iframe entirely and rely only on
postMessage, you will not learn that the QR has expired. See the warning underTIMELINES_ERROR. - Phone-pairing UI always renders inside the iframe. There is no toggle to disable it. If you want a QR-only flow, hide the iframe entirely and drive QR via
TIMELINES_START_QR. - The default UI remains active even if you hide the iframe. Hiding the iframe prevents the user from seeing TimelinesAI’s UI but does not disable it server-side.
- The
qr_linkis single-use across connections. AfterTIMELINES_QR_CONNECTED, generating another QR for the same user requires a fresh call to the QR endpoint.
See also
- Embedding overview
- Generate QR code for user
- Partner API Overview → QR code embedding —
display_mode=embeddingURL parameter

