Provero Logo

Age Verification API

Identity and age assurance. Provero uses age-verification information available from the subscriber's mobile network to determine whether a chosen age threshold can be confirmed. This is an age check, not an identity or KYC check, and it does not return an exact age or date of birth. The upstream service currently supports Pay Monthly subscribers on the UK's four main mobile networks: EE, O2, Vodafone and Three.
Send a mobile number and minimum age to check whether available subscriber information confirms that threshold. Use meets_age_requirement as the age-check outcome: status: success means the request completed, not that the requirement was met. Live requests require a Provero API key and Age Verification access.

Endpoint

POST
https://api.provero.io/api/validate/age

Headers

Authorization: Bearer REPLACE_WITH_API_TOKEN
Content-Type: application/json
Accept: application/json


Request Body

Field Type Required Description
mobile_number string Yes Mobile number in E.164 international format, including the leading +, for example +447700900123.
minimum_age integer Yes Minimum age to verify, from 0 to 120. For example, use 18 for an 18+ check or 25 for a 25+ check.
Request Body example (JSON)
{
    "mobile_number": "+447700900123",
    "minimum_age": 18
}

Code Examples

curl -X POST https://api.provero.io/api/validate/age \
  -H "Authorization: Bearer REPLACE_WITH_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"mobile_number":"+447700900123","minimum_age":18}'
<?php
$payload = [
    "mobile_number" => "+447700900123",
    "minimum_age" => 18,
];

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.provero.io/api/validate/age",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer REPLACE_WITH_API_TOKEN",
        "Content-Type: application/json",
        "Accept: application/json"
    ],
]);

$response = curl_exec($curl);
if (curl_errno($curl)) {
    echo 'Error:' . curl_error($curl);
}
curl_close($curl);
echo $response;
$response = Http::withToken('REPLACE_WITH_API_TOKEN')
    ->acceptJson()
    ->post('https://api.provero.io/api/validate/age', [
        'mobile_number' => '+447700900123',
        'minimum_age' => 18,
    ]);

return $response->json();
const response = await fetch('https://api.provero.io/api/validate/age', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer REPLACE_WITH_API_TOKEN',
    'Content-Type': 'application/json',
    Accept: 'application/json'
  },
  body: JSON.stringify({
    mobile_number: '+447700900123',
    minimum_age: 18
  })
});
response = requests.post(
    'https://api.provero.io/api/validate/age',
    headers={'Authorization': 'Bearer REPLACE_WITH_API_TOKEN'},
    json={'mobile_number': '+447700900123', 'minimum_age': 18},
)

Response Examples

Success - Requirement Met
{
    "status": "success",
    "verification_id": "age_123456",
    "mobile_number": "+447746266201",
    "minimum_age": 18,
    "meets_age_requirement": true,
    "identity_verified": true,
    "adult_content_restriction_active": false,
    "parental_controls_active": false,
    "mobile_network_code": "23410"
}
Success - Requirement Not Confirmed
{
    "status": "success",
    "verification_id": "age_123457",
    "mobile_number": "+447746266202",
    "minimum_age": 25,
    "meets_age_requirement": false,
    "identity_verified": false,
    "adult_content_restriction_active": false,
    "parental_controls_active": false,
    "mobile_network_code": "23410"
}
Success - Higher-age Requirement Met
{
    "status": "success",
    "verification_id": "age_123458",
    "mobile_number": "+447746266201",
    "minimum_age": 50,
    "meets_age_requirement": true,
    "identity_verified": true,
    "adult_content_restriction_active": false,
    "parental_controls_active": false,
    "mobile_network_code": "23410"
}
Success - Secondary Information Unavailable
{
    "status": "success",
    "verification_id": "age_123459",
    "mobile_number": "+447746266205",
    "minimum_age": 18,
    "meets_age_requirement": true,
    "identity_verified": null,
    "adult_content_restriction_active": null,
    "parental_controls_active": null,
    "mobile_network_code": null
}
Success - Adult-content Restriction Active
{
    "status": "success",
    "verification_id": "age_123460",
    "mobile_number": "+447746266203",
    "minimum_age": 18,
    "meets_age_requirement": true,
    "identity_verified": true,
    "adult_content_restriction_active": true,
    "parental_controls_active": false,
    "mobile_network_code": "23410"
}
Success - Parental Controls Active
{
    "status": "success",
    "verification_id": "age_123461",
    "mobile_number": "+447746266204",
    "minimum_age": 18,
    "meets_age_requirement": true,
    "identity_verified": true,
    "adult_content_restriction_active": false,
    "parental_controls_active": true,
    "mobile_network_code": "23410"
}
Additional response examples 11
Validation Error - Invalid Mobile Number (422)
{
    "status": "error",
    "error": {
        "code": "invalid_mobile_number",
        "message": "Enter a valid mobile number in international format."
    }
}
Validation Error - Invalid Minimum Age (422)
{
    "status": "error",
    "error": {
        "code": "invalid_age",
        "message": "Enter a valid minimum age."
    }
}
Not Found - Subscriber Not Found (404)
{
    "status": "error",
    "error": {
        "code": "subscriber_not_found",
        "message": "We couldn't find information for this mobile number."
    }
}
Validation Error - Network Not Supported (422)
{
    "status": "error",
    "error": {
        "code": "network_not_supported",
        "message": "Age verification isn't available for this mobile network."
    }
}
Validation Error - Subscriber Opted Out (422)
{
    "status": "error",
    "error": {
        "code": "subscriber_opted_out",
        "message": "Age verification isn't available for this mobile number."
    }
}
Validation Error - Age Verification Not Available (422)
{
    "status": "error",
    "error": {
        "code": "age_verification_not_available",
        "message": "Age verification isn't available for this mobile number."
    }
}
Unauthorized - Invalid API Key (401)
{
    "status": "error",
    "error": {
        "code": "invalid_api_key",
        "message": "The API key is missing or invalid."
    }
}
Forbidden - Age Verification Access Not Enabled (403)
{
    "status": "error",
    "error": {
        "code": "age_verification_access_not_enabled",
        "message": "Age Verification isn't currently enabled for this account. Sign in to the Provero UI and request access from the Playground."
    }
}
Rate Limited - Too Many Requests (429)
{
    "status": "error",
    "error": {
        "code": "rate_limit_exceeded",
        "message": "Too many requests have been made. Please try again later."
    }
}
Request Timeout (408)
{
    "status": "error",
    "error": {
        "code": "request_timed_out",
        "message": "The verification request timed out. Please try again."
    }
}
Service Temporarily Unavailable (503)
{
    "status": "error",
    "error": {
        "code": "service_temporarily_unavailable",
        "message": "Age Verification is temporarily unavailable. Please try again later."
    }
}

Response Body

Success structure

Field Name Type Example Always Present Description
status string success Yes Indicates that the verification request completed. This is not the age-check result.
verification_id string age_123456 Yes Unique Provero reference for this request.
mobile_number string +447746266201 Yes The mobile number checked, normalized to E.164 international format.
minimum_age integer 18 Yes The minimum age requested.
meets_age_requirement boolean 1 Yes The primary age-check outcome. Whether the available subscriber information confirms the requested minimum age.
identity_verified boolean|null 1 Yes Whether the information used for the age check was verified against official identification. This supporting signal is not an identity or KYC result; null means it is unavailable.
adult_content_restriction_active boolean|null Yes Whether the network reports an adult-content restriction as active. This does not replace the age result; null means the signal is unavailable or unsupported.
parental_controls_active boolean|null Yes Whether the network reports parental controls as active. This does not replace the age result; null means the signal is unavailable or unsupported.
mobile_network_code string|null 23410 Yes Combined mobile country and network code associated with the result, or null when unavailable.

Error structure

Field Name Type Example Always Present Description
status string error Yes Indicates that the request could not be completed.
error object {"code":"invalid_age","message":"Enter a valid minimum age."} Yes Contains a stable error.code for integration logic and a human-readable error.message. Some errors intentionally share customer-safe messages.

Understanding the response

Use meets_age_requirement as the primary outcome. A value of false means the requested threshold was not confirmed; it must not be interpreted as the subscriber's exact age or as confirmation that they are below the threshold.

identity_verified, adult_content_restriction_active and parental_controls_active are supporting signals and do not override the age result. Do not treat a null supporting signal as false.

Request examples

Change only minimum_age to run an 18+, 21+, 25+, or 50+ check through the same endpoint.

18+ check

{
    "mobile_number": "+447746266141",
    "minimum_age": 18
}

21+ check

{
    "mobile_number": "+447746266141",
    "minimum_age": 21
}

25+ check

{
    "mobile_number": "+447746266141",
    "minimum_age": 25
}

50+ check

{
    "mobile_number": "+447746266141",
    "minimum_age": 50
}

Errors and recommended actions

Error responses use the same envelope across Age Verification failures. The HTTP status identifies the failure class and error.code is the stable value to branch on in your integration; do not branch on the human-readable message. Automatically retry only request_timed_out (408), rate_limit_exceeded (429) and service_temporarily_unavailable (503), using bounded backoff. Do not retry other responses unchanged.

HTTP statusCodeRecommended action
422 invalid_mobile_number Correct the number and include the leading +.
422 invalid_age Supply an integer minimum_age from 0 to 120.
422 age_verification_not_available Do not infer an age outcome; use another permitted age-assurance route.
404 subscriber_not_found Check the number. If it is correct, use another permitted age-assurance route.
422 network_not_supported Use another permitted age-assurance route.
422 subscriber_opted_out Do not retry unless the subscriber's status changes.
403 age_verification_access_not_enabled Sign in to Provero and request Age Verification access from the Playground.
401 invalid_api_key Supply a valid API token.
402 insufficient_balance Add credit before sending another request.
429 rate_limit_exceeded Wait and retry using backoff.
408 request_timed_out Retry with backoff.
503 service_temporarily_unavailable Retry later using exponential backoff.

Ready to go live?

Explore the simulated Playground first. Live checks require a Provero API key and Age Verification enabled on your account.