---
title: "How the iframe works"
description: "The Flume iframe runs the whole find, price and save flow inside your page. Your backend starts a session, and your page exchanges six messages with it."
url: https://docs.tryflume.ai/embed
updated: 2026-11-11
---

# How the iframe works

> The Flume iframe runs the whole find, price and save flow inside your page. Your backend starts a session, and your page exchanges six messages with it.

The Flume iframe is a page Flume hosts and you frame. It runs the whole flow: verify the user, search by photo, get an instant quote, save. Your backend starts it. Your page listens to it.

## Who does what?

| Actor | Responsibility |
|---|---|
| Your backend | Starts a session. Exchanges the connect code. Stores the user access token. Holds the partner key |
| Your page | Frames the iframe. Checks and handles its messages. Writes the saved item |
| Flume iframe | Draws every screen. Calls the Flume API with its own short-lived credential |
| Flume API | Verifies users, searches, prices, builds the save payload |

Your partner key and the user access token never reach the browser.

## What is the lifecycle?

**Diagram: The whole flow, from a click to a saved item.** One open of the iframe, end to end. Lighter steps happen only the first time a user opens it.

```mermaid
sequenceDiagram
  participant iframe as Flume iframe
  participant page as Your page
  participant backend as Your backend
  participant flume as Flume servers
  page->>backend: open item
  backend->>flume: POST /start-iframe-session
  flume->>backend: iframe_url, session_uuid
  backend->>page: iframe_url, session_uuid
  page->>iframe: iframe.src = iframe_url
  iframe-->>page: flume:iframe_ready
  iframe-->>page: flume:user_connected (not every time)
  page->>backend: connect_code (not every time)
  backend->>flume: POST /users/exchange-connect-code (not every time)
  iframe-->>page: flume:save_item
  page-->>iframe: flume:item_saved
  iframe-->>page: flume:close_iframe
```

1. The user clicks your button. Your page asks your backend to start a session.
2. Your backend calls POST /start-iframe-session with the user, project and item.
3. Flume returns iframe_url and session_uuid.
4. Your backend passes both to your page.
5. Your page starts the ready timer, adds the message listener, then sets the iframe src.
6. The iframe posts flume:iframe_ready. Your page clears the timer.
7. First time only: the user verifies their email, and the iframe posts flume:user_connected with a connect code.
8. First time only: your page sends the connect code to your backend.
9. First time only: your backend exchanges the code for the user access token and stores it.
10. The user saves a product. The iframe posts flume:save_item with the save payload.
11. Your page writes its record and replies flume:item_saved, or flume:item_save_failed.
12. The iframe posts flume:close_iframe. Your page removes the iframe.

## What is a session?

An **iframe session** is one user working on one item of one project. Your backend starts it with [`POST /start-iframe-session`](https://docs.tryflume.ai/embed/server-calls.md#start-a-session). Flume keeps its state on the server.

| You send | Required fields | Purpose |
|---|---|---|
| `user` | `external_ref`, `email` | Who is working |
| `project` | `external_ref` | Where the result is filed in the user's Flume account |
| `item` | `external_id` | What the user wants a product for |
| `host_origin` | Yes | The exact origin of the page that frames the iframe |

| You get back | Use |
|---|---|
| `session_uuid` | The session's id. Filter messages by it. Log it |
| `iframe_url` | Set it as the iframe `src` at once. It holds the **launch code** |

The launch code works once, for 120 seconds. Never store, rebuild or reuse `iframe_url`.

## When is a session reused?

Flume reuses a session when the user, the project and the item are the same.

- The item is the same when its `external_id`, `name`, `item_type`, `labels`, photo links and room names are unchanged.
- A change to one of those starts a new session.
- Quantity, unit, ZIP code and unit price are not compared.

A reopened session restores the first of these that exists:

1. A save that is still waiting for your page's reply.
2. The instant quote.
3. The search, at its last step.
4. The category detection.

## When does a session end?

| Event | What happens |
|---|---|
| The user closes the iframe | The session stays. A reopen resumes it |
| 12 hours pass since the session's first open | The iframe posts `flume:close_iframe` with reason `expired`. Start a session again |
| You revoke the user's access token | The session ends at its next call |
| The user's access token is replaced | The session ends at its next call |
| 30 days pass with no use | The session is dropped. The next open starts fresh |

- Reopening the same item does not restart the 12 hours.
- Inside those hours the iframe renews its own credential. You do nothing.

## What must you build?

| Piece | Where |
|---|---|
| A call to start a session | Backend |
| A call to exchange a connect code | Backend |
| A handler that writes a saved item | Backend or page |
| The iframe tag and the [host snippet](https://docs.tryflume.ai/embed/host-page.md#the-host-snippet) | Page |

The [full example](https://docs.tryflume.ai/embed/example.md) has all four in three small files.

## What must you store?

**Diagram: What you store, and what you never store.** Two things are worth keeping. Everything else is used once and dropped.

```mermaid
flowchart LR
  s-exchange["Exchange response / POST /users/exchange-connect-code"]
  s-save["flume:save_item / the save payload"]
  s-start["Session response / POST /start-iframe-session"]
  s-connected["flume:user_connected"]
  k-token["User access token / per external_ref, encrypted"]
  k-item["Your saved item / keyed by save_uuid: your fields, / photo bytes, product_url, two ids"]
  n-url["iframe_url / set as the iframe src at once"]
  n-code["connect_code / exchange at once"]
  s-exchange -->|"access_token"| k-token
  s-save -->|"mapped fields"| k-item
  s-start -->|"use once"| n-url
  s-connected -->|"use once"| n-code
```

1. From the exchange response, store the user access token, per external_ref, encrypted, on your server.
2. From flume:save_item, store your own record keyed by save_uuid: the fields you map, the photo bytes, product_url, and the two ids an Open in Flume link needs (match.search_session_uuid and product.sku_uuid).
3. Never store iframe_url or its launch code. Set it as the iframe src at once.
4. Never store a connect code. Exchange it at once.
5. Also never store image links or an Open in Flume link: both expire. Log session_uuid with your item id and user id.

| What | Why |
|---|---|
| The user access token, per user, on your server | Send it on the next open so the user skips the email step |
| A stable `external_ref` per user | Flume finds the user's earlier work by it |
| A stable `project.external_ref` and `item.external_id` | A reopen of the same item resumes where the user was |
| `session_uuid`, with your item id and user id | Flume support asks for it |
| `save_uuid` with your own record | So a retried save writes nothing twice |
| The mapped payload and copies of the image bytes | Image links expire |
| `product_url` | The durable link back to the product in Flume |

## What does the iframe not do?

- It does not resize itself. You size the element. See [Set up your page](https://docs.tryflume.ai/embed/host-page.md#sizing).
- It does not send an error message. See [Timeouts and expiry](https://docs.tryflume.ai/embed/timeouts.md) for how failures show.
- It does not navigate your page. The iframe tag grants no top navigation.
- It does not call your backend. All it sends you are the [messages](https://docs.tryflume.ai/embed/messages.md).
- It has no theming options you can set from your page.
- There is no npm package for the host snippet. Copy the file from [Set up your page](https://docs.tryflume.ai/embed/host-page.md).

## Next

- [Quickstart](https://docs.tryflume.ai/quickstart/embed.md)
- [Set up your page](https://docs.tryflume.ai/embed/host-page.md)
- [Iframe messages](https://docs.tryflume.ai/embed/messages.md)
