What an embed block is
An embed block frames one of your pages inside Custral. Your page renders in its own origin, and (if you ask for it and the workspace agrees) receives a short-lived credential it can use to read the data the block is configured to show. Two things are worth being clear about before you build one.A customer can already frame your page without you. The built-in
Embed block takes any
https:// URL. What
declaring one buys you is context: which record the reader is on, which
filters are applied, and a token to read rows with.Declaring one
An embed block is declared on your provider manifest alongside your properties, sync and AI pack:The template placeholders
Every value is URL-encoded, so a value containing
&, # or a space arrives as
one parameter rather than changing the shape of your URL.
A template that resolves to a different origin than you declared is refused,
not corrected. The block renders a refusal instead of framing anything. That
includes a placeholder in the host: https://{{org.id}}.acme.com/… is rejected
at declaration time.
A worked example: a panel on a record
Point the block at a record page and read the record it is on.dana@acme.com, your page is framed at:
record and email parameters are always present. Their emptiness is the
signal.
The handshake
Your page and Custral talk overpostMessage.
1
Your page posts custral:ready
Attach your
message listener first. The host replies immediately, and
a listener attached after the post misses custral:init.2
Custral replies with custral:init
Carrying
protocolVersion, your token, and the first context.3
Custral sends custral:context whenever anything changes
A filter moved, the reader opened a different record, the theme changed.
4
Your page posts custral:resize as its content grows
The host clamps the height. Report it from a
ResizeObserver, not once on
mount.The token
custral:init carries a short-lived token scoped to one block instance.
- Send it as
Authorization: Bearer <token>to/v1. - It expires in 15 minutes and is reusable within that window.
- It never appears in your URL, and you must never put it there. URLs leak
into access logs,
Refererheaders, browser history and forwarded links. - It carries your declared scopes intersected with what the viewer can already do. A viewer who cannot write never hands you a token that can.
- Uninstalling your provider stops it working at once, not when it expires.
What you cannot do
A reference implementation
apps/web/src/app/embed-demo in the Custral repository is a working embed: it
posts custral:ready, renders the context, reports its height from a
ResizeObserver, and makes one /v1/me call with the token. It is written to
be copied.