Skip to content

Iframe messages

The iframe and your page talk with window.postMessage. There are six message types: four from the iframe to your page, two from your page to the iframe.

Every message, in both directions, has this shape.

{
"version": 1,
"type": "flume:iframe_ready",
"session_uuid": "c1f0a6de-3b52-4d8e-9c47-2f8a1b6d0e93",
"payload": {}
}
FieldTypeNotes
versionnumberAlways 1
typestringOne of the six types below
session_uuidstringThe session from POST /start-iframe-session
payloadobjectDepends on type

Drop a message unless all four hold.

CheckWhy
event.origin equals the iframe's originAnother frame cannot pose as Flume
event.source is your iframe's contentWindowAnother window on that origin cannot pose as this iframe
data.version is 1A future version is ignored safely
data.session_uuid is your session'sA stale iframe cannot write to a new item

Ignore any type you do not know. The host snippet does all of this.

Every message, and which way it goesAll six postMessage types between the iframe and your page, in the order one open usually sends them. Four come to your page, two go back. The same content is listed as text under the diagram.Flume iframeYour page1flume:iframe_ready2flume:user_connected3flume:save_item4flume:item_saved5flume:item_save_failed6flume:close_iframepostMessageLighter: not every time

Every message, and which way it goes. All six postMessage types between the iframe and your page, in the order one open usually sends them. Four come to your page, two go back.

Read this diagram as text
  1. The iframe posts flume:iframe_ready once it has painted, with an empty payload. Clear the ready timer and show the iframe.
  2. First open only: the iframe posts flume:user_connected with a connect_code. Send it to your backend at once. The iframe expects no reply.
  3. The iframe posts flume:save_item with the save payload, which carries save_uuid. It waits 60 seconds for your reply.
  4. Your page replies flume:item_saved with the same save_uuid, and item_ref and item_label when you have them.
  5. Or your page replies flume:item_save_failed with the same save_uuid and a reason: permission, conflict, storage or error.
  6. The iframe posts flume:close_iframe with a reason of done, closed or expired. Remove the iframe. On expired, start a new session.
TypeDirectionPayloadWhen
flume:iframe_readyIframe to pageEmptyThe iframe has loaded
flume:user_connectedIframe to pageconnect_codeThe user verified their email
flume:save_itemIframe to pageThe save payloadThe user saved a product
flume:close_iframeIframe to pagereasonThe iframe should be removed
flume:item_savedPage to iframesave_uuid, your idsYour write worked
flume:item_save_failedPage to iframesave_uuid, reasonYour write failed

The iframe has loaded and drawn its first screen.

  • Payload: {}.
  • Do this: clear your ready timer, remove your spinner, move focus into the iframe.
  • It is also sent when the iframe loaded but could not start, for example with a used launch code. The iframe then shows its own error, with a retry and a close button. Your page cannot tell the two cases apart, and does not need to: clear the timer in both.
  • After a failed start, the iframe's close button sends flume:close_iframe with closed, and its retry sends expired.

The user verified their email inside the iframe.

Payload fieldTypeNotes
connect_codestringSingle use. Valid for 120 seconds
{
"version": 1,
"type": "flume:user_connected",
"session_uuid": "c1f0a6de-3b52-4d8e-9c47-2f8a1b6d0e93",
"payload": { "connect_code": "connect_example_code_0000" }
}
  • Do this: send connect_code to your backend. Call POST /users/exchange-connect-code. Store the access_token over any token you held for the user.
  • Any token you held for this user stopped working when they verified. See Users and verification.
  • If you skip the exchange, you hold no working token. The user verifies again on the next open.

The user confirmed a save. The payload is the full save payload, one JSON object.

Payload fieldTypeNotes
save_uuidstring (UUID)Identifies this save. A retry carries the same value
schema_versionstring"1.0"
Other fieldsSee Save payload
  • Do this: write the item into your records, then reply with flume:item_saved or flume:item_save_failed.
  • Reply within 60 seconds. Silence counts as a failure.
  • If the user presses "Try again", you get the same save_uuid again. Do not write a second record.

The iframe is done. Remove it from your page.

Payload fieldTypeValues
reasonstringdone, expired or closed
reasonMeaningDo this
doneThe user finished after a saveRemove the iframe. Refresh your data
expiredThe session ended, or the user pressed Try again after a failed startStart a session again and remount
closedThe user pressed X or EscapeRemove the iframe
{
"version": 1,
"type": "flume:close_iframe",
"session_uuid": "c1f0a6de-3b52-4d8e-9c47-2f8a1b6d0e93",
"payload": { "reason": "done" }
}

Post replies to the iframe's window, with the iframe's origin as the target origin. Never use "*".

frame.contentWindow.postMessage(
{ version: 1, type: "flume:item_saved", session_uuid: sessionUuid, payload },
new URL(iframeUrl).origin,
);

The iframe accepts a reply only when all of these hold:

  • it comes from the page that framed it,
  • that page's origin is the host_origin you sent,
  • it carries the session's session_uuid,
  • its save_uuid is the save the iframe is waiting on.

A reply that fails one of these is ignored, and the save waits out its 60 seconds.

Your write worked.

Payload fieldTypeRequiredNotes
save_uuidstring (UUID)YesFrom the flume:save_item you are answering
item_refstringNoYour id for the record. Max 128 characters
item_labelstringNoYour label for it. Max 200 characters
{
"version": 1,
"type": "flume:item_saved",
"session_uuid": "c1f0a6de-3b52-4d8e-9c47-2f8a1b6d0e93",
"payload": { "save_uuid": "2b9d6f1c-7a34-4e58-b0c2-9d1e3f5a7b6c", "item_ref": "row_9931", "item_label": "T-1.A" }
}

Your write failed. The iframe shows the user a retry.

Payload fieldTypeRequiredNotes
save_uuidstring (UUID)YesFrom the flume:save_item you are answering
reasonstringYespermission, conflict, storage or error
messagestringNoDetail for Flume's logs. Cut at 500 characters. Never shown to the user
reasonUse it when
permissionThe user may not edit that record
conflictThe record changed or is locked
storageYour write failed
errorAnything else

The payload must be a plain object. A thrown Error cannot be sent as it is. The host snippet turns one into a proper payload.

Every way a save can endThree outcomes of one flume:save_item. Two of them show the user the same message, and a retry repeats the same save_uuid. The same content is listed as text under the diagram.flume:save_itemcarries save_uuidflume:item_savedyour write workedflume:item_save_failedpermission, conflict,storage or errorNo replywithin 60 secondsSaved screenshows item_labelCould not saveClose, or Try again

Every way a save can end. Three outcomes of one flume:save_item. Two of them show the user the same message, and a retry repeats the same save_uuid.

Read this diagram as text
  1. The iframe posts flume:save_item with a save_uuid.
  2. Your page replies flume:item_saved: the user sees the saved screen, with your item_label when you send one.
  3. Your page replies flume:item_save_failed with a reason of permission, conflict, storage or error: the user sees one message with Close and Try again. The reason is not shown.
  4. Your page does not reply within 60 seconds: the user sees the same message.
  5. Try again posts flume:save_item again with the same save_uuid. Your write must be safe to repeat.
CaseThe user sees
You reply flume:item_savedA saved screen. It shows item_label when you send one, as "Saved as ...". Otherwise your item's own label
You reply flume:item_save_failed, with any reasonOne message: the save to your product failed, with Close and Try again. reason and message are never shown
You do not reply within 60 secondsThe same message
Your reply arrives after thatA late reply for the same save_uuid can still be applied while that save is the current one. Do not rely on it: reply within the time limit
Flume could not build the payloadAn error from Flume. Your page receives no flume:save_item
  • Try again sends flume:save_item again with the same save_uuid. A slow write of yours may have finished meanwhile, so the write must be safe to repeat.
  • After a save, the user can press Done, which sends flume:close_iframe with done, or open the product in Flume, which keeps the iframe open.
  • It posts only to the host_origin you sent when you started the session. If your page is on another origin, no message reaches it.
  • It reports each save's result to Flume itself. Your backend makes no call for it.
  • One exception: when the iframe cannot start, it has no session. It then posts only flume:iframe_ready and flume:close_iframe, to the page that framed it.
  • No resize message. You size the iframe.
  • No error message. The iframe shows its own error screen when it cannot start. Your ready timer covers a frame that never loads.
  • No message per search or per quote. Only a save reaches your page.

version is 1. A message with another version, or a type you do not know, must be ignored.