Skip to main content

Your First API Call (Verification Gateway)

note

Verification Gateway was formerly VaaS (Verification as a Service). Only the name changed: keep using your existing hostname (for example vaas.stg.iden2.app) and API paths.

This walkthrough takes you from zero to a 201 Created verification session, and then to your first verified credential presentation.

Prerequisites​

  • An OAuth access token with the verification.session.create and verification.session.read scopes (Authentication)
  • Staging environment access
  • A wallet app holding a credential (issue one first via Credential Factory if needed)

The examples below assume you have already acquired a token and stored it in $ACCESS_TOKEN — see Authentication.

1. Create a verification session​

All request fields are optional — the minimal request is an empty object {}. Here we set a TTL and a correlation ID:

curl -X POST https://vaas.stg.iden2.app/api/v1/verifier/sessions \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"ttlSeconds": 120,
"externalId": "my-first-verification"
}'

A successful call returns 201 Created:

{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"authorizationUrl": "openid4vp://authorize?response_type=vp_token&client_id=...&client_metadata=...",
"qrCodeDataUrl": "data:image/png;base64,iVBORw0KGgo...",
"status": "pending",
"createdAt": "2025-01-15T10:00:00Z",
"expiresAt": "2025-01-15T10:02:00Z",
"externalId": "my-first-verification",
"credentialType": "VerifiedPerson"
}

2. Show the QR code​

<img src="data:image/png;base64,iVBORw0KGgo..." alt="Scan with your wallet to share your credential" />

The holder scans the QR with their wallet, reviews which fields are requested, and consents to share them. You don't need to parse the authorizationUrl — just display it. (Curious what's inside it? See client_metadata vs. client_id.)

3. Poll for the result​

curl https://vaas.stg.iden2.app/api/v1/verifier/sessions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $ACCESS_TOKEN"

Poll every 3–5 seconds until status is terminal:

StatusTerminal?Meaning
pendingNoWaiting for the holder to present
completedYesVerification passed — credentialData contains the disclosed claims
failedYesVerification failed — failureReason explains why

On completed, the response includes the extracted claims and detailed check results:

{
"sessionId": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"credentialData": {
"givenName": "Alice",
"dateOfBirth": "1990-01-15"
},
"verificationResult": {
"signatureValid": true,
"issuerTrusted": true,
"policyCompliant": true,
"revocationStatus": "not_revoked",
"issuerMemberId": "urn:uuid:3c4d5e6f-...",
"checks": [
{ "type": "signature", "status": "success", "algorithm": "ES256" },
{ "type": "revocation", "status": "success", "mechanism": "BitstringStatusList" },
{ "type": "issuer_trust", "status": "success" }
]
}
}
Before you grant access

Don't just check status === "completed". Always also verify verificationResult.signatureValid, issuerTrusted, and that revocationStatus !== "revoked". See Security Best Practices.

Troubleshooting​

Response / resultLikely cause
401Missing, invalid, or expired access token
403Your token lacks the required scope, or your configuration isn't permitted to request this credential type
failed with issuer_not_trustedThe credential's issuer isn't in your trust network — contact iDen2
failed with expiredHolder didn't present in time — create a new session

Next steps​