# Embed API

> Embed a playable Frame, a read-only Patch or a node card with an iframe and control it with postMessage.

Source: https://docs.tune.toys/developers/embed/ (updated 2026-11-01)

**Status:** Release, help-patch and node-card embeds, every view below, the `tunetoys-embed/v1` protocol and `@tunetoys/embed` are implemented; check the [release notes](https://docs.tune.toys/releases/) for the version that ships them on tune.toys. These docs embed node cards and help patches on every node page.

## Subjects and views

Every embed shows one **subject** in one **view**. The server decides which views a subject offers; a view it does not offer falls back to the subject's default with a console warning.

| Route                                         | Subject                                            | Views (default first)                                          |
| --------------------------------------------- | -------------------------------------------------- | -------------------------------------------------------------- |
| `https://tune.toys/embed/t/<id>`              | The current public release of a Toy                | `frame`; `patch` and `split` when the creator allows the Patch |
| `https://tune.toys/embed/r/<digest>`          | One exact release (stable for blog posts and docs) | as above                                                       |
| `https://tune.toys/embed/help/<type>/<order>` | A help patch from these docs, by node type         | `split`, `patch`, `frame`, `card` (with `node=<id>`)           |
| `https://tune.toys/embed/node/<type>`         | One node's card at its default values              | `card`                                                         |

| View    | Shows                                                                                                              |
| ------- | ------------------------------------------------------------------------------------------------------------------ |
| `frame` | The playable Frame with a Play button                                                                              |
| `patch` | The read-only Patch, drawn by the editor: values change, cards fold, ports show hints; nothing is saved or rewired |
| `split` | The Patch above the Frame and Play                                                                                 |
| `card`  | One node card, interactive like the editor's but silent; on a help patch, name the node with `node=<id>`           |

```html
<iframe
  src="https://tune.toys/embed/help/std.delay/1?view=split&theme=auto"
  title="Your first echo"
  width="560"
  height="480"
  loading="lazy"
  allow="autoplay; midi"
></iframe>
```

Or let the script build size and upgrade a placeholder: `data-tunetoys-embed` takes `toy:<id>`, `release:<digest>`, `help:<type>/<order>` or `node:<type>`.

```html
<div data-tunetoys-embed="node:std.lowpass" data-theme="dark"></div>
<script async src="https://tune.toys/embed/v1/embed.js"></script>
```

Release embeds follow the creator's embed policy and origin allowlist. Help-patch and node embeds hold no account data and may be framed by any site. A paid release without a demo never shows its Patch.

## Query parameters

All are optional; unknown keys are ignored.

| Parameter       | Values                            | Behavior                                                 |
| --------------- | --------------------------------- | -------------------------------------------------------- |
| `view`          | `frame`, `patch`, `split`, `card` | One of the views the subject offers                      |
| `node`          | a node id in the help patch       | The card to show with `view=card`                        |
| `theme`         | `light`, `dark`, `auto`           | Embed chrome and editor theme; not the Toy's Frame theme |
| `controls`      | `show`, `hide`                    | `hide` renders the Frame for display plus a Play button  |
| `preset`        | a preset id of the release        | Applied after preparation                                |
| `p.<controlId>` | number                            | Initial value of a public control, clamped; at most 32   |
| `title`         | `show`, `hide`                    | Title line                                               |
| `locale`        | a supported locale                | Embed chrome language                                    |
| `ref`           | opaque label                      | Counted in daily counters only                           |

There is deliberately no `autoplay`, no URL loading and no parameter that names an account or entitlement.

## Messages

Messages are plain objects `{ protocol, channel, id?, type, ... }`, at most 16 KiB. Host to embed: `init`, `setParameter`, `setParameters`, `play`, `stop`, `loadPreset`, `setTheme`, `requestState`. Embed to host: `ready` (with `subject`, `view` and, for releases, `digest`), `state`, `parameterChanged`, `playbackChanged`, `error`, `resize`. `play` works only after an in-frame user gesture has unlocked audio; a node card answers `not_embeddable`. Size the iframe from `resize`, which follows the handshake as soon as the embed has measured itself. Always check `event.origin` and `event.source` before trusting a message; the `@tunetoys/embed` package does this for you.

Only public control values can be read or written. No message can read source, assets or account data, install, purchase or navigate the top window.
