Verify Identity
API reference for verifying identity data against national databases with name matching.
Verify an identity number against national databases and optionally match the returned profile against expected biographical data.
Endpoint
POST /api/v1/identity/verify
Scope: identity:resolve
Request body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Identity type: bvn, nin, tin, voter, passport, phone, license |
value | string | Yes | The identity number to verify |
matchAgainst | object | No | Biographical data to match against the resolved profile |
matchAgainst.firstName | string | No | Expected first name |
matchAgainst.lastName | string | No | Expected last name |
matchAgainst.dateOfBirth | string | No | Expected date of birth (ISO 8601 date, e.g. 1990-05-15) |
consent | object | Yes | Consent proof (see below) |
consent.reference | string | Yes | Your application's consent reference ID |
consent.obtainedAt | string | Yes | ISO 8601 timestamp when consent was obtained |
The consent field is mandatory. Requests without a valid consent reference are rejected with a BAD_REQUEST error. See Consent & NDPR for compliance details.
Response
{
"success": true,
"data": {
"verified": true,
"matchScore": 0.94,
"matches": {
"firstName": { "match": true, "score": 0.96 },
"lastName": { "match": true, "score": 1.0 },
"dateOfBirth": { "match": true, "score": 1.0 }
},
"profile": {
"firstName": "Adaeze",
"lastName": "Okonkwo",
"dateOfBirth": "1990-05-15",
"gender": "female",
"phone": "+2348012345678"
},
"provider": "primary",
"verifiedAt": "2026-04-05T14:30:00.000Z"
}
}
| Field | Type | Description |
|---|---|---|
verified | boolean | Overall verification result (true if all provided matchAgainst fields pass) |
matchScore | number | Aggregate match score between 0 and 1 |
matches | object | Per-field match results with individual scores |
profile | object | Profile data returned from the identity provider |
provider | string | Which provider in the fallback chain answered the request |
verifiedAt | string | ISO 8601 timestamp of verification |
If matchAgainst is omitted, the endpoint still resolves the identity and returns the profile, but verified will be null and matches will be empty. Use the Resolve endpoint if you only need profile data without matching.
Examples
curl
curl -X POST https://api.platformxe.com/api/v1/identity/verify \
-H "Content-Type: application/json" \
-H "x-api-key: pxk_live_your_api_key_here" \
-d '{
"type": "bvn",
"value": "22345678901",
"matchAgainst": {
"firstName": "Adaeze",
"lastName": "Okonkwo",
"dateOfBirth": "1990-05-15"
},
"consent": {
"reference": "consent_ref_abc123",
"obtainedAt": "2026-04-01T10:00:00.000Z"
}
}'
SDK
import { PlatformXe } from '@caldera/platformxe-sdk';
const px = new PlatformXe({ apiKey: 'pxk_live_your_api_key_here' });
const result = await px.identity.verify({
type: 'bvn',
value: '22345678901',
matchAgainst: {
firstName: 'Adaeze',
lastName: 'Okonkwo',
dateOfBirth: '1990-05-15',
},
consent: {
reference: 'consent_ref_abc123',
obtainedAt: '2026-04-01T10:00:00.000Z',
},
});
if (result.data.verified) {
console.log('Identity verified with score:', result.data.matchScore);
// "Identity verified with score: 0.94"
} else {
console.log('Verification failed. Matches:', result.data.matches);
}
Verify without name matching
const result = await px.identity.verify({
type: 'nin',
value: '12345678901',
consent: {
reference: 'consent_ref_def456',
obtainedAt: '2026-04-01T10:00:00.000Z',
},
});
// verified is null when matchAgainst is not provided
console.log(result.data.profile.firstName);
// "Adaeze"
Error responses
| Code | Description |
|---|---|
BAD_REQUEST | Missing required fields, invalid identity type, or missing consent |
NOT_FOUND | No identity record found for the given type and value |
FORBIDDEN | API key does not have the identity:resolve scope |
RATE_LIMITED | Exceeded plan limit for identity verification requests |