DocumentationAPI Reference
API ChangelogOpenAPI SpecStatus

Prevent users from creating multiple Inquiries

Some Persona inquiry templates are only meant to be finished once per user. For example, you might have an onboarding template where, if the user passes verification, they gain access to your site. If they fail, they should be denied access.

You will want to prevent your users from creating multiple inquiries on these templates for the following reasons:

  • Fraud vector: Allowing a user to create multiple inquiries on the same template can effectively give them unlimited attempts to try and pass Persona’s verifications
  • Increased user friction: your users may be confused why they’re being asked to verify their identity multiple times

Best practice for preventing multiple inquiries per user

1. Create inquiries via API

Creating inquiries via API restricts end users from arbitrarily creating inquiries. See Creating Inquiries via API for more information.

2. Assign each user a Reference ID upon inquiry creation

A Reference ID is a string unique to every user that is used to identify a their Persona account in a way that makes sense to your business. Persona recommends using the same user ID that represents the user in your internal system.

Inquiries created with the same Reference ID will all get associated with the same account, which is how you can tell if a user has already gone through the Persona flow.

3. Before loading the Persona widget, check to see if the user has already gone through Persona Verification

👍

Ideally, you will have saved the user's verification status in your internal systems and can route the user accordingly without querying Persona for previous inquiries.

If you don't have this implemented, please read on.

You will want to check if there are existing inquiries with your user's Reference ID

  1. Make a call to List all Inquiries and filter on the account’s Reference ID.
  2. Filter the inquiries returned on the specific template you’re checking for.
import requests

reference_id = "your reference ID here"
inquiry_template_id = "your inquiry template ID here"
api_key = "your API key here"

url = f"https://withpersona.com/api/v1/inquiries?filter[reference-id]={reference_id}"

headers = {
    "accept": "application/json",
    "Persona-Version": "<api version>",
    "Authorization": f"Bearer {api_key}"
}

response = requests.get(url, headers=headers)
inquiries = response.json()["data"]

# Filter for your specific inquiry template
template_property = "template" if inquiry_template_id.startswith("tmpl_") else "inquiry-template"
relevant_inquiries = list(
    filter(lambda inquiry: inquiry["relationships"][template_property]["data"]["id"] == inquiry_template_id, inquiries))

4. Decide how to proceed based on the user’s existing inquiries

if len(relevant_inquiries) == 0:
    createNewInquiry()

else:
    # If you have multiple created inquiries under this template, 
		# you may want to look at all of their statuses and decide how to proceed
    existing_inquiry = relevant_inquiries[0]
    existing_inquiry_status = existing_inquiry["attributes"]["status"]

    handleExistingInquiry(existing_inquiry_status)
  1. If there is an existing inquiry that has already successfully finished (where the status is completed or approved), there may be no need to create a new inquiry and you can let the user onto your system.

    1. :construction: The "correct status to search for will depend on your Persona setup as well as your usage of Persona workflows. Refer to Inquiry Model Lifecycle for an explanation of Inquiry statuses.
  2. If there is an existing inquiry that has unsuccessfully finished (where the status is failed, declined, or marked-for-review), you may want to actively prevent the user from creating a new inquiry, as they have previously failed Persona verification.

  3. If there is an existing inquiry with a status of expired, you can
    i. Resume this inquiry
    ii. Create a new inquiry with the same Reference ID

We recommend you first check to see if the existing inquiry's template version (a string beginning with itmplv_) is the same as the inquiry template's current version, to ensure the inquiry your user is going through has the most up-to-date configuration. You should resume the inquiry if the two versions match (which will allow the user to pick up where they left off), and create a new inquiry if the versions do not match.

existing_inquiry_template_version = existing_inquiry["data"]["relationships"]["inquiry-template-version"]["data"]["id"]
template_object = list(filter(lambda x: x["type"] == "inquiry-template", existing_inquiry["included"]))[0]
current_template_version = template_object["relationships"]["latest-published-version"]["data"]["id"]

if existing_inquiry_template_version == current_template_version:
    resume_inquiry()
    
else:
    create_new_inquiry()

5. Save the user’s inquiry status into your internal system

To avoid having to look up a user’s inquiries in this fashion every time they access your site, you can save their inquiry status in your system and query that status when necessary.