Skip to content

Facts: how to verify things about a person

A fact is a yes or no that Prson signs about a person: "over 18", "an EU citizen", "lives in Lisbon", "has a work email". The person shares only the answer, never the data behind it. This page shows how to ask for each kind, what a yes proves and what it doesn't.

Want the code for your own request? Build your request picks the facts and writes it for you. Explaining it to someone who isn't a developer? How to verify anything about someone on app.prson.net has a plain-language guide for each kind. The full list, with prices: What you can ask for.

What a fact is

  • Prson works out the answer from something it verified: the chip of a passport, ID card or residence permit, a code sent by email or SMS, a letter posted to an address, or a DNS record.
  • The person sees who is asking and why, and decides whether to answer. If they do, you get yes or no, signed by Prson. They can also decline.
  • When Prson can't tell (for example a birth year without a date, right at the age you ask), it gives no answer rather than guess, and the person can't fulfil that requirement. Mark a requirement optional if a missing answer shouldn't hold up the rest.
  • A fact is only as good as the verification behind it: each section below says what that is, and what it doesn't prove.

How to ask

Every fact is one requirement, { "type": "fact", "fact": "<id>" }, in a verification. Over REST, send it to POST /v1/verifications (see Verifications API). An AI agent calls the create_verification tool on the MCP server https://api.prson.net/mcp/verify with the same title and requirements (see MCP for AI agents). Either way you get a share_url to send to the person yourself.

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you are over 18 to open an account",
  "requirements": [
    { "type": "fact", "fact": "age_gte_18" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you are over 18 to open an account",
      "requirements": [
        { "type": "fact", "fact": "age_gte_18" }
      ]
    }
  }
}

Up to 10 requirements fit in one verification, so you can ask for several facts at once.

The answer

Each answer comes back in the verification's responses (and in the verification.* webhooks): fact.value is the yes or no. Prson vouches for it until fact.expires_at: an hour unless asked otherwise, never more than 180 days, and never past the verification it rests on. verdict_signature lets you check Prson signed it.

response.json
GET /v1/verifications/{id}

{
  "id": "…",
  "status": "fulfilled",
  "responses": [
    {
      "respondent_id": "rsp_…",
      "type": "fact",
      "status": "verified",
      "fact": {
        "id": "age_gte_18",
        "value": true,
        "description": "Person is at least 18 years old",
        "expires_at": "…"
      },
      "verdict_signature": "…"
    }
  ]
}

Availability

  • Available Age, verification level, nationality, document, residence permit, email and website facts.
  • Where enabled Phone and address facts work only where Prson can verify them: capabilities.phone_verification and capabilities.address_verification in GET https://api.prson.net/v1/verifications/requirements (public). Otherwise the API answers 422 requirement_unavailable. Countries: Coverage by country.
  • Not available yet Bank balance, income and bank account facts, and academic email addresses: asking for them is refused.

All facts

Every fact the API knows, by family: 46 in all. Each says what a yes proves, what it doesn't, where it comes from and whether you can ask for it now. To put a request together and get its code, use Build your request.

Age

How old the person is, from the date of birth on their passport or ID card chip. You learn only yes or no, never the date.

How to verify it, in plain words on app.prson.net.

At least a given age

Available

age_gte_{age}

The person is at least this many years old.

Example
age_gte_18 (18 or older)
From
The date of birth on their passport or ID card chip
Limits
Worked out from the chip's date of birth at the moment Prson signs the answer. If only a birth year is known and the person could be on either side of the age, Prson gives no answer rather than guess, so the request can't be fulfilled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

At most a given age

Available

age_lte_{age}

The person is at most this many years old (age_lte_17 is under 18).

Example
age_lte_17 (17 or younger)
From
The date of birth on their passport or ID card chip
Limits
Worked out from the chip's date of birth at the moment Prson signs the answer. If only a birth year is known and the person could be on either side of the age, Prson gives no answer rather than guess, so the request can't be fulfilled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Between two ages

Available

age_between_{from}_{to}

The person is between these two ages, both included.

Example
age_between_18_30 (Between 18 and 30 years old)
From
The date of birth on their passport or ID card chip
Limits
Worked out from the chip's date of birth at the moment Prson signs the answer. If only a birth year is known and the person could be on either side of the age, Prson gives no answer rather than guess, so the request can't be fulfilled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it
  • age_gte_18 is over 18, age_gte_21 over 21, age_lte_17 under 18. Any age from 0 to 130 works, and age_between_{from}_{to} for a range.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you are over 21 to order wine",
  "requirements": [
    { "type": "fact", "fact": "age_gte_21" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you are over 21 to order wine",
      "requirements": [
        { "type": "fact", "fact": "age_gte_21" }
      ]
    }
  }
}

Document

The identity document whose chip they verified in Prson: its kind, the country that issued it and how long it is valid.

How to verify it, in plain words on app.prson.net.

Identity document not expired

Available

doc_not_expired

Document is not expired.

Example
doc_not_expired (Identity document not expired)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity document valid for some months more

Available

doc_expires_after_{months}m

The document expires more than this many months from now.

Example
doc_expires_after_6m (Identity document valid for more than 6 months)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Kind of identity document

Available

document_type_eq_{type}

The document they verified is a passport, a national ID card or a residence permit.

Example
document_type_eq_passport (Identity document is a passport)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity document from a country

Available

issuing_country_eq_{country}

The document was issued by this country.

Example
issuing_country_eq_PRT (Identity document issued by Portugal)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity document from an EU country

Available

issuing_country_in_eu

Document was issued by an EU country.

Example
issuing_country_in_eu (Identity document issued by an EU country)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity document from an EU or EEA country

Available

issuing_country_in_eea

Document was issued by an EU or EEA country.

Example
issuing_country_in_eea (Identity document issued by an EU or EEA country)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity document from a Schengen country

Available

issuing_country_in_schengen

Document was issued by a Schengen country.

Example
issuing_country_in_schengen (Identity document issued by a Schengen country)
From
Their passport or ID card chip, checked by Prson
Limits
Read from the chip of the document they verified in Prson (level 5 or 6). The expiry is the date on the chip: it doesn't say whether the document was since reported lost, stolen or cancelled.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it
  • These facts can also go in a selfie or document capture's required_facts, checked by Prson when the person answers.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm your passport is valid for 6 more months",
  "requirements": [
    { "type": "fact", "fact": "document_type_eq_passport" },
    { "type": "fact", "fact": "doc_expires_after_6m" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm your passport is valid for 6 more months",
      "requirements": [
        { "type": "fact", "fact": "document_type_eq_passport" },
        { "type": "fact", "fact": "doc_expires_after_6m" }
      ]
    }
  }
}

Nationality

Their nationality as written in the document whose chip they verified: one country, or the EU, the EEA or the Schengen Area.

How to verify it, in plain words on app.prson.net.

Citizen of a country

Available

nationality_eq_{country}

Their nationality is this country.

Example
nationality_eq_DEU (Citizen of Germany)
From
Their passport or ID card chip, checked by Prson
Limits
The nationality written in the document whose chip they verified in Prson (level 5 or 6). A person with two nationalities is matched on the one in that document: a no doesn't mean they hold no other.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

EU citizen

Available

nationality_in_eu

Holder is an EU citizen.

Example
nationality_in_eu (EU citizen)
From
Their passport or ID card chip, checked by Prson
Limits
The nationality written in the document whose chip they verified in Prson (level 5 or 6). A person with two nationalities is matched on the one in that document: a no doesn't mean they hold no other.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Citizen of an EU or EEA country

Available

nationality_in_eea

Holder is an EEA citizen.

Example
nationality_in_eea (Citizen of an EU or EEA country)
From
Their passport or ID card chip, checked by Prson
Limits
The nationality written in the document whose chip they verified in Prson (level 5 or 6). A person with two nationalities is matched on the one in that document: a no doesn't mean they hold no other.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Citizen of a Schengen country

Available

nationality_in_schengen

Holder is a citizen of a Schengen country.

Example
nationality_in_schengen (Citizen of a Schengen country)
From
Their passport or ID card chip, checked by Prson
Limits
The nationality written in the document whose chip they verified in Prson (level 5 or 6). A person with two nationalities is matched on the one in that document: a no doesn't mean they hold no other.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it
  • Countries use ISO 3166-1 alpha-3 codes in upper case: nationality_eq_PRT, nationality_eq_DEU, nationality_eq_USA.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you are an EU citizen to apply",
  "requirements": [
    { "type": "fact", "fact": "nationality_in_eu" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you are an EU citizen to apply",
      "requirements": [
        { "type": "fact", "fact": "nationality_in_eu" }
      ]
    }
  }
}

Where they live

Where their postal address is (country, region, city or postcode), proved with a code in a letter posted to it.

How to verify it, in plain words on app.prson.net.

Has a verified postal address

Where enabled

address_verified

Postal address is verified.

Example
address_verified (Postal address verified)
From
A code in a letter posted to their address
Limits
A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in a country

Where enabled

address_country_eq_{country}

Their verified postal address is in this country.

Example
address_country_eq_PT (Postal address in Portugal)
From
A code in a letter posted to their address
Limits
Any country where the letter can be delivered: see Coverage by country. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in an EU country

Where enabled

address_country_in_eu

Postal address is in the EU.

Example
address_country_in_eu (Postal address in an EU country)
From
A code in a letter posted to their address
Limits
Any country where the letter can be delivered: see Coverage by country. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in an EU or EEA country

Where enabled

address_country_in_eea

Postal address is in the EEA.

Example
address_country_in_eea (Postal address in an EU or EEA country)
From
A code in a letter posted to their address
Limits
Any country where the letter can be delivered: see Coverage by country. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in a Schengen country

Where enabled

address_country_in_schengen

Postal address is in the Schengen Area.

Example
address_country_in_schengen (Postal address in a Schengen country)
From
A code in a letter posted to their address
Limits
Any country where the letter can be delivered: see Coverage by country. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in a region, state or province

Where enabled

address_region_eq_{country}_{region}

Their verified postal address is in this region of this country.

Example
address_region_eq_US_california (Postal address in California, United States)
From
A code in a letter posted to their address
Limits
The region is written lower case, accents removed, words joined by hyphens ("São Paulo" becomes sao-paulo), and compared with what the person wrote on their address, so local spellings matter: lisboa, not lisbon. No answer if their address has no region; an address in another country is a no. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in a city

Where enabled

address_city_eq_{country}_{city}

Their verified postal address is in this city of this country.

Example
address_city_eq_PT_lisboa (Postal address in Lisboa, Portugal)
From
A code in a letter posted to their address
Limits
The city is written lower case, accents removed, words joined by hyphens ("São Paulo" becomes sao-paulo), and compared with what the person wrote on their address, so local spellings matter: lisboa, not lisbon. No answer if their address has no city; an address in another country is a no. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Lives in a postcode area

Where enabled

address_postcode_prefix_{country}_{prefix}

Their verified postal address has a postcode starting with these letters and digits.

Example
address_postcode_prefix_PT_1000 (Postal address in Portugal, postcode starting 1000)
From
A code in a letter posted to their address
Limits
Compares letters and digits only, in upper case: spaces and dashes are removed from their postcode (1000-001 becomes 1000001), so write the prefix the same way. An address in another country is a no. A letter with a one-time code was posted to the address (by Pingen) and the person typed the code in the app. It proves a letter reached them there on the day they verified, not that they live there now, own it, or are the only person there. An address verification lasts 365 days.
Price
Included in the base price
Links
Guide · Reference · Build a request with it
  • Countries use ISO 3166-1 alpha-2 codes in upper case (PT, US). Regions and cities are written lower case without accents, words joined by hyphens: address_region_eq_US_new-york, address_city_eq_BR_sao-paulo.
  • Use the local spelling people write on their address (lisboa, munchen, not lisbon or munich). When unsure, a postcode prefix or the country is more reliable.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you live in Lisbon to join the residents' offer",
  "requirements": [
    { "type": "fact", "fact": "address_city_eq_PT_lisboa" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you live in Lisbon to join the residents' offer",
      "requirements": [
        { "type": "fact", "fact": "address_city_eq_PT_lisboa" }
      ]
    }
  }
}

Residence permit

A residence permit read from its chip, and which country issued it.

How to verify it, in plain words on app.prson.net.

Residence permit from a country

Available

residence_permit_from_{country}

They verified a residence permit issued by this country.

Example
residence_permit_from_PRT (Residence permit from Portugal)
From
The chip of a residence permit they verified in Prson, checked by Prson
Limits
Needs a residence permit whose chip the person verified in Prson (document type residence_permit); it says which country issued it. It doesn't say what the permit allows (work, study, family) or whether it was revoked; add doc_not_expired to know it hasn't expired. Someone who verified a passport or ID card instead answers no: that isn't evidence they have no permit.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Residence permit from an EU country

Available

residence_permit_in_eu

Holds a residence permit issued by an EU country.

Example
residence_permit_in_eu (Residence permit from an EU country)
From
The chip of a residence permit they verified in Prson, checked by Prson
Limits
Needs a residence permit whose chip the person verified in Prson (document type residence_permit); it says which country issued it. It doesn't say what the permit allows (work, study, family) or whether it was revoked; add doc_not_expired to know it hasn't expired. Someone who verified a passport or ID card instead answers no: that isn't evidence they have no permit.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Residence permit from an EU or EEA country

Available

residence_permit_in_eea

Holds a residence permit issued by an EU or EEA country.

Example
residence_permit_in_eea (Residence permit from an EU or EEA country)
From
The chip of a residence permit they verified in Prson, checked by Prson
Limits
Needs a residence permit whose chip the person verified in Prson (document type residence_permit); it says which country issued it. It doesn't say what the permit allows (work, study, family) or whether it was revoked; add doc_not_expired to know it hasn't expired. Someone who verified a passport or ID card instead answers no: that isn't evidence they have no permit.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Residence permit from a Schengen country

Available

residence_permit_in_schengen

Holds a residence permit issued by a Schengen country.

Example
residence_permit_in_schengen (Residence permit from a Schengen country)
From
The chip of a residence permit they verified in Prson, checked by Prson
Limits
Needs a residence permit whose chip the person verified in Prson (document type residence_permit); it says which country issued it. It doesn't say what the permit allows (work, study, family) or whether it was revoked; add doc_not_expired to know it hasn't expired. Someone who verified a passport or ID card instead answers no: that isn't evidence they have no permit.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it
  • Add doc_not_expired (or doc_expires_after_{months}m) to know the permit is still valid: the residence permit facts alone only say who issued it.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you hold a Portuguese residence permit that hasn't expired",
  "requirements": [
    { "type": "fact", "fact": "residence_permit_from_PRT" },
    { "type": "fact", "fact": "doc_not_expired" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you hold a Portuguese residence permit that hasn't expired",
      "requirements": [
        { "type": "fact", "fact": "residence_permit_from_PRT" },
        { "type": "fact", "fact": "doc_not_expired" }
      ]
    }
  }
}

Phone

A phone number they proved with an SMS code: that it is verified, a mobile, or from a country.

How to verify it, in plain words on app.prson.net.

Has a verified phone number

Where enabled

phone_verified

Phone number is verified.

Example
phone_verified (Phone number verified)
From
A code sent by SMS to their phone
Limits
They signed in with a code sent by SMS to that number, so they could receive its texts when they verified. A phone verification lasts 365 days. It doesn't say whose name the line is in.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Phone number is a mobile

Where enabled

phone_is_mobile

Phone number is a mobile number.

Example
phone_is_mobile (Phone number is a mobile)
From
A code sent by SMS to their phone
Limits
The line type comes from the international numbering plan, not a live lookup with the carrier: a number moved to another network keeps its original range's type. Where the plan doesn't separate mobiles from landlines (the US, Canada and a few others) Prson gives no answer, so the request can't be fulfilled with a yes or no there. Internet (VoIP) numbers are a no. They signed in with a code sent by SMS to that number, so they could receive its texts when they verified. A phone verification lasts 365 days. It doesn't say whose name the line is in.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Phone number from a country

Where enabled

phone_country_eq_{country}

Their verified phone number belongs to this country's numbering plan.

Example
phone_country_eq_PT (Phone number from Portugal)
From
A code sent by SMS to their phone
Limits
The country comes from the number itself (the international numbering plan), not a live lookup with the carrier: it says nothing about where the person is. They signed in with a code sent by SMS to that number, so they could receive its texts when they verified. A phone verification lasts 365 days. It doesn't say whose name the line is in.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Phone number from an EU country

Where enabled

phone_country_in_eu

Phone number is from an EU country.

Example
phone_country_in_eu (Phone number from an EU country)
From
A code sent by SMS to their phone
Limits
The country comes from the number itself (the international numbering plan), not a live lookup with the carrier: it says nothing about where the person is. They signed in with a code sent by SMS to that number, so they could receive its texts when they verified. A phone verification lasts 365 days. It doesn't say whose name the line is in.
Price
Included in the base price
Links
Guide · Reference · Build a request with it
  • phone_is_mobile can't be answered for US and Canadian numbers (their numbering plan doesn't separate mobiles from landlines): don't ask it of people there.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you have a Portuguese mobile number",
  "requirements": [
    { "type": "fact", "fact": "phone_is_mobile" },
    { "type": "fact", "fact": "phone_country_eq_PT" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you have a Portuguese mobile number",
      "requirements": [
        { "type": "fact", "fact": "phone_is_mobile" },
        { "type": "fact", "fact": "phone_country_eq_PT" }
      ]
    }
  }
}

Email

An email address they proved with a code: that it is verified, a work address, at a given domain, or not a throwaway one.

How to verify it, in plain words on app.prson.net.

Has a verified email address

Available

email_verified

Email address is verified.

Example
email_verified (Email address verified)
From
A code sent to their email address
Limits
They typed a code sent to that address, so they could read that inbox when they verified. An email verification lasts 180 days. It doesn't say who owns or runs the address.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Work email address

Available

email_work

Email address is at an organisation's own domain, not a free or throwaway provider.

Example
email_work (Work email address (not a free or throwaway provider))
From
A code sent to their email address
Limits
Yes means the domain isn't on Prson's list of free or throwaway providers (gmail.com, outlook.com, yahoo, gmx and others; mailinator.com and others). It doesn't prove an employer or a job title, or that a company runs the domain: a personal domain counts. To ask about one organisation, use email_domain_eq_{domain}. They typed a code sent to that address, so they could read that inbox when they verified. An email verification lasts 180 days. It doesn't say who owns or runs the address.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Email address at a domain

Available

email_domain_eq_{domain}

Their verified email address is at exactly this domain.

Example
email_domain_eq_example.com (Email address at example.com)
From
A code sent to their email address
Limits
The domain must match exactly: mail.example.com and example.com are different. They could read an inbox at that domain when they verified; it doesn't prove they still work or study there, or their role. They typed a code sent to that address, so they could read that inbox when they verified. An email verification lasts 180 days. It doesn't say who owns or runs the address.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

Email address isn't a throwaway one

Available

email_not_disposable

Email address is not at a throwaway provider.

Example
email_not_disposable (Email address is not a throwaway one)
From
A code sent to their email address
Limits
Yes means the domain isn't on a short list of throwaway inbox services. The list isn't complete: a rare throwaway service can still pass. They typed a code sent to that address, so they could read that inbox when they verified. An email verification lasts 180 days. It doesn't say who owns or runs the address.
Price
Included in the base price
Links
Guide · Reference · Build a request with it

School or university email address

Coming soon

email_domain_academic

Email address is at a university or school.

Example
email_domain_academic (School or university email address)
From
A list of academic domains (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Included in the base price
Links
Guide · Reference
  • email_work only says the address isn't at a free or throwaway provider. To know someone has an address at one company or school, ask email_domain_eq_{domain} with its domain.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you have an example.com email address",
  "requirements": [
    { "type": "fact", "fact": "email_domain_eq_example.com" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you have an example.com email address",
      "requirements": [
        { "type": "fact", "fact": "email_domain_eq_example.com" }
      ]
    }
  }
}

Website

A website's domain they proved they control with a DNS record.

How to verify it, in plain words on app.prson.net.

Controls a website

Available

website_domain_eq_{domain}

They proved control of this domain's DNS.

Example
website_domain_eq_example.com (Controls the website example.com)
From
A DNS record they added to the domain, checked by Prson
Limits
They added a DNS TXT record at _prson-challenge.{domain} that Prson looked up, so they controlled the domain's DNS at that time. It lasts up to 365 days, never past the domain's registration expiry. It doesn't prove who legally owns the domain or the company behind it. The domain must match exactly: www.example.com and example.com are different.
Price
Included in the base price
Links
Guide · Reference · Build a request with it
  • The person proves it in the Prson app by adding a TXT record at _prson-challenge.{domain} in the domain's DNS.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you control example.com",
  "requirements": [
    { "type": "fact", "fact": "website_domain_eq_example.com" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you control example.com",
      "requirements": [
        { "type": "fact", "fact": "website_domain_eq_example.com" }
      ]
    }
  }
}

Identity level

How far their identity was checked. Level 5 or more is what Prson calls a verified human: a passport or ID card chip checked by Prson.

How to verify it, in plain words on app.prson.net.

Verified human

Available

verification_level_gte_5

Prson checked the chip of their passport or ID card (level 5 or more).

Example
verification_level_gte_5 (Verified human (identity level 5 or higher))
From
Their verification level in Prson (5 and 6: chip checked by Prson)
Limits
Says how far the identity was checked, not who the person is: no name or document detail is shared. Levels 5 and 6 (a passport or ID card chip checked by Prson) are what Prson calls a verified human; 6 adds a face match between a live selfie and the chip photo. Levels 1 to 4 are checks done on the phone and are never called verified human.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Verified human, with a face match

Available

verification_level_gte_6

Level 6: chip checked by Prson, plus a face match between a live selfie and the chip photo.

Example
verification_level_gte_6 (Verified human (identity level 6 or higher))
From
Their verification level in Prson (5 and 6: chip checked by Prson)
Limits
Says how far the identity was checked, not who the person is: no name or document detail is shared. Levels 5 and 6 (a passport or ID card chip checked by Prson) are what Prson calls a verified human; 6 adds a face match between a live selfie and the chip photo. Levels 1 to 4 are checks done on the phone and are never called verified human.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity level 4 or more

Available

verification_level_gte_4

At least a photo of an identity document, checked on the phone (never called a verified human).

Example
verification_level_gte_4 (Identity verified to level 4 or higher)
From
Their verification level in Prson (5 and 6: chip checked by Prson)
Limits
Says how far the identity was checked, not who the person is: no name or document detail is shared. Levels 5 and 6 (a passport or ID card chip checked by Prson) are what Prson calls a verified human; 6 adds a face match between a live selfie and the chip photo. Levels 1 to 4 are checks done on the phone and are never called verified human.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it

Identity level 3 or more

Available

verification_level_gte_3

At least a live selfie and Face ID on their phone (never called a verified human).

Example
verification_level_gte_3 (Identity verified to level 3 or higher)
From
Their verification level in Prson (5 and 6: chip checked by Prson)
Limits
Says how far the identity was checked, not who the person is: no name or document detail is shared. Levels 5 and 6 (a passport or ID card chip checked by Prson) are what Prson calls a verified human; 6 adds a face match between a live selfie and the chip photo. Levels 1 to 4 are checks done on the phone and are never called verified human.
Price
Included in the ID check
Links
Guide · Reference · Build a request with it
  • verification_level_gte_5 is what Prson calls a verified human: the chip of their passport or ID card was read and checked by Prson. verification_level_gte_6 adds a face match between a live selfie and the chip photo.
  • Instead of a fact, you can set min_verification_level on the verification: only people at that level can answer it. Sign in with Prson gives the same answer as the verified_human claim.

Example

REST (cURL)POST /v1/verifications
curl -X POST https://api.prson.net/v1/verifications \
  -H "Authorization: Bearer $PRSON_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "title": "Confirm you are a real person to join the beta",
  "requirements": [
    { "type": "fact", "fact": "verification_level_gte_5" }
  ]
}
JSON
MCPtools/call on https://api.prson.net/mcp/verify
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_verification",
    "arguments": {
      "title": "Confirm you are a real person to join the beta",
      "requirements": [
        { "type": "fact", "fact": "verification_level_gte_5" }
      ]
    }
  }
}

Bank

Bank account, balance and income. Coming soon: Prson can't verify these yet, and asking for them is refused.

Has a verified bank account

Coming soon

has_verified_bank_account

Has a verified bank account.

Example
has_verified_bank_account (Has a verified bank account)
From
Bank linking (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Premium: €0.50, never discounted
Links
Reference

Bank account in a country

Coming soon

bank_account_country_eq_{country}

Their bank account is in this country.

Example
bank_account_country_eq_PRT (Bank account in Portugal)
From
Bank linking (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Premium: €1.00, never discounted
Links
Reference

Bank account in an EU country

Coming soon

bank_account_in_eu

Their bank account is in an EU country.

Example
bank_account_in_eu (Bank account in an EU country)
From
Bank linking (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Premium: €1.00, never discounted
Links
Reference

Bank account in an EU or EEA country

Coming soon

bank_account_in_eea

Their bank account is in an EU or EEA country.

Example
bank_account_in_eea (Bank account in an EU or EEA country)
From
Bank linking (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Premium: €1.00, never discounted
Links
Reference

Bank balance of at least an amount

Coming soon

balance_gte_{amount}_{currency}

Their bank balance is at least this amount.

Example
balance_gte_1000_eur (Bank balance of at least €1,000)
From
Bank linking (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Premium: €0.50, never discounted
Links
Reference

Monthly income of at least an amount

Coming soon

income_gte_{amount}_{currency}

Their monthly income is at least this amount.

Example
income_gte_2000_eur (Monthly income of at least €2,000)
From
Bank linking (not available yet)
Limits
Coming soon: Prson can't verify this yet, so asking for it is refused.
Price
Premium: €1.50, never discounted
Links
Reference
  • Prson can't verify bank accounts, balances or income yet: asking for these facts is refused.