Identity Verification
KYC Match API
Checks identity information against data associated with a mobile subscriber.
Send mobile_number in international format and at least one qualifying verification field. Each supplied identity field is verified independently and returned as a separate result. The API does not return an overall KYC result or score.
Field availability varies by country, mobile network and the subscriber information available to the verification source. A field being accepted by the API does not guarantee that it can be verified for every subscriber.
mobile_number is always required. The qualifying verification fields are full_name, first_name, last_name, address, street_number, street_name, postcode, town_city, region, country and date_of_birth. Other supported identity fields may be supplied alongside a qualifying field, but do not satisfy the minimum request requirement by themselves.
Only send information that is necessary for your verification process.
Endpoint
https://api.provero.io/api/validate/kyc
Headers
Authorization: Bearer REPLACE_WITH_API_TOKEN
Content-Type: application/json
Accept: application/json
Request Body
mobile_number is always required. You must also include at least one verification field marked with an asterisk (*).
| Field | Type | Required | Description |
|---|---|---|---|
mobile_number
|
string |
Yes | Mobile number in E.164 international format, including the leading +, for example +447700900123 |
*full_name
|
string |
No | Customer's full name |
*first_name
|
string |
No | Customer's first name |
*last_name
|
string |
No | Customer's last name or surname |
*date_of_birth
|
string |
No | Date of birth in YYYY-MM-DD format |
*address
|
string |
No | Customer's complete residential address |
*postcode
|
string |
No | Postcode or ZIP code |
email
|
string |
No | Email address |
*street_number
|
string |
No | Building or property number |
*street_name
|
string |
No | Street name |
*town_city
|
string |
No | Town or city |
*region
|
string |
No | State, county, province or region |
*country
|
string |
No | Customer's claimed country of residence as an ISO 3166-1 alpha-2 code, for example GB. This is a field to verify, not a routing parameter |
additional_address_information
|
string |
No | Flat, unit, building name or other additional address information |
middle_name
|
string |
No | Middle name or names |
last_name_at_birth
|
string |
No | Last name at birth |
gender
|
string |
No | Customer's gender |
identity_document_number
|
string |
No | Identity document number as a JSON string. Send the identifier only; document images and scans are not accepted. Supported document types vary by country and mobile network |
At least one field marked * must be supplied alongside mobile_number. Other optional fields cannot satisfy this requirement by themselves.
Most common request
{
"mobile_number": "+447700900123",
"full_name": "John Doe",
"date_of_birth": "1985-06-15"
}
Request using all supported fields
{
"mobile_number": "+447700900123",
"full_name": "John Doe",
"first_name": "John",
"last_name": "Doe",
"middle_name": "Michael",
"last_name_at_birth": "Smith",
"date_of_birth": "1985-06-15",
"address": "Flat A, 10 High Street, London, SW1A 1AA",
"street_number": "10",
"street_name": "High Street",
"additional_address_information": "Flat A",
"town_city": "London",
"region": "Greater London",
"postcode": "SW1A 1AA",
"country": "GB",
"email": "john.doe@example.com",
"gender": "male",
"identity_document_number": "ABC123456"
}
Code Examples
curl --request POST \
--url https://api.provero.io/api/validate/kyc \
--header 'Authorization: Bearer REPLACE_WITH_API_TOKEN' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"mobile_number": "+447700900123",
"full_name": "John Doe",
"date_of_birth": "1985-06-15"
}'
import requests
url = "https://api.provero.io/api/validate/kyc"
payload = {
"mobile_number": "+447700900123",
"full_name": "John Doe",
"date_of_birth": "1985-06-15",
}
headers = {
"Authorization": "Bearer REPLACE_WITH_API_TOKEN",
"Content-Type": "application/json",
"Accept": "application/json",
}
response = requests.post(url, headers=headers, json=payload)
print(response.status_code)
print(response.json())
const response = await fetch("https://api.provero.io/api/validate/kyc", {
method: "POST",
headers: {
Authorization: "Bearer REPLACE_WITH_API_TOKEN",
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
mobile_number: "+447700900123",
full_name: "John Doe",
date_of_birth: "1985-06-15"
})
});
const data = await response.json();
console.log(response.status, data);
<?php
$url = 'https://api.provero.io/api/validate/kyc';
$payload = json_encode([
'mobile_number' => '+447700900123',
'full_name' => 'John Doe',
'date_of_birth' => '1985-06-15',
]);
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer REPLACE_WITH_API_TOKEN',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => $payload,
]);
$response = curl_exec($curl);
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
echo $statusCode . PHP_EOL;
echo $response . PHP_EOL;
<?php
use Illuminate\Support\Facades\Http;
$response = Http::withToken('REPLACE_WITH_API_TOKEN')
->acceptJson()
->post('https://api.provero.io/api/validate/kyc', [
'mobile_number' => '+447700900123',
'full_name' => 'John Doe',
'date_of_birth' => '1985-06-15',
]);
dump($response->status(), $response->json());
Response Examples
Exact Match - Score 100
{
"status": "success",
"verification_id": "kyc_example_exact",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "match"
}
}
}
Partial Match - Strong Similarity (85-99)
{
"status": "success",
"verification_id": "kyc_example_strong",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "partial_match",
"similarity_score": 91,
"similarity": "strong"
}
}
}
Partial Match - Moderate Similarity (80-84)
{
"status": "success",
"verification_id": "kyc_example_moderate",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "partial_match",
"similarity_score": 82,
"similarity": "moderate"
}
}
}
Partial Match - Possible Similarity (75-79)
{
"status": "success",
"verification_id": "kyc_example_possible",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "partial_match",
"similarity_score": 77,
"similarity": "possible"
}
}
}
No Match - Low Similarity (1-74)
{
"status": "success",
"verification_id": "kyc_example_low",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "no_match",
"similarity_score": 40,
"similarity": "low"
}
}
}
No Match - No Similarity (0)
{
"status": "success",
"verification_id": "kyc_example_no_match",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "no_match",
"similarity_score": 0,
"similarity": "none"
}
}
}
Additional response examples 7
Unable to Verify
{
"status": "success",
"verification_id": "kyc_example_unable",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "unable_to_verify"
}
}
}
Mixed Result
{
"status": "success",
"verification_id": "kyc_123e4567-e89b-12d3-a456-426614174000",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "match"
},
"last_name": {
"result": "partial_match",
"similarity_score": 91,
"similarity": "strong"
},
"date_of_birth": {
"result": "unable_to_verify"
}
}
}
Missing Identity Field - HTTP 422
{
"status": "error",
"error": {
"code": "missing_verification_data",
"message": "Supply at least one qualifying verification field: full_name, first_name, last_name, address, street_number, street_name, postcode, town_city, region, country or date_of_birth."
}
}
Subscriber Not Found - HTTP 404
{
"status": "error",
"error": {
"code": "subscriber_not_found",
"message": "We couldn't find information for this mobile number."
}
}
Data Not Available - HTTP 422
{
"status": "error",
"error": {
"code": "data_not_available",
"message": "The requested information isn't available for this mobile number."
}
}
Insufficient Balance - HTTP 402
{
"status": "error",
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance for validation request."
}
}
Temporarily Unavailable - HTTP 503
{
"status": "error",
"error": {
"code": "service_temporarily_unavailable",
"message": "KYC verification is temporarily unavailable. Please try again later."
}
}
Response Body
Success structure
| Field Name | Type | Example | Always Present | Description |
|---|---|---|---|---|
status |
string |
success | Yes | Request status. Returns success when the verification request completed |
verification_id |
string |
kyc_123e4567-e89b-12d3-a456-426614174000 | Yes | Unique identifier for the verification request. Retain this when contacting support |
mobile_number |
string |
+447700900123 | Yes | Mobile number that was checked |
mobile_network_code |
string|null |
23410 | No | Public Land Mobile Network identifier formed from the Mobile Country Code and Mobile Network Code (MCC+MNC), when returned by the verification source. For example, 23410 identifies the UK (234) and O2 (10). This field does not describe the subscriber porting history |
results |
object |
{...} | Yes | Field-level verification results. Contains an entry for each submitted identity field |
results.<submitted_field>.result |
string |
partial_match | Yes | Field-level outcome: match, partial_match, no_match or unable_to_verify |
results.<submitted_field>.similarity_score |
number |
91 | No | Similarity value from 0 to 99, returned only for supported fields when the value is not an exact match and a score is available |
results.<submitted_field>.similarity |
string |
strong | No | Descriptive similarity: strong, moderate, possible, low or none. Returned only for supported fields when available |
Error structure
| Field Name | Type | Example | Always Present | Description |
|---|---|---|---|---|
status |
string |
error | Yes | Request status. Returns error |
error.code |
string |
missing_verification_data | Yes | Stable, machine-readable code identifying the error. Use this value in application logic |
error.message |
string |
Supply at least one qualifying verification field... | Yes | Human-readable description of the error. Do not rely on this text for application logic |
Service Specific Error Codes
| HTTP status | Error code | Meaning | Recommended handling |
|---|---|---|---|
| 401 | invalid_api_key |
The API key is missing or invalid. | Supply a valid API token. |
| 402 | insufficient_balance |
The account does not have enough credit for the request. | Add credit before sending another request. |
| 403 | kyc_access_not_enabled |
KYC is not enabled for the account. | Request KYC access in the Playground. |
| 404 | subscriber_not_found |
No subscriber information could be found for the mobile number. | Check the number. If it is correct, use an alternative verification route. |
| 408 | request_timed_out |
The verification request did not complete within the allowed time. | Retry with backoff. Contact support if timeouts continue. |
| 422 | invalid_mobile_number |
The mobile number is invalid or not in international format. | Correct the number and include the leading +. |
| 422 | missing_verification_data |
mobile_number was supplied without a qualifying verification field. | Add one of the qualifying fields listed in Request Body. |
| 422 | data_not_available |
The subscriber was identified, but none of the requested verification information was available. | Try a different identity field or use manual review. |
| 429 | rate_limit_exceeded |
The account has exceeded the permitted request rate. | Wait and retry with backoff. |
| 503 | service_temporarily_unavailable |
The KYC verification service is temporarily unavailable. | Retry with backoff. Contact support if the problem continues. |
Understand the Response
status: success means the verification request completed successfully. It does not mean that the submitted identity information matched.
Each submitted identity field is verified separately and returned under results using the same field name. Fields that are not supplied are not included in the response.
| result | Score where available | Meaning | Recommended handling |
|---|---|---|---|
match | 100 | The submitted value exactly matched. Exact matches are returned without similarity fields. | Treat the individual field as an exact match. |
partial_match | 75-99 | The value reached the partial-match threshold but was not exact. This indicates similarity, not a verified identity match. | Use similarity_score and your own verification rules. |
no_match | 0-74 | The value did not reach the partial-match threshold. | Check the supplied value or follow your no-match process. |
unable_to_verify | - | The field could not be verified for this subscriber. This is not a match or a no match. | Try another identity field or review the customer manually. |
Similarity
When returned, similarity_score is a value from 0 to 99 describing how similar the submitted value is to the information held. Use result as the field-level outcome and use the score as supporting evidence when the result is partial_match.
An exact match contains only result: match. Similarity fields are omitted when unavailable or not applicable, and unable_to_verify contains only its result.
| Similarity score | result | similarity | Meaning |
|---|---|---|---|
| 100 | match | - | Exact match. Similarity fields are not returned. |
| 85-99 | partial_match | strong | Strong similarity, but not an exact match. |
| 80-84 | partial_match | moderate | Moderate similarity, but not an exact match. |
| 75-79 | partial_match | possible | Possible similarity, but not an exact match. |
| 1-74 | no_match | low | Low similarity; the partial-match threshold was not reached. |
| 0 | no_match | none | No similarity was identified. |
| Unavailable | unable_to_verify | - | The field could not be checked. |
Fields with Similarity Scoring
Every supported field returns result. Only the fields marked Yes may also return similarity_score and similarity.
| Submitted field | Returns result | May return similarity fields |
|---|---|---|
full_name | Yes | Yes |
first_name | Yes | Yes |
last_name | Yes | Yes |
date_of_birth | Yes | No |
address | Yes | Yes |
postcode | Yes | No |
email | Yes | No |
street_number | Yes | Yes |
street_name | Yes | Yes |
town_city | Yes | Yes |
region | Yes | Yes |
country | Yes | No |
additional_address_information | Yes | No |
middle_name | Yes | Yes |
last_name_at_birth | Yes | Yes |
gender | Yes | No |
identity_document_number | Yes | No |
Subscriber and Field Availability Outcomes
These outcomes are deliberately distinct.
| Outcome | Scope | Meaning |
|---|---|---|
subscriber_not_found | Entire request | The mobile subscriber could not be found. The HTTP 404 response contains no field results. |
data_not_available | Entire request | The subscriber was found, but none of the requested identity information was available. The HTTP 422 response contains no usable field results. |
unable_to_verify | Individual field | The request completed and the subscriber was found, but that field could not be checked. Other fields may still return results. |
Implementation Summary
- Send
mobile_numberplus at least one qualifying verification field. email,middle_name,last_name_at_birth,additional_address_information,genderandidentity_document_numberdo not satisfy the minimum request requirement by themselves.- Treat every field in
resultsindependently and useresultas the verification outcome. - Treat scores from 75 to 99 as
partial_match; scores below 75 remainno_match. - Use
similarity_scoreonly as supporting evidence. Exact matches return onlyresult: match. - Do not treat
unable_to_verifyasno_match. - Use
error.code, noterror.message, for application logic. - Automatically retry only HTTP 408, 429 and 503 responses, using backoff.
Retry Guidance
Only retry the same request automatically for request_timed_out, rate_limit_exceeded and service_temporarily_unavailable.
Use exponential backoff and limit the number of retries. Do not automatically retry validation, authentication, access, balance or verification-outcome errors without first changing the relevant input or account state.