Quickstart: Embedded Flow with Inquiry Template

An Embedded Flow embeds Persona’s verification UI directly into your website as an iframe.

There are two ways to use Embedded Flow:

  1. Generate inquiries from an inquiry template (Minimal code required)
  2. Pre-create inquiries via API (More code required)

This guide walks you through the first method: generating inquiries from an inquiry template.

You will:

  • Create a web page that shows a user onboarding flow
  • Configure a button to open a Persona verification via Embedded Flow
  • Test that your flow works
  • View inquiry results via API
  • (optional) Set up and receive webhook alerts about changes to the inquiry
Alternative: Pre-create inquiries

Generating inquiries from an inquiry template (the method shown in this guide) is the fastest way to implement Embedded Flow. However, due to limitations of this method, we recommend you pre-create inquiries in production. To learn how, see Quickstart: Pre-create inquiries for Embedded Flow.

Prerequisites

You’ll need:

  • A Persona account
  • Python installed locally
    • This guide shows how to host an HTML page on localhost using Python, but you can adapt the setup to another language.

Before you start, you should:

Scenario

A user named Alexander Sample just joined your dog walking app as a dog walker. You want to verify his identity to ensure the safety of users on your service.

Alexander’s user ID in your app is “usr_ABC123”. During account signup in your app, he stated his birthdate is August 31, 1977.

Step 1: Create an inquiry template

Every inquiry is created from an inquiry template, which defines details like the specific verification logic and UI text and branding of that inquiry. You can think of inquiry templates as a mold that lets you create many inquiries.

Persona offers a suite of solutions that include preconfigured inquiry templates. In this tutorial, use the “KYC” solution to verify your dog walkers.

Follow these instructions to add the “KYC” solution to your Sandbox environment.

Step 2: Locate the inquiry template ID

Find the ID of the newly-created inquiry template.

In the Persona dashboard, navigate to Inquiries > Templates. Find the “KYC” template in the list of inquiry templates, and note the value in the ID field. The value should begin with itmpl_.

Step 3: Create the web page

Now, set up the user onboarding page that will display the verification flow to Alexander.

  1. Create a new directory called embedded-flow-demo/.

  2. Inside that directory, create a file called onboarding.html with the following code:

embedded-flow-demo/onboarding.html
1<!DOCTYPE html>
2<html>
3<head>
4 <title>Complete Your Profile - Dog Walker</title>
5 <style>
6 body {
7 font-family: Arial, sans-serif;
8 max-width: 600px;
9 margin: 50px auto;
10 padding: 20px;
11 text-align: center;
12 }
13 .container {
14 border: 1px solid #ddd;
15 border-radius: 8px;
16 padding: 40px;
17 background-color: #f9f9f9;
18 }
19 h1 {
20 color: #333;
21 margin-bottom: 10px;
22 }
23 p {
24 color: #666;
25 line-height: 1.6;
26 margin-bottom: 30px;
27 }
28 button {
29 background-color: #0066cc;
30 color: white;
31 border: none;
32 padding: 15px 40px;
33 font-size: 16px;
34 border-radius: 5px;
35 cursor: pointer;
36 }
37 button:hover {
38 background-color: #0052a3;
39 }
40 .user-info {
41 background-color: #fff;
42 border: 1px solid #ddd;
43 border-radius: 4px;
44 padding: 15px;
45 margin-bottom: 30px;
46 text-align: left;
47 }
48 .user-info h3 {
49 margin-top: 0;
50 color: #333;
51 }
52 .user-info p {
53 margin: 8px 0;
54 }
55 </style>
56</head>
57<body>
58 <div class="container">
59 <h1>Welcome, Alexander 🐕</h1>
60 <p>
61 Before you can start walking dogs, we need to verify your identity.
62 This helps ensure the safety of pet owners and walkers like you.
63 </p>
64
65 <div class="user-info">
66 <h3>Your Information</h3>
67 <p><strong>Name:</strong> Alexander Sample</p>
68 <p><strong>Birthdate:</strong> August 31, 1977</p>
69 </div>
70
71 <button id="verify-button">Start Verifying</button>
72 </div>
73 <div>
74 <p>Debug info:</p>
75 <p id="debug-info"></p>
76 </div>
77
78 <script>
79 // Button doesn't work yet - we'll add Persona integration next.
80 document.getElementById('verify-button').addEventListener('click', () => {
81 alert('Verification flow will go here');
82 });
83 </script>
84</body>
85</html>
  1. Start a local Python server to host this file:

    $# cd to the directory
    >cd embedded-flow-demo/
    >
    ># start a local server
    >python -m http.server 8000
  2. Load localhost:8000/onboarding.html in a browser to view the page.

You should see the onboarding flow for our newly-registered dog walker:

dog walker onboarding page

Right now, the “Start Verifying” button doesn’t work. You’ll wire it up in Step 5.

Step 4: Add the Persona Web SDK

The web page code does not yet contain the Persona SDK. Let’s add it.

  1. In the <head> section of onboarding.html, add the following lines right after the closing </style> tag:
embedded-flow-demo/onboarding.html
1<script src="https://cdn.withpersona.com/dist/persona-vX.Y.Z.js" crossorigin="anonymous"></script>
2<meta charset="UTF-8" />
3<meta name="viewport" content="width=device-width, initial-scale=1" />
  1. In the code you added, replace X.Y.Z. in the CDN URL with the latest version of the SDK. Check the SDK changelog for the latest version.
    • For example, if the latest version is 5.4.0: https://cdn.withpersona.com/dist/persona-v5.4.0.js
Alternative: npm

You can also install the SDK as an npm package.

Step 5: Make the button open the Persona flow

Right now, if you click “Start Verifying”, you see an alert. Make the button trigger a Persona verification flow instead.

  1. Locate the following lines in the HTML:
embedded-flow-demo/onboarding.html
1<script>
2// Button doesn't work yet - we'll add Persona integration next.
3document.getElementById('verify-button').addEventListener('click', () => {
4 alert('Verification flow will go here');
5});
6</script>
  1. Replace those lines with the following code:
embedded-flow-demo/onboarding.html
1<script>
2// In this demo, we hardcode Alexander's user information.
3// In a real implementation, this information should come from your internal systems.
4let userId = 'usr_ABC123';
5let userFields = {
6 name_first: "Alexander",
7 name_last: "Sample",
8 birthdate: "1977-08-31",
9}
10
11document.getElementById('verify-button').addEventListener('click', () => {
12 const client = new Persona.Client({
13 templateId: "itmpl_XXXXXXXXXXXXX",
14 environmentId: "env_XXXXXXXXXXXXX",
15 referenceId: userId,
16 fields: userFields,
17 onReady: () => client.open(),
18 onCancel: ({ inquiryId, sessionToken }) => {
19 // For demonstration purposes, we will just log to the console.
20 console.log(`An inquiry was cancelled. ID: ${inquiryId}`);
21 },
22 onError: (error) => {
23 // For demonstration purposes, we will just log to the console.
24 console.log('An error occurred:', error)
25 },
26 onEvent: (name, metadata) => {
27 if (name === 'start') {
28 // For demonstration purposes, we will just log to the console.
29 const inquiryId = metadata.inquiryId;
30 console.log(`Starting inquiry with ID: ${inquiryId}`);
31 }
32 },
33 onComplete: ({ inquiryId, status, fields }) => {
34 // Inquiry completed. For demonstration purposes, we will show a debug message in the UI.
35 document.getElementById('debug-info').innerText = `Completed inquiry with ID: ${inquiryId} \n\nWrite down this ID for Step 9.`;
36
37 // Here, you could also send a request to your backend to log the completion.
38
39 // Clean up the client to avoid memory leaks.
40 client.destroy();
41 },
42 });
43});
44</script>
  1. In the code, fill in the following values:
    • templateId: Replace itmpl_XXXXXXXXXXXXX with your inquiry template ID from Step 2.
    • environmentId: Replace env_XXXXXXXXXXXXX with the ID of the Persona environment you’re using. In this tutorial, we’re using your Sandbox environment. Here’s how to find the ID of your environment.

About the code

This code creates a new Persona web client (new Persona.Client({...})). Note that:

  • A new inquiry is created when new Persona.Client({...}) is invoked.
  • You must provide a templateId at minimum. If you don’t provide an environment ID, by default your production environment is used.
  • Callbacks, like onComplete and onError, let you coordinate your app’s UI with changes in the Persona UI. Do not rely on them for up-to-date data about the state of the inquiry. Use webhooks (Step 6) for logic that depends on inquiry state.

This code demonstrates two best practices for initiating inquiries:

  • Pass a reference ID: “usr_ABC123” is set as the reference-id. A reference ID lets you tag an inquiry as being associated with a particular end user. Persona recommends using the user’s UID from your internal systems.
  • Prefill inquiry fields: We prefill the inquiry with information we know about Alexander: his first name, last name, and birthdate. Providing this information helps streamline the verification experience for Alexander, and helps increase your confidence that his information is valid.

Step 6: Set up a webhook (optional)

You can receive notifications when any inquiry’s state changes. For example, you can be alerted when any inquiry is started by a user, or when any inquiry is completed. See the full list of inquiry events you can be alerted about.

To receive automatic notifications:

  1. Create a webhook endpoint (for a sample server, see Webhook quickstart)
  2. In the dashboard, navigate to Webhooks > Webhooks.
  3. Add your endpoint URL
  4. Select the following “Enabled events”: inquiry.started, inquiry.completed, inquiry.approved, inquiry.declined, and inquiry.failed

For this tutorial, you can skip webhooks and view results in the dashboard.

Step 7: Test the flow

In production, Alexander would click the “Start Verifying” button and complete verification on his own.

For this tutorial, you’ll complete the flow yourself as Alexander:

  1. Click “Start Verifying”. The Persona verification flow will open in a modal.
  2. Click through the verification steps.
    • Do not enter real personal information, since this is Sandbox.
    • Keep the “Pass verifications” toggle enabled (visible at the bottom of the flow) to simulate passing all the checks.
  3. After you complete the flow, note the inquiry ID printed to the “Debug info” section of the page. You’ll use it in Step 9.

The inquiry ID will look like inq_XXXXXXXXXXXXX.

Step 8: (optional) Inspect webhook events

If you set up the webhook in Step 6, check your server logs. You should see events from inquiry.started, inquiry.completed, and inquiry.approved.

Note: If you want to receive the inquiry.failed event, you can reload the page and click “Start Verifying” again. Then click through the verification flow, this time with the “Pass verifications” toggle disabled.

Step 9: View inquiry results via API

Now that you’ve completed the inquiry, take a look at the results. Note that because this inquiry was created in Sandbox, some of the data will be demo data.

Retrieve the inquiry details:

$curl https://api.withpersona.com/inquiries/inq_XXXXXXXXXXXXX \
>-X GET \
>-H "Authorization: Bearer YOUR_API_KEY" \
>-H "Content-Type: application/json" \
>-H "Persona-Version: 2025-10-27"
>
># Replace:
># - YOUR_API_KEY with your API key
># - inq_XXXXXXXXXXXXX with the inquiry ID from Step 7

The response includes:

  • data.attributes.reference-id: The reference ID you provided
  • data.attributes.status: Should be approved
  • data.attributes.fields: Prefilled and collected data

Note that:

  • The final status of your inquiry is approved instead of completed because the KYC solution includes Workflows that automatically approve passing inquiries. See the Next Steps section to learn more.
  • Because this inquiry was created in Sandbox, much of the data will be null or empty. Keep in mind you’ll see different outputs in Production.

Alternative: View in Dashboard You can also view results in the dashboard at Inquiries > All Inquiries. See this Help Center guide for details.

Summary

In this tutorial, you:

  • Created a web page that shows a step in a user onboarding flow
  • Added the Persona Web SDK
  • Configured a button click to open a Persona verification in a modal (Embedded Flow)
  • Tested the complete flow
  • (Optional) Received alerts about changes to the inquiry, via webhook
  • Retrieved inquiry results via API

This is a complete Embedded Flow integration that creates inquiries using an inquiry template.

Limitations of this approach

This implementation is simple, but has drawbacks:

  • Users may create duplicate inquiries: Each time a user clicks “Start Verifying”, a new inquiry is created. If they click multiple times, they will create multiple inquiries, which create noise in your data.
  • Users can’t resume inquiries: If a user reloads the page mid-flow, they must start over with a new inquiry.
  • Users can spoof information: Since the client is providing the user information (user ID and user fields), this information could be spoofed by the user.

To address these issues, Persona recommends you pre-create inquiries on your server in production. See Quickstart: Pre-create inquiries for Embedded Flow to learn how.

Next steps

Enhance this integration:

  • Pre-create inquiries: Complete the next quickstart to learn how Persona recommends you deploy Embedded Flow in production.
  • Subscribe to additional events: Understand the different inquiry events you can be alerted about, and the difference between the “Done” and “Post-inquiry” phases.
  • Learn webhook best practices: In production, you’ll need to handle duplicate events and other issues.

Explore further:

  • Explore the KYC solution: The KYC solution includes two Workflows and a Case template. In this tutorial, the Workflows seamlessly ran in the background and changed the final status of your inquiry from completed to approved.
  • Explore other integration methods: Try Hosted Flow if you’re looking to distribute verification flows as links. See Choosing an integration method.