> ## Documentation Index
> Fetch the complete documentation index at: https://developers.apps.filed.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Embed the binder in your product

> Show a client's binder inside your own site as a chromeless iframe, authenticated with a workspace token

The binder (Documents, Forms, and Leadsheets) can be shown inside your own
product as an iframe, with none of the Filed app's sidebar or top bar. This
is a different integration path from the rest of these guides: instead of
calling the GraphQL API yourself, you send the visitor's browser to a Filed URL
that signs them in and renders the binder UI directly.

```mermaid theme={null}
flowchart LR
  A["Your server"] -->|"1. exchange API key"| B["workspaceToken"]
  B -->|"2. build sign-in URL"| C["iframe src=<br/>/sign-in/token"]
  C -->|"3. sets cookies,<br/>redirects"| D["/embed/workspaces/:id/<br/>clients/:id/binder"]
```

<Note>
  This is a UI embed, not a GraphQL operation. The visitor's browser (inside the
  iframe) authenticates with a cookie, not a `Bearer` header, so none of the
  requests here go through your own backend.
</Note>

## 1. Get a workspace token

Exchange an API key for a `workspaceToken` exactly as described in
[Authentication](/guides/authentication): call
`exchangeSurfaceRefreshTokenForAccessTokens` from your server, and keep the API
key itself on your server. Never send the API key to the browser, only the
short-lived `workspaceToken`.

<Warning>
  The `workspaceToken` is a bearer credential for the workspace: anyone who has it
  can read and write whatever the token's access level allows. Mint it on your
  server, right before rendering the page that embeds the iframe, and never log it.
</Warning>

## 2. Build the sign-in URL

Point the iframe's `src` at `/sign-in/token` on the Filed app domain, with the
token and the embed path you want the visitor to land on:

```
https://web.apps.filed.com/sign-in/token?workspace_token=<jwt>&redirect=<path>
```

<ParamField query="workspace_token" type="string" required>
  The `workspaceToken` from step 1. Must decode to a payload containing a
  `workspaceId` claim, otherwise the visitor is sent to the sign-in page instead.
</ParamField>

<ParamField query="redirect" type="string" required>
  Where to send the browser after the cookie is set. Must be a same-origin
  relative path starting with `/` (not `//`), URL-encoded since it contains `/`.
  For an embed, this is the binder path from step 3.
</ParamField>

<Info>
  `/sign-in/token` also accepts a `user_token` parameter for a different, unrelated
  flow: signing in as a specific user rather than pinning a workspace. It is not
  used for embedding the binder.
</Info>

## 3. Create the embed element

Set the sign-in URL on an iframe element, then append it to the container where
the binder should render:

```js theme={null}
const iframe = document.createElement("iframe");
iframe.src =
  "https://web.apps.filed.com/sign-in/token?workspace_token=YOUR_WORKSPACE_TOKEN&redirect=%2Fembed%2Fworkspaces%2FYOUR_WORKSPACE_ID%2Fclients%2FYOUR_CLIENT_ID%2Fbinder";
iframe.style.cssText = "width: 100%; height: 100%; border: 0";
document.querySelector("#binder-container").replaceChildren(iframe);
```

This renders the binder the token's user gets in the Filed app, with no
sidebar and no breadcrumbs. On the classic binder that is the same three tabs,
Documents, Forms, and Leadsheets; append `/docs`, `/forms`, or `/leads2` to
land on a specific tab (the bare path redirects to `/docs`). A firm that has
moved to the new binder gets the new binder here as well, which keeps its open
document and section in `?subdoc=` and `?activeSection=` instead.

## Token expiry

Like every `workspaceToken`, the one used here expires after about 30 minutes.
When it does, the binder shows its own "session expired" state inside the
iframe rather than redirecting out (there is nowhere sensible to redirect an
iframe to on another site). Mint a fresh `workspaceToken`, build a new
`/sign-in/token` URL, and reset the element's `src` to recover.

<Tip>
  Rebuild and reset the iframe `src` on an interval shorter than 30 minutes (for
  example every 20) so visitors rarely see the expired state.
</Tip>

## Next steps

* **Authentication**: review how API keys, `workspaceToken`s, and access levels
  work in [Authentication](/guides/authentication).
* **Browse the binder over the API**: to read binder data yourself (files,
  missing items, search) instead of embedding the UI, see
  [Browse a client's binder](/guides/recipes/browse-the-binder).
