Biometric identity verification

Ask a payee to verify their identity with a government ID and a live selfie, start the verification session, and read the result as a payer or payee.

A biometric identity verification checks a Payee's government ID and a live selfie against each other and against the Payee's identity. The Payee owns the verification. A payer asks for one by creating a request, then reads the outcome from that request once the Payee shares it.

This is separate from the account holder's own KYC record under /v3/onboarding; see Identity verification.

Two resources

ResourceOwnerWhat it holds
BiometricIdentityVerificationThe payeeThe session lifecycle, document type, risk signals, and fields read off the ID.
BiometricIdentityVerificationRequestThe payerA payer's view of one payee's verification, with a derived status.

A payer never reads the verification directly. It reads the same data embedded on its request, and only once the request is terminal. Wingspan applies this because the verification carries government-ID data.

Endpoints

Ask for a verification

POST /v3/compliance/biometric-identity-verification-requests is the standalone path. A request that fulfills a BiometricIdentityVerification requirement is created by the platform when the requirement instance is created, so you don't call this for those.

FieldTypeNotes
payerPayeeIdstring, requiredThe relationship.
requirementIdstringOptional.
externalIdstringYour reconciliation ID. Unique per payer account.
forceCreatebooleanSkip reuse of an earlier passed verification.
metadataobject
curl -X POST https://api.wingspan.app/v3/compliance/biometric-identity-verification-requests \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "payerPayeeId": "PAYER_PAYEE_ID", "externalId": "idv-1042" }'
// 201 Created (trimmed)
{
  "id": "REQUEST_ID",
  "payerAccountId": "PAYER_ACCOUNT_ID",
  "payeeAccountId": "PAYEE_ACCOUNT_ID",
  "biometricIdentityVerificationId": "VERIFICATION_ID",
  "status": "Pending",
  "resultFiles": []
}

The payee's underlying verification is found or created in the same call. If the payee's principal person already passed a verification they started themselves on another account, that result is reused and the request can be Complete straight away. forceCreate: true skips the reuse.

When the payee Account has no principal, the request verifies its Business representative. Creating one needs a committed Business representative identity. If that maps to a Stakeholder, the request reuses that Stakeholder's verification.

Request status

status is derived and can't be set. It combines the verification's outcome with whether the payee agreed to share identity documents with you:

  • Pending: not finished, or passed but not yet shared with you.
  • Complete: passed and shared.
  • Failed: failed and shared.

Once the request is Complete or Failed, biometricIdentityVerification is embedded and resultFiles lists the captured images. While it is Pending, the biometricIdentityVerification key is absent, not null.

resultFiles entries hold imageType, fileId, and mimeType. They are IDs only. Resolve a fileId through the vault.

List filters: status, payerAccountId, payeeAccountId, biometricIdentityVerificationId, externalId (each with eq or anyOf), accountIds[anyOf], and includeDescendants. Only the payer can PATCH a request, and only externalId and metadata. A payee gets 404.

Run the verification (payee)

The payee's own verification moves Created to Pending to Passed or Failed. Both end states are final. A new attempt creates a new verification.

  1. Read the verification with GET /v3/compliance/biometric-identity-verifications/{id}. A payer gets 404 here, as it does for a verification that doesn't exist. A payer's list is empty.
  2. Call POST .../{id}/start. It returns a session credential and moves the verification to Pending.
// 200 OK
{ "sessionToken": "SESSION_TOKEN", "expiresAt": "2026-11-02T18:30:00Z" }

Treat sessionToken as a secret. It authorizes document and selfie submission. Each call mints a new credential, so an abandoned attempt can simply be started again.

A finished verification has documentType (IDCard, DriversLicense, Passport, PassportCard, Permit, Visa, or ResidenceDocument), riskSignals (reason codes behind a Failed result), and extractedFields read off the document.

Errors

StatusWhen
400Start on a verification that already reached Passed or Failed.
403Start when the principal's compliance entity belongs to a person and the caller isn't that person, including an account API key.
404Anyone but the payee calls start. A payer reads a verification. A payee calls PATCH on a request.
409Duplicate externalId. The verification changed while starting: retry with a new Idempotency-Key. An earlier attempt on another record is still under review. The bound identity record or vault changed.
422detailCode users.BiometricIdentityVerificationPrincipalRequired when the account has no principal person (or an unaccepted principal assignment on create). users.BiometricIdentityVerificationPrincipalComplianceEntityRequired when the principal has no individual compliance entity. Fix the cause, then retry with a new Idempotency-Key. A repeated key replays the earlier 422.

Events

There are no published webhook events for biometric identity verification. Poll the request, or the requirement it backs.


Did this page help you?