> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blujay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Embedded view

> Show a customer's text threads inside your product, in your brand.

Put Blujay's messaging screen inside your product, so a customer's teammate texts from your app without building threads, bubbles and replies yourself. Your server creates a short-lived view URL; your page puts it in an iframe.

![The embedded view showing a conversation with a photo, a threaded reply, a heart reaction, a Read receipt and a typing indicator](https://mintcdn.com/blujay-api/puUPdHZjY8zVeT-I/images/partners/embedded-view.png?fit=max\&auto=format\&n=puUPdHZjY8zVeT-I\&q=85\&s=b0c82a2a072c81b8cc271f27aa5a631d)

One conversation in the embedded view: photos, threaded replies, reactions, read receipts and typing, as in Messages.

> [!NOTE]
>
> **Partner accounts only.** Before your first view, send [Blujay support](https://docs.blujay.io/support.md) the exact origins that will frame it (like `https://app.example.com`, plus your staging origin), your accent color as `#RRGGBB`, and optionally your logo's https URL.

## Create a view URL

Call this from your server when the page that shows the view loads. Any partner key works, with the customer's header.

```bash curl theme={null}
curl -X POST https://api.blujay.io/v1/embed/sessions \
  -H "Authorization: Bearer blu_your_api_key" \
  -H "Blujay-Workspace: workspace_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "team_member_id": "member_abc123",
    "mode": "thread",
    "phone_number": "+15555550101",
    "parent_origin": "https://app.example.com"
  }'
```

```javascript Node.js theme={null}
const response = await fetch("https://api.blujay.io/v1/embed/sessions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BLUJAY_API_KEY}`,
    "Blujay-Workspace": "workspace_abc123",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    team_member_id: "member_abc123",
    mode: "thread",
    phone_number: "+15555550101",
    parent_origin: "https://app.example.com",
  }),
});
const { url } = (await response.json()).data;
```

```python Python theme={null}
import os
import requests

response = requests.post(
    "https://api.blujay.io/v1/embed/sessions",
    headers={
        "Authorization": f"Bearer {os.environ['BLUJAY_API_KEY']}",
        "Blujay-Workspace": "workspace_abc123",
    },
    json={
        "team_member_id": "member_abc123",
        "mode": "thread",
        "phone_number": "+15555550101",
        "parent_origin": "https://app.example.com",
    },
    timeout=60,
)
url = response.json()["data"]["url"]
```

```json 201 Created theme={null}
{
  "status": "success",
  "data": {
    "url": "https://.../embed/partner/k3J9xQ2b...#intent=...",
    "expires_at": "2026-10-28T17:01:00.000Z"
  },
  "trace_id": "trc_8f2a1c0e4b7d",
  "timestamp": "2026-10-28T17:00:00.000Z"
}
```

Put `data.url` straight into the iframe. It works once, for 60 seconds, so create it when the page loads and never log, store or share it. Full reference: [Create an embedded view URL](https://docs.blujay.io/api-reference/partners/create-an-embedded-view-url).

## Modes

| `mode` | Shows | Also send |
| - | - | - |
| `thread` | One conversation. Blujay's servers refuse anything outside it. | Exactly one of `phone_number` (it doesn't need to be a contact yet) or `chat_id`. |
| `inbox` | The customer's whole inbox, with the assignee filter. | Neither. |

The view acts as `team_member_id`, so "Assigned to me" means them.

## Frame it

```html theme={null}
<iframe src="{url}" title="Messages" style="width:100%;height:640px;border:0"></iframe>
```

Only the page at `parent_origin` can frame it. Don't add `sandbox` restrictions that block scripts or same-origin storage.

## Listen for the view's messages

The view posts to your exact `parent_origin` only, and listens to nothing from your page. Accept a message only when its origin is the view URL's origin.

```javascript theme={null}
const frame = document.querySelector("iframe");
const viewOrigin = new URL(frame.src).origin;

window.addEventListener("message", async (event) => {
  if (event.origin !== viewOrigin || event.data?.source !== "partner-embed") return;

  if (event.data.type === "message_sent") {
    console.log("Sent in chat", event.data.chat_id); // chat_id can be missing
  }

  if (event.data.type === "session_ended") {
    // Ask your server for a new view URL, then swap it in.
    const { url } = await fetch("/blujay/view-url").then((r) => r.json());
    frame.src = url;
  }
});
```

`/blujay/view-url` stands for your own server route that calls `POST /v1/embed/sessions`. Each message is `{ source: "partner-embed", version: 1, type, ... }`:

| `type` | When |
| - | - |
| `ready` | The view opened. |
| `message_sent` | A text or attachment was accepted for sending. Includes `chat_id` when known. |
| `session_ended` | The view ended. `reason` is `expired`, `invalid`, `unavailable` or `updated`. Create a new URL and replace the iframe's `src`. |

## What the view shows

* **Your brand.** Your accent color and logo; no Blujay name or logo. Bubbles stay iMessage blue and SMS green.
* **Messaging, not a contact record.** The contact panel shows the name, number, email, whether they use iMessage, the assignee, the sending number and group controls. Keep names and details current with [Contacts](https://docs.blujay.io/contacts.md).
* **No calls.** Calls don't start in the view.

## Good to know

* **Sessions last up to 8 hours** from opening and are never extended.
* **A view ends at its next request** if you revoke the key that made it, the customer is closed, or the teammate is deactivated.
* **Paused or closing customers can't make changes** from the view; Blujay refuses them.
* **Wrong origin?** An origin you didn't register returns `400 EMBED_PARENT_ORIGIN_NOT_REGISTERED`.

## Next steps

> [card] [Customers and teammates](https://docs.blujay.io/partners/customers)
>
> Add the teammate the view acts as.

> [card] [Partner webhooks](https://docs.blujay.io/partners/webhooks)
>
> Get every customer's events in one place.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.