Identity Verification
Mobile network KYC 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:
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 (*).
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"
}
Request Examples
Choose language Bash (cURL) 5 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
Choose response example Exact Match - Score 100 14 examples
{
"status": "success",
"verification_id": "kyc_example_exact",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "match"
}
}
}
{
"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"
}
}
}
{
"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"
}
}
}
{
"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"
}
}
}
{
"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"
}
}
}
{
"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"
}
}
}
{
"status": "success",
"verification_id": "kyc_example_unable",
"mobile_number": "+447700900123",
"mobile_network_code": "23410",
"results": {
"full_name": {
"result": "unable_to_verify"
}
}
}
{
"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"
}
}
}
{
"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."
}
}
{
"status": "error",
"error": {
"code": "subscriber_not_found",
"message": "We couldn't find information for this mobile number."
}
}
{
"status": "error",
"error": {
"code": "data_not_available",
"message": "The requested information isn't available for this mobile number."
}
}
{
"status": "error",
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance for validation request."
},
"service": "kyc",
"required_amount": "0.0060000000",
"current_balance": "0.0000000000"
}
{
"status": "error",
"error": {
"code": "monthly_unlimited_payment_required",
"message": "Your monthly unlimited plan requires payment. Sign in to Provero and renew this service."
},
"service": "kyc",
"required_amount": "150.00",
"current_balance": "0.0000000000",
"error_code": "monthly_unlimited_payment_required",
"monthly_fee": "150.00",
"paid_until": null,
"renewal_url": "https://api.provero.io/dashboard#monthly-unlimited-plans"
}
{
"status": "error",
"error": {
"code": "service_temporarily_unavailable",
"message": "KYC verification is temporarily unavailable. Please try again later."
}
}
Response Body
Success structure
Error structure
Service Specific Error Codes
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.