ID Mobile — Silent phone number verification

Support DQE
Support DQE
  • Updated
Number Verify - ID Mobile API

Use this endpoint to verify whether the phone number sent in the request matches the number initiating the request. The process involves two steps: initiate the verification request, then retrieve the result.

Related ID Mobile documentation:

Step 1: Request verification

Request

Both GET and POST are supported. This opens a consent page that the end user must accept before the result can be retrieved in Step 2.

{SERVER_ADDRESS} and {LICENCE_CODE} are provided by DQE upon account creation. {TOKEN} is the access token obtained from the ID Mobile Access Token endpoint. Contact your DQE account manager for the server address and licence code.
GEThttps://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify&redirect_uri={URL_REDIRECT}

Code examples

Request a Number Verify consent link

curl "https://{SERVER_ADDRESS}/IDMOBILE/?number=33612345678&token={TOKEN}&mode=2&name=MYCOMPANY&licence={LICENCE_CODE}&scope=numVerify"
fetch("https://{SERVER_ADDRESS}/IDMOBILE/?" + new URLSearchParams({ number: "33612345678", token: "{TOKEN}", mode: "2", name: "MYCOMPANY", licence: "{LICENCE_CODE}", scope: "numVerify" })) .then(r => r.json()) .then(data => console.log(data));
import requests response = requests.get( "https://{SERVER_ADDRESS}/IDMOBILE/", params={ "number": "33612345678", "token": "{TOKEN}", "mode": "2", "name": "MYCOMPANY", "licence": "{LICENCE_CODE}", "scope": "numVerify", }, ) print(response.json())
<?php $params = http_build_query([ 'number' => '33612345678', 'token' => '{TOKEN}', 'mode' => '2', 'name' => 'MYCOMPANY', 'licence' => '{LICENCE_CODE}', 'scope' => 'numVerify', ]); $ch = curl_init("https://{SERVER_ADDRESS}/IDMOBILE/?{$params}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true);
const axios = require('axios'); axios.get('https://{SERVER_ADDRESS}/IDMOBILE/', { params: { number: '33612345678', token: '{TOKEN}', mode: '2', name: 'MYCOMPANY', licence: '{LICENCE_CODE}', scope: 'numVerify' } }) .then(response => console.log(response.data));
HttpClient client = HttpClient.newHttpClient(); String url = "https://{SERVER_ADDRESS}/IDMOBILE/" + "?number=33612345678&token={TOKEN}&mode=2&name=MYCOMPANY&licence={LICENCE_CODE}&scope=numVerify"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
using var client = new HttpClient(); var url = "https://{SERVER_ADDRESS}/IDMOBILE/" + "?number=33612345678&token={TOKEN}&mode=2&name=MYCOMPANY&licence={LICENCE_CODE}&scope=numVerify"; var response = await client.GetAsync(url); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);
package main import ( "fmt" "io" "net/http" ) func main() { url := "https://{SERVER_ADDRESS}/IDMOBILE/" + "?number=33612345678&token={TOKEN}&mode=2&name=MYCOMPANY&licence={LICENCE_CODE}&scope=numVerify" resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }
POSThttps://{SERVER_ADDRESS}/IDMOBILE/

Add the following parameters in the request body using Content-Type: application/x-www-form-urlencoded:

Code examples

Request a Number Verify consent link

curl -X POST "https://{SERVER_ADDRESS}/IDMOBILE/" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "licence={LICENCE_CODE}" \ -d "number=33612345678" \ -d "token={TOKEN}" \ -d "mode=2" \ -d "name=MYCOMPANY" \ -d "scope=numVerify"
fetch("https://{SERVER_ADDRESS}/IDMOBILE/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ licence: "{LICENCE_CODE}", number: "33612345678", token: "{TOKEN}", mode: "2", name: "MYCOMPANY", scope: "numVerify" }) }) .then(r => r.json()) .then(data => console.log(data));
import requests response = requests.post( "https://{SERVER_ADDRESS}/IDMOBILE/", data={ "licence": "{LICENCE_CODE}", "number": "33612345678", "token": "{TOKEN}", "mode": "2", "name": "MYCOMPANY", "scope": "numVerify", }, ) print(response.json())
<?php $ch = curl_init("https://{SERVER_ADDRESS}/IDMOBILE/"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'licence' => '{LICENCE_CODE}', 'number' => '33612345678', 'token' => '{TOKEN}', 'mode' => '2', 'name' => 'MYCOMPANY', 'scope' => 'numVerify', ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true);
const axios = require('axios'); const qs = require('querystring'); axios.post('https://{SERVER_ADDRESS}/IDMOBILE/', qs.stringify({ licence: '{LICENCE_CODE}', number: '33612345678', token: '{TOKEN}', mode: '2', name: 'MYCOMPANY', scope: 'numVerify' })) .then(response => console.log(response.data));
HttpClient client = HttpClient.newHttpClient(); String form = "licence={LICENCE_CODE}&number=33612345678&token={TOKEN}&mode=2&name=MYCOMPANY&scope=numVerify"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{SERVER_ADDRESS}/IDMOBILE/")) .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(form)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
using var client = new HttpClient(); var form = new Dictionary<string, string> { ["licence"] = "{LICENCE_CODE}", ["number"] = "33612345678", ["token"] = "{TOKEN}", ["mode"] = "2", ["name"] = "MYCOMPANY", ["scope"] = "numVerify" }; var response = await client.PostAsync( "https://{SERVER_ADDRESS}/IDMOBILE/", new FormUrlEncodedContent(form)); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);
package main import ( "fmt" "io" "net/http" "net/url" ) func main() { form := url.Values{} form.Set("licence", "{LICENCE_CODE}") form.Set("number", "33612345678") form.Set("token", "{TOKEN}") form.Set("mode", "2") form.Set("name", "MYCOMPANY") form.Set("scope", "numVerify") resp, err := http.PostForm("https://{SERVER_ADDRESS}/IDMOBILE/", form) if err != nil { panic(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }

Parameters

Parameter Description Mand / Opt
SERVER_ADDRESS Address of the DQE server that will process the data. Mandatory
licence Number assigned to you as your licence code. Mandatory
number Phone number. Mandatory
token Token retrieved through authentication. Mandatory
mode Static value. Must be 2. Mandatory
name Partner name in the DQE database, usually your company name. Mandatory
scope Static value. Must be numVerify for this scope. Mandatory
redirect_uri Redirection URL. DQE adds the session token and status to the redirect. Optional
Combining scopes — numVerify can be combined with info (phone number intelligence) in a single request, e.g. scope=numVerify,info. See the info fields below.

info add-on fields — returned in addition to this endpoint's own fields when info is included in scope:

Field Description Example
telorigine Phone number in the request. 0600000000
tel Phone number, formatted. +33600000000
geolocation Geographic situation of the phone number. FRANCE
operator Current operator of the phone number, if subscribed. ORANGE
oldoperator Previous operator of the phone number. SFR
ported Indicates if the phone number is ported, if subscribed. Y
type Type of the phone number. MOBILE
iderror Error code of the check (0 or 1). 1

Response

On success, the API returns a JSON object containing the consent page URL to present to the end user.

Key Description Type
status success String
operator Operator. String
url URL of the operator API. String

Response example

Example success response
{ "status": "success", "operator": "SFR", "url": "htt***fr.fr/api/a**l8ET6UMbsaG0AOm5FsakgyKu*" }

Errors

Note on error codes 05–07 — these three codes are part of the shared step-1 validation list used across ID Mobile scopes. They reference the user_infos parameter and its phone key, which belong to other scopes (such as Matching without OTP) — Number Verify's own request has no such fields, so these codes are not expected to be triggered by a standard Number Verify call.
Error ID Error type Example request Response
01 invalid request https://{SERVER_ADDRESS}/IDMOBILE/?token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Example: missing number parameter.
{"status": "error", "error_id": "01", "error_type": "invalid request"}
02 invalid licence key https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={INCORRECT_LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "02", "error_type": "invalid licence key"}
04 invalid scope https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=wrongScope
{"status": "error", "error_id": "04", "error_type": "invalid scope"}
05 missing or empty parameter (user_infos) for this scope Not triggered by Number Verify’s own parameters
This code comes from a validation layer shared across ID Mobile scopes and references the user_infos/phone fields used by other scopes (such as Matching without OTP). Number Verify has no such parameter.
{"status": "error", "error_id": "05", "error_type": "missing or empty parameter (user_infos) for this scope"}
06 bad parameter format (user_infos) is not a valid JSON Not triggered by Number Verify’s own parameters
This code comes from a validation layer shared across ID Mobile scopes and references the user_infos/phone fields used by other scopes (such as Matching without OTP). Number Verify has no such parameter.
{"status": "error", "error_id": "06", "error_type": "bad parameter format (user_infos) is not a valid JSON"}
07 missing mandatory key in user informations (phone) Not triggered by Number Verify’s own parameters
This code comes from a validation layer shared across ID Mobile scopes and references the user_infos/phone fields used by other scopes (such as Matching without OTP). Number Verify has no such parameter.
{"status": "error", "error_id": "07", "error_type": "missing mandatory key in user informations (phone)"}
09 ineligible phone number https://{SERVER_ADDRESS}/IDMOBILE/?number={INELIGIBLE_NUMBER}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "09", "error_type": "ineligible phone number"}
10 invalid phone number https://{SERVER_ADDRESS}/IDMOBILE/?number={INVALID_NUMBER}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "10", "error_type": "invalid phone number"}
11 phone number is empty https://{SERVER_ADDRESS}/IDMOBILE/?number=&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "11", "error_type": "phone number is empty"}
12 phone check failed https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Operator-side condition — a syntactically valid request can still fail here.
{"status": "error", "error_id": "12", "error_type": "phone check failed"}
13 operator [Operator Name] not found https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Operator-side condition.
{"status": "error", "error_id": "13", "error_type": "operator [Operator Name] not found"}
14 operator [Operator Name] not authorized for this licence https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Operator-side condition — your licence is not authorised for this operator.
{"status": "error", "error_id": "14", "error_type": "operator [Operator Name] not authorized for this licence"}
15 operator [Operator Name] not supported yet https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Operator-side condition.
{"status": "error", "error_id": "15", "error_type": "operator [Operator Name] not supported yet"}
16 operator [Operator Name] unreachable https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Operator-side condition.
{"status": "error", "error_id": "16", "error_type": "operator [Operator Name] unreachable"}
17 scope not supported by this operator [Operator Name] yet https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
Operator-side condition.
{"status": "error", "error_id": "17", "error_type": "scope not supported by this operator [Operator Name] yet"}
30 invalid or expired token https://{SERVER_ADDRESS}/IDMOBILE/?number={NUM}&token={EXPIRED_TOKEN}&mode=2&name={NAME}&licence={LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "30", "error_type": "invalid or expired token"}

Test the API

Click the button below to test this endpoint live in your browser.

Open console
Step 2 — Retrieve result

Once the end user has accepted (or rejected) the consent page from Step 1, call this endpoint to retrieve the verification result.

Step 2: Retrieve result

Request

Both GET and POST are supported.

{SERVER_ADDRESS} and {LICENCE_CODE} are provided by DQE upon account creation. {TOKEN} is the same access token used in Step 1.
GEThttps://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify

Code examples

Retrieve the Number Verify result

curl "https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify"
fetch("https://{SERVER_ADDRESS}/GET/?" + new URLSearchParams({ token: "{TOKEN}", Licence: "{LICENCE_CODE}", scope: "numVerify" })) .then(r => r.json()) .then(data => console.log(data));
import requests response = requests.get( "https://{SERVER_ADDRESS}/GET/", params={ "token": "{TOKEN}", "Licence": "{LICENCE_CODE}", "scope": "numVerify", }, ) print(response.json())
<?php $params = http_build_query([ 'token' => '{TOKEN}', 'Licence' => '{LICENCE_CODE}', 'scope' => 'numVerify', ]); $ch = curl_init("https://{SERVER_ADDRESS}/GET/?{$params}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true);
const axios = require('axios'); axios.get('https://{SERVER_ADDRESS}/GET/', { params: { token: '{TOKEN}', Licence: '{LICENCE_CODE}', scope: 'numVerify' } }) .then(response => console.log(response.data));
HttpClient client = HttpClient.newHttpClient(); String url = "https://{SERVER_ADDRESS}/GET/" + "?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
using var client = new HttpClient(); var url = "https://{SERVER_ADDRESS}/GET/" + "?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify"; var response = await client.GetAsync(url); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);
package main import ( "fmt" "io" "net/http" ) func main() { url := "https://{SERVER_ADDRESS}/GET/" + "?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify" resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }
POSThttps://{SERVER_ADDRESS}/GET/

Add the following parameters in the request body using Content-Type: application/x-www-form-urlencoded:

Code examples

Retrieve the Number Verify result

curl -X POST "https://{SERVER_ADDRESS}/GET/" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "Licence={LICENCE_CODE}" \ -d "token={TOKEN}" \ -d "scope=numVerify"
fetch("https://{SERVER_ADDRESS}/GET/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ Licence: "{LICENCE_CODE}", token: "{TOKEN}", scope: "numVerify" }) }) .then(r => r.json()) .then(data => console.log(data));
import requests response = requests.post( "https://{SERVER_ADDRESS}/GET/", data={ "Licence": "{LICENCE_CODE}", "token": "{TOKEN}", "scope": "numVerify", }, ) print(response.json())
<?php $ch = curl_init("https://{SERVER_ADDRESS}/GET/"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'Licence' => '{LICENCE_CODE}', 'token' => '{TOKEN}', 'scope' => 'numVerify', ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true);
const axios = require('axios'); const qs = require('querystring'); axios.post('https://{SERVER_ADDRESS}/GET/', qs.stringify({ Licence: '{LICENCE_CODE}', token: '{TOKEN}', scope: 'numVerify' })) .then(response => console.log(response.data));
HttpClient client = HttpClient.newHttpClient(); String form = "Licence={LICENCE_CODE}&token={TOKEN}&scope=numVerify"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{SERVER_ADDRESS}/GET/")) .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(form)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
using var client = new HttpClient(); var form = new Dictionary<string, string> { ["Licence"] = "{LICENCE_CODE}", ["token"] = "{TOKEN}", ["scope"] = "numVerify" }; var response = await client.PostAsync( "https://{SERVER_ADDRESS}/GET/", new FormUrlEncodedContent(form)); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);
package main import ( "fmt" "io" "net/http" "net/url" ) func main() { form := url.Values{} form.Set("Licence", "{LICENCE_CODE}") form.Set("token", "{TOKEN}") form.Set("scope", "numVerify") resp, err := http.PostForm("https://{SERVER_ADDRESS}/GET/", form) if err != nil { panic(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) }

Parameters

Parameter Description Mand / Opt
SERVER_ADDRESS Address of the DQE server that will process the data. Mandatory
Licence Number assigned to you as your licence code. Mandatory
token Token retrieved through authentication. Mandatory
scope Static value. Must be numVerify for this scope. Mandatory

Response

Success

Key Description Type
status success: information was successfully retrieved. String
scope Contains the scope previously sent. String
numVerify Always true when this key is present — it confirms the phone number matched. A non-matching phone number is never returned as numVerify: false in a success response; it is returned as error 20 instead (see Errors below). Boolean

Pending

Returned while DQE is still waiting for the operator's response — poll Step 2 again after a short delay.

Key Description Type
status pending: DQE is waiting for the operator response. String
scope Contains numVerify. String

Response example

Example success response
{ "status": "success", "scope": "numVerify", "numVerify": true }
Example pending response
{ "status": "pending", "scope": "numVerify" }

Errors

Error ID Error type Example request Response
01 invalid request https://{SERVER_ADDRESS}/GET/?Licence={LICENCE_CODE}&scope=numVerify
Example: missing token parameter.
{"status": "error", "error_id": "01", "error_type": "invalid request"}
02 invalid licence key https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={INCORRECT_LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "02", "error_type": "invalid licence key"}
04 invalid scope https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=wrongScope
{"status": "error", "error_id": "04", "error_type": "invalid scope"}
18 failed to retrieve data from operator https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify
No data was received after OTP validation.
{"status": "error", "error_id": "18", "error_type": "failed to retrieve data from operator"}
20 Not the same phone number between the phone in the request https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify
The phone number sent in the request does not match the one initiating the request — this is the equivalent of a numVerify: false result, returned as an error rather than a successful response.
{"status": "error", "error_id": "20", "error_type": "Not the same phone number between the phone in the request"}
21 access denied https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify
OTP validation was declined.
{"status": "error", "error_id": "21", "error_type": "access denied"}
30 invalid or expired token https://{SERVER_ADDRESS}/GET/?token={EXPIRED_TOKEN}&Licence={LICENCE_CODE}&scope=numVerify
{"status": "error", "error_id": "30", "error_type": "invalid or expired token"}
99 internal server error https://{SERVER_ADDRESS}/GET/?token={TOKEN}&Licence={LICENCE_CODE}&scope=numVerify
Server error.
{"status": "error", "error_id": "99", "error_type": "internal server error"}
Example error response
{ "status": "error", "error_id": "20", "error_type": "OTP process failed" }

Test the API

Click the button below to test this endpoint live in your browser.

Open console

See also

Was this article helpful?

0 out of 0 found this helpful