Embed Interview
Get ready-to-paste code to embed an interview directly into your product.
Returns the embed URL and copy-paste code snippets for running a Persona interview inside your own product — no redirect required. Supports iframes, JavaScript widgets, and React Native.
Embeds will not work until the domain hosting them is added to the allowlist. See Domain allowlist below.
The project must be launched before its embed URL is active. See Launch Project.
Get embed snippets
Authentication
x-api-key headerPath Parameters
| Name | Type | Description |
|---|---|---|
project_id* | string | — |
Headers
| Name | Type | Description |
|---|---|---|
x-api-key | string | — |
Responses
| Field | Type | Description |
|---|---|---|
embed_urlrequired | string | Embed Url |
interview_idrequired | string | Interview Id |
project_idrequired | string | Project Id |
snippetsrequired | object | — |
↳ iframerequired | string | — |
↳ widget_inlinerequired | string | Widget Inline |
↳ widget_overlay_centerrequired | string | Widget Overlay Center |
↳ widget_overlay_dock_rightrequired | string | Widget Overlay Dock Right |
↳ mobile_webviewrequired | string | Mobile Webview |
↳ mobile_modalrequired | string | Mobile Modal |
Example request
curl "https://external-api.prod.insightscompany.io/v1/projects/<project_id>/embed" \
-H "x-api-key: <api_key>"Example response
{
"embed_url": "https://call.insightscompany.io/embed/c3d4e5f6-0000-0000-0000-000000000002/b2c3d4e5-0000-0000-0000-000000000001",
"interview_id": "c3d4e5f6-0000-0000-0000-000000000002",
"project_id": "b2c3d4e5-0000-0000-0000-000000000001",
"snippets": {
"iframe": "<iframe src=\"...\" width=\"100%\" ...></iframe>",
"mobile_modal": "import { Modal } from 'react-native'; ...",
"mobile_webview": "import { WebView } from 'react-native-webview'; ...",
"widget_inline": "<script defer src=\"...\"></script>",
"widget_overlay_center": "<div id=\"persona-launch\">...</div>\n<script defer ...></script>",
"widget_overlay_dock_right": "<div id=\"persona-launch\">...</div>\n<script defer ...></script>"
}
}{
"embed_url": "https://call.insightscompany.io/embed/c3d4e5f6-.../b2c3d4e5-...",
"interview_id": "c3d4e5f6-...",
"project_id": "b2c3d4e5-...",
"snippets": {
"iframe": "<iframe src=\"...\" width=\"100%\" ...></iframe>",
"widget_inline": "<script defer src=\"...\"></script>",
"widget_overlay_center": "<div id=\"persona-launch\">...</div>\n<script defer ...></script>",
"widget_overlay_dock_right": "<div id=\"persona-launch\">...</div>\n<script defer ...></script>",
"mobile_webview": "import { WebView } from 'react-native-webview'; ...",
"mobile_modal": "import { Modal } from 'react-native'; ..."
}
}Response fields
| Field | Type | Description |
|---|---|---|
embed_url | string | Direct URL to the interview — use as the src in a custom embed |
interview_id | UUID | Interview associated with this project |
project_id | UUID | The project ID |
snippets.iframe | string | HTML <iframe> ready to paste into any webpage |
snippets.widget_inline | string | JavaScript widget that renders inline on the page |
snippets.widget_overlay_center | string | JavaScript widget that opens as a centred overlay — includes a launcher button |
snippets.widget_overlay_dock_right | string | JavaScript widget that opens as a right-docked overlay — includes a launcher button |
snippets.mobile_webview | string | React Native <WebView> snippet |
snippets.mobile_modal | string | React Native <Modal> wrapping a <WebView> snippet |
Domain allowlist
Each project has an allowlist of domains permitted to embed its interview. Any domain not on the list will be blocked. You can add as many domains as needed — for example https://app.example.com and https://staging.example.com can both be active at the same time.
The allowlist can also be managed from the Recruit tab in the Persona dashboard.
Get allowlist
Authentication
x-api-key headerPath Parameters
| Name | Type | Description |
|---|---|---|
project_id* | string | — |
Headers
| Name | Type | Description |
|---|---|---|
x-api-key | string | — |
Responses
| Field | Type | Description |
|---|---|---|
project_idrequired | string | Project Id |
allowed_urlsrequired | string[] | Domains currently permitted to embed this project's interview. |
curl "https://external-api.prod.insightscompany.io/v1/projects/<project_id>/embed/allow-list" \
-H "x-api-key: <api_key>"{
"project_id": "b2c3d4e5-0000-0000-0000-000000000001",
"allowed_urls": ["https://app.example.com", "https://staging.example.com"]
}An empty allowed_urls array means no domains are permitted yet — the embed will not work until at least one is added.
Update allowlist
Authentication
x-api-key headerPath Parameters
| Name | Type | Description |
|---|---|---|
project_id* | string | — |
Headers
| Name | Type | Description |
|---|---|---|
x-api-key | string | — |
Request Bodyrequired
| Field | Type | Description |
|---|---|---|
allowed_urlsrequired | string[] | Full list of domains permitted to embed this project. Replaces the existing allowlist entirely — pass an empty list to clear it. Each entry must be a full http(s) URL; only the scheme and host are kept. Valid: `https://app.example.com`. Invalid: `*.example.com`, `example.com` (no scheme), `https://localhost` (no dot). |
Responses
| Field | Type | Description |
|---|---|---|
project_idrequired | string | Project Id |
allowed_urlsrequired | string[] | Domains currently permitted to embed this project's interview. |
curl -X PUT "https://external-api.prod.insightscompany.io/v1/projects/<project_id>/embed/allow-list" \
-H "x-api-key: <api_key>" \
-H "Content-Type: application/json" \
-d '{"allowed_urls": ["https://app.example.com", "https://staging.example.com"]}'This replaces the allowlist entirely. Pass an empty array to remove all domains.
Each URL is normalised to scheme://host[:port] — paths and query strings are stripped automatically. Wildcards are not supported.
| Valid | Invalid |
|---|---|
https://app.example.com | *.example.com (wildcard) |
https://staging.example.com:3000 | example.com (no scheme) |
http://app.example.com | https://localhost (no dot in hostname) |
Returns the updated { project_id, allowed_urls }.
Embed options
iframe
The simplest option — paste directly into any HTML page:
<iframe
src="https://call.insightscompany.io/embed/<interview_id>/<project_id>"
width="100%"
style="max-width: 767px"
height="667"
allow="camera; microphone; fullscreen; display-capture; autoplay"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-presentation"
referrerpolicy="strict-origin-when-cross-origin">
</iframe>Widget (inline)
Renders the interview inline at the script's location:
<script defer
src="https://call.insightscompany.io/embed-widget/v1/persona-embed.js"
data-persona-layout="inline"
data-interview-id="<interview_id>"
data-project-id="<project_id>">
</script>Widget (overlay)
Opens the interview as an overlay triggered by a button. Two positions are available — center and dock-right:
<div id="persona-launch">
<button type="button">Start interview</button>
</div>
<script defer
src="https://call.insightscompany.io/embed-widget/v1/persona-embed.js"
data-persona-layout="overlay"
data-overlay-position="center"
data-launcher-selector="#persona-launch"
data-interview-id="<interview_id>"
data-project-id="<project_id>">
</script>Replace data-overlay-position="center" with "dock-right" to dock the overlay to the right edge of the screen.
React Native
WebView — renders the interview inline:
import { WebView } from 'react-native-webview';
<WebView
source={{ uri: "https://call.insightscompany.io/embed/<interview_id>/<project_id>" }}
style={{ flex: 1 }}
/>Modal — opens as a full-screen modal:
import { Modal } from 'react-native';
import { WebView } from 'react-native-webview';
<Modal visible={visible} animationType="slide">
<WebView
source={{ uri: "https://call.insightscompany.io/embed/<interview_id>/<project_id>" }}
style={{ flex: 1 }}
/>
</Modal>Notes
- The embed URL does not expire — you can cache it and reuse it.
- The
snippetsfield returns pre-filled code with the correct interview and project IDs already substituted. - Camera and microphone permissions are required; ensure your page or app requests them.
- As interviews complete, records appear in Interviews.