Integration
Verification types
Integration

Verification types

Everything you can ask users to prove. Each credential in a user's wallet supports one or more requirements, and you can combine requirements from different credentials in one session.

Proof pricing across methods#

Verifications are priced identically once issued into the user vault: 0.5ยข (โ‚ฌ0.005) per proof reuse (less than a cent), with your first 500 successful proof reuses free. When a user does not yet hold a required credential, LKP passes through the exact wholesale cost of initial issuance (no markup, no more, no less). First-time proofs are always paid to cover wholesale provider costs; your 500 free allowance applies to reuses.

Proof MethodSupported ChecksInitial Issuance (At Cost)Proof Reuse
Facial Age EstimationAGE_OVER (18+, 21+) via 1 to 2s selfieโ‚ฌ0.10โ‚ฌ0.005
Government ID DocumentAGE_OVER, COUNTRY_EQUALS, sybil uniquenessโ‚ฌ0.33โ‚ฌ0.005
Phone Number OTPOwnership of phone, carrier country codeโ‚ฌ0.06โ‚ฌ0.005
Email Address OTPOwnership of email, corporate/school domainโ‚ฌ0.01โ‚ฌ0.005
Social & Developer AccountsGitHub org, follower thresholds, X, TikTok, Instagramโ‚ฌ0.00โ‚ฌ0.005
Open Banking AccountAccount holder name, balance thresholdโ‚ฌ0.15โ‚ฌ0.005

For age verification, businesses can configure kycWorkflow on session creation to choose age_estimation (โ‚ฌ0.10 first check, โ‚ฌ0.005 reuse), full_id (โ‚ฌ0.33 first check, โ‚ฌ0.005 reuse), or either (user picks).

Government ID#

LiveIssued via Didit ยท 7 credentials ยท source government_id

Facts printed on a passport, ID card or residence permit, checked with liveness: age, nationality (citizenship), name, sex, document details, and the address country on the document when it has one. This is verified identity, not current physical location.

AGE_OVER

The holder is at least this many years old today.

minAge: 1 to 150 years. Users see: โ€œ18 years or olderโ€.
{"kind":"AGE_OVER","minAge":18}
COUNTRY_EQUALS

The nationality (citizenship) printed on the document, not current physical location. Pass several countries to accept any of them (France or the UK).

countryIsoNumeric: ISO 3166-1 numeric, or an array of up to 16. Users see: โ€œNationality: Netherlandsโ€.
{"kind":"COUNTRY_EQUALS","countryIsoNumeric":528}
AGE_AT_MOST

The holder is at most this many years old today. Combine with a minimum age for a range.

maxAge: 0 to 150 years. Users see: โ€œ25 years or youngerโ€.
{"kind":"AGE_AT_MOST","maxAge":25}
SEX_EQUALS

The sex printed on the document.

sex: "F" | "M" | "X", or an array of up to 16. Users see: โ€œSex on document: Femaleโ€.
{"kind":"SEX_EQUALS","sex":"F"}
DOCUMENT_VALID_FOR

The identity document stays valid for at least this many more days.

minDays: 0 to 3650 days. Users see: โ€œID document valid for at least 90 daysโ€.
{"kind":"DOCUMENT_VALID_FOR","minDays":90}
DOCUMENT_TYPE_EQUALS

The kind of document the holder verified with.

documentType: "passport" | "id_card" | "residence_permit" | "drivers_license", or an array of up to 16. Users see: โ€œVerified with a passportโ€.
{"kind":"DOCUMENT_TYPE_EQUALS","documentType":"passport"}
ISSUING_COUNTRY_EQUALS

The country that issued the document.

countryIsoNumeric: ISO 3166-1 numeric, or an array of up to 16. Users see: โ€œID issued by: Netherlandsโ€.
{"kind":"ISSUING_COUNTRY_EQUALS","countryIsoNumeric":528}
FULL_NAME_EQUALS

The holder's given names and surname as printed on the document. Case and accents are ignored.

fullName: string, up to 100 characters, or an array of up to 16. Users see: โ€œName on ID: JAN DE VRIESโ€.
{"kind":"FULL_NAME_EQUALS","fullName":"JAN DE VRIES"}
DOCUMENT_NUMBER_EQUALS

The number of the document the holder verified with.

documentNumber: string, up to 100 characters, or an array of up to 16. Users see: โ€œID document number NX1234567โ€.
{"kind":"DOCUMENT_NUMBER_EQUALS","documentNumber":"NX1234567"}
RESIDENCE_COUNTRY_EQUALS

The country of the address printed on the document, when it has one. This is not proof that the holder currently lives there.

countryIsoNumeric: ISO 3166-1 numeric, or an array of up to 16. Users see: โ€œAddress country on ID: Netherlandsโ€.
{"kind":"RESIDENCE_COUNTRY_EQUALS","countryIsoNumeric":528}

Phone number#

LiveIssued via Didit ยท 2 credentials ยท source phone

Ownership of a phone number, checked with a one-time code. Each number backs only one wallet.

PHONE_VERIFIED

The holder owns a phone number. Each number backs only one wallet.

lineType: "any" | "not_virtual" | "mobile". Users see: โ€œHas a verified phone numberโ€.
{"kind":"PHONE_VERIFIED","lineType":"any"}
PHONE_COUNTRY_EQUALS

The country the phone number belongs to.

countryIsoNumeric: ISO 3166-1 numeric, or an array of up to 16. Users see: โ€œPhone number from: Netherlandsโ€.
{"kind":"PHONE_COUNTRY_EQUALS","countryIsoNumeric":528}
PHONE_NUMBER_EQUALS

The holder owns exactly this number, in international format.

phoneNumber: E.164 string, e.g. +31612345678, or an array of up to 16. Users see: โ€œOwns phone number +31612345678โ€.
{"kind":"PHONE_NUMBER_EQUALS","phoneNumber":"+31612345678"}

Work or school email#

LiveIssued via Didit ยท 2 credentials ยท source email

Ownership of an email address at an organisation's domain, checked with a one-time code.

EMAIL_VERIFIED

The holder owns an email address of this kind. Work means an organisation's own domain, not a free mailbox.

type: "any" | "work_or_school" | "school". Users see: โ€œHas a verified work or school email addressโ€.
{"kind":"EMAIL_VERIFIED","type":"work_or_school"}
EMAIL_DOMAIN_EQUALS

The address belongs to this organisation. Subdomains count: student.uva.nl matches uva.nl.

domain: domain string, e.g. company.com, or an array of up to 16. Users see: โ€œEmail address at example.comโ€.
{"kind":"EMAIL_DOMAIN_EQUALS","domain":"example.com"}
EMAIL_ADDRESS_EQUALS

The holder owns exactly this email address.

email: email address string, or an array of up to 16. Users see: โ€œOwns jane@example.comโ€.
{"kind":"EMAIL_ADDRESS_EQUALS","email":"jane@example.com"}

Instagram#

LiveIssued via TLSNotary ยท 2 credentials ยท source instagram

Ownership of an Instagram account, its username, follower and post counts and verified badge, notarized from Instagram's own servers.

FOLLOWERS_AT_LEAST

The holder's Instagram account has at least this many followers.

minFollowers: integer โ‰ฅ 0 followers. Users see: โ€œAt least 1,000 Instagram followersโ€.
{"kind":"FOLLOWERS_AT_LEAST","minFollowers":1000}
INSTAGRAM_USERNAME_EQUALS

The holder owns this Instagram account.

username: string, up to 64 characters, or an array of up to 16. Users see: โ€œInstagram account @lkpโ€.
{"kind":"INSTAGRAM_USERNAME_EQUALS","username":"lkp"}
INSTAGRAM_POSTS_AT_LEAST

The Instagram account has published at least this many posts.

minPosts: integer โ‰ฅ 0 posts. Users see: โ€œAt least 10 Instagram postsโ€.
{"kind":"INSTAGRAM_POSTS_AT_LEAST","minPosts":10}
INSTAGRAM_VERIFIED

The Instagram account has Instagram's verified badge.

No parameters. Users see: โ€œVerified Instagram accountโ€.
{"kind":"INSTAGRAM_VERIFIED"}

X#

LiveIssued via X ยท 3 credentials ยท source x

Ownership of an X account via X's own login: username, followers, posts, account age and verification.

X_FOLLOWERS_AT_LEAST

The holder's X account has at least this many followers.

minFollowers: integer โ‰ฅ 0 followers. Users see: โ€œAt least 1,000 followers on Xโ€.
{"kind":"X_FOLLOWERS_AT_LEAST","minFollowers":1000}
X_USERNAME_EQUALS

The holder owns this X account.

username: string, up to 64 characters, or an array of up to 16. Users see: โ€œX account @lkpโ€.
{"kind":"X_USERNAME_EQUALS","username":"lkp"}
X_ACCOUNT_AGE_AT_LEAST

The X account was created at least this many days ago.

minDays: 0 to 36500 days. Users see: โ€œX account at least 1 year oldโ€.
{"kind":"X_ACCOUNT_AGE_AT_LEAST","minDays":365}
X_VERIFIED

The X account is verified.

No parameters. Users see: โ€œVerified X accountโ€.
{"kind":"X_VERIFIED"}
X_POSTS_AT_LEAST

The X account has published at least this many posts.

minPosts: integer โ‰ฅ 0 posts. Users see: โ€œAt least 100 posts on Xโ€.
{"kind":"X_POSTS_AT_LEAST","minPosts":100}

TikTok#

LiveIssued via TikTok ยท 3 credentials ยท source tiktok

Ownership of a TikTok account via TikTok's own login: username, followers, likes, videos and verification.

TIKTOK_FOLLOWERS_AT_LEAST

The holder's TikTok account has at least this many followers.

minFollowers: integer โ‰ฅ 0 followers. Users see: โ€œAt least 1,000 TikTok followersโ€.
{"kind":"TIKTOK_FOLLOWERS_AT_LEAST","minFollowers":1000}
TIKTOK_USERNAME_EQUALS

The holder owns this TikTok account.

username: string, up to 64 characters, or an array of up to 16. Users see: โ€œTikTok account @lkpโ€.
{"kind":"TIKTOK_USERNAME_EQUALS","username":"lkp"}
TIKTOK_LIKES_AT_LEAST

The TikTok account's videos have at least this many likes in total.

minLikes: integer โ‰ฅ 0 likes. Users see: โ€œAt least 10,000 TikTok likesโ€.
{"kind":"TIKTOK_LIKES_AT_LEAST","minLikes":10000}
TIKTOK_VERIFIED

The TikTok account is verified.

No parameters. Users see: โ€œVerified TikTok accountโ€.
{"kind":"TIKTOK_VERIFIED"}
TIKTOK_VIDEOS_AT_LEAST

The TikTok account has published at least this many videos.

minVideos: integer โ‰ฅ 0 videos. Users see: โ€œAt least 10 TikTok videosโ€.
{"kind":"TIKTOK_VIDEOS_AT_LEAST","minVideos":10}

GitHub#

LiveIssued via GitHub ยท 5 credentials ยท source github

Ownership of a GitHub account via GitHub's own login: username, followers, account age, two-factor status, repositories, contributions and organisations.

GITHUB_FOLLOWERS_AT_LEAST

The holder's GitHub account has at least this many followers.

minFollowers: integer โ‰ฅ 0 followers. Users see: โ€œAt least 10 GitHub followersโ€.
{"kind":"GITHUB_FOLLOWERS_AT_LEAST","minFollowers":10}
GITHUB_USERNAME_EQUALS

The holder owns this GitHub account.

username: string, up to 64 characters, or an array of up to 16. Users see: โ€œGitHub account @lkpโ€.
{"kind":"GITHUB_USERNAME_EQUALS","username":"lkp"}
GITHUB_ACCOUNT_AGE_AT_LEAST

The GitHub account was created at least this many days ago.

minDays: 0 to 36500 days. Users see: โ€œGitHub account at least 1 year oldโ€.
{"kind":"GITHUB_ACCOUNT_AGE_AT_LEAST","minDays":365}
GITHUB_TWO_FACTOR

The GitHub account has two-factor authentication turned on.

No parameters. Users see: โ€œGitHub account with two-factor sign-inโ€.
{"kind":"GITHUB_TWO_FACTOR"}
GITHUB_REPOS_AT_LEAST

The GitHub account owns at least this many public repositories.

minRepos: integer โ‰ฅ 0 repositories. Users see: โ€œAt least 5 public GitHub repositoriesโ€.
{"kind":"GITHUB_REPOS_AT_LEAST","minRepos":5}
GITHUB_CONTRIBUTIONS_AT_LEAST

The GitHub account made at least this many contributions in the last year.

minContributions: integer โ‰ฅ 0 contributions. Users see: โ€œAt least 100 GitHub contributions in the last yearโ€.
{"kind":"GITHUB_CONTRIBUTIONS_AT_LEAST","minContributions":100}
GITHUB_ORG_MEMBER

The holder is a member of this GitHub organisation.

organisation: string, up to 100 characters, or an array of up to 16. Users see: โ€œMember of the github GitHub organisationโ€.
{"kind":"GITHUB_ORG_MEMBER","organisation":"github"}

Bank account#

LiveIssued via Enable Banking ยท 3 credentials ยท source bank

A bank account read through open banking: its balance, IBAN and account holder name.

BALANCE_AT_LEAST

The holder's account balance is at least this amount, in euros.

minBalanceCents: integer โ‰ฅ 0 (minor currency units). Users see: โ€œBalance of at least โ‚ฌ1,000.00โ€.
{"kind":"BALANCE_AT_LEAST","minBalanceCents":100000}
BANK_ACCOUNT_EQUALS

The holder controls exactly this bank account.

iban: string, up to 100 characters, or an array of up to 16. Users see: โ€œHolds bank account NL91ABNA0417164300โ€.
{"kind":"BANK_ACCOUNT_EQUALS","iban":"NL91ABNA0417164300"}
BANK_HOLDER_EQUALS

The name the bank has on the account. Case and accents are ignored.

holderName: string, up to 100 characters, or an array of up to 16. Users see: โ€œBank account in the name of JAN DE VRIESโ€.
{"kind":"BANK_HOLDER_EQUALS","holderName":"JAN DE VRIES"}

Combining requirements#

  • Send up to 40 requirements per session (the full catalog). Same-credential checks compile to one proof. The user must prove all of them, in one step, with one anonymous ID.
  • Minimums of the same kind merge to the strictest: two minimum ages keep the higher one.
  • Exact matches accept several values: nationality can be { "kind": "COUNTRY_EQUALS", "countryIsoNumeric": [250, 826] } (France or the UK). Repeating the same requirement with different values unions them. The result confirms that one of the values matched, not which one.
  • Users only share what you ask for. Requiring a minimum age never reveals the birth date or the nationality.
  • Nationality is citizenship printed on the document, not current physical location. Address country is the address on the document when it has one.
  • Exact-match requirements (a name, a phone number, an organisation) reveal nothing beyond the match. Users see the exact value you ask about before they share.

The console's integration builder lets you pick requirements visually and generates the request for you.

List them programmatically#

GET/v1/verification-types

Public, no API key needed. Returns every module and requirement with its parameter limits, status and an example, so you can build your own settings UI or validate configuration in CI.

curl https://lkp-verifier.onrender.com/v1/verification-types

Response

{
  "object": "list",
  "maxRequirements": 40,
  "maxProofs": 27,
  "data": [
    {
      "id": "government_id",
      "title": "Government ID",
      "provider": "Didit",
      "status": "live",
      "requirements": [
        {
          "kind": "AGE_OVER",
          "status": "live",
          "combine": "strictest",
          "param": { "name": "minAge", "label": "Minimum age", "input": "integer", "default": 18, "min": 1, "max": 150, "unit": "years" },
          "example": { "kind": "AGE_OVER", "minAge": 18 }
        },
        {
          "kind": "COUNTRY_EQUALS",
          "status": "live",
          "combine": "any_of",
          "maxValues": 16,
          "param": { "name": "countryIsoNumeric", "label": "Country", "input": "country", "default": 528, "min": 1, "max": 999 },
          "example": { "kind": "COUNTRY_EQUALS", "countryIsoNumeric": [250, 826] }
        },
        โ€ฆ
      ]
    },
    โ€ฆ
  ]
}

Need something else?#

We add new verification types regularly. If you need a check that isn't listed, such as a different document attribute, another social platform or a professional licence, tell us what you need and how you'd use it.