Where it is
Embed widget in the sidebar (/embed/).
Publishable keys
A key authorizes a page to start interviews.
- New key opens the create form.
- Scope — any study in the organization, or just this study.
- Allowed origins — the sites allowed to use the key, one per line (
https://acme.com). - Metadata size limit (bytes) — cap on the metadata a page may attach; default 8192.
- Create key.
You get two values: a publishable key dtro_pk_… for the browser, and a signing secret dtro_sk_… for your server. Keep the signing secret server-side — anyone holding it can forge metadata for your studies.
Keys are listed with their scope, allowed origins, status and creation date, and can be revoked or reactivated.
The snippet
<script async src="https://app.deutero.ai/widget/v1/deutero-widget.js"
data-publishable-key="dtro_pk_…"
data-survey-id="<survey uuid>"
data-mode="chat"
data-metadata='{"plan":"pro","participant_id":"crm-42"}'></script>
Mode is chat or voice. The page fills in your key and study id for you; Copy takes the whole thing.
The script mounts itself into a shadow root on your page, so the launcher will not show up in document.querySelector searches — if you are debugging your integration, look for the last <div> in <body> and inspect its shadowRoot.
Metadata: untrusted vs verified
One key has a meaning of its own: participant_id. Whatever it holds is also recorded as the interview's Your participant ID, the same field a link's ?participant_id= sets — so an embedded study can be joined back to your own users, and filtered by that ID in the interviews list. It stays in the metadata bag as well.
Anything in data-metadata comes from the page, so a visitor can change it in dev tools before starting. That is fine for context you only want to read next to the transcript. It is not fine when the interview acts on the value — asking enterprise-only questions, skipping a section for trial users, or splitting results by plan.
For those, your server mints a short-lived JWT signed with the key's signing secret, and the page passes it as data-signed-token instead of data-publishable-key. Deutero verifies the signature, marks those values verified, and they override any page-supplied value of the same name.
Signed Metadata has the token requirements, the metadata limits, Python and TypeScript minting examples (including the single-page-app case where the widget loads after render), and what to check when a bootstrap is rejected. The Embed page in the dashboard carries the same examples.
Seeing the metadata later
Metadata attached to an interview shows up with that interview, with page-supplied and verified values distinguished. Over the API, get_interview returns it with its provenance.
With MCP
create_embed_key {"allowed_origins": ["https://acme.com"], "study_id": "…",
"metadata_max_bytes": 8192}
list_embed_keys {}
update_embed_key {"key_id": "…", "status": "revoked"}
get_embed_snippet {"study_id": "…", "publishable_key": "dtro_pk_…", "mode": "chat"}
create_embed_key returns the signing secret once. get_embed_snippet returns both the plain and signed-token variants. list_embed_keys never returns secrets.
Last updated: September 2026