curl -X POST https://verification.didit.me/v3/phone/risk/ \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"phone_number": "+14155552671",
"country_code": "US",
"vendor_data": "lead-123",
"metadata": {"source": "signup_prescreen"}
}'import os, requests
resp = requests.post(
"https://verification.didit.me/v3/phone/risk/",
headers={"x-api-key": os.environ["DIDIT_API_KEY"], "Content-Type": "application/json"},
json={
"phone_number": "+14155552671",
"country_code": "US",
"vendor_data": "lead-123",
"metadata": {"source": "signup_prescreen"},
},
timeout=15,
)
resp.raise_for_status()
result = resp.json()
print(result["status"]) # Approved / In Review / Declined
print(result["phone"]["phone_intelligence"]["score"])const res = await fetch('https://verification.didit.me/v3/phone/risk/', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone_number: '+14155552671',
country_code: 'US',
vendor_data: 'lead-123',
metadata: { source: 'signup_prescreen' },
}),
});
const data = await res.json();
console.log(data.status, data.phone.phone_intelligence?.score);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/phone/risk/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '+14155552671'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://verification.didit.me/v3/phone/risk/"
payload := strings.NewReader("{\n \"phone_number\": \"+14155552671\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://verification.didit.me/v3/phone/risk/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"phone_number\": \"+14155552671\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/phone/risk/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"phone_number\": \"+14155552671\"\n}"
response = http.request(request)
puts response.read_body{
"request_id": "4fd09d2e-9bc9-4c4e-9c46-7f625ac0ab62",
"status": "Approved",
"phone": {
"status": "Approved",
"phone_number_prefix": "+1",
"phone_number": "4155552671",
"full_number": "+14155552671",
"country_code": "US",
"country_name": "United States",
"carrier": {
"name": "Example Mobile",
"type": "mobile"
},
"is_disposable": false,
"is_virtual": false,
"verification_method": null,
"verification_attempts": 0,
"verified_at": null,
"warnings": [],
"lifecycle": [],
"matches": [],
"phone_intelligence": {
"score": 3,
"phone_type_risk": "Low",
"phone_trust_index": 97,
"network_stability_index": 95,
"is_disposable": false,
"is_ported": false,
"is_recently_ported": false,
"carrier_type": "mobile",
"reason_codes": []
},
"enrichment": {
"score": 3,
"phone_type_risk": "Low",
"phone_trust_index": 97,
"network_stability_index": 95,
"is_disposable": false,
"is_ported": false,
"is_recently_ported": false,
"carrier_type": "mobile",
"reason_codes": []
}
},
"vendor_data": "lead-123",
"metadata": {
"source": "signup_prescreen"
},
"created_at": "2026-09-01T10:30:00.123456+00:00"
}Phone Risk API
Risk-score a phone number without sending an OTP. Carrier, line type, porting, disposable-number, and fraud signals in one server-to-server call.
curl -X POST https://verification.didit.me/v3/phone/risk/ \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"phone_number": "+14155552671",
"country_code": "US",
"vendor_data": "lead-123",
"metadata": {"source": "signup_prescreen"}
}'import os, requests
resp = requests.post(
"https://verification.didit.me/v3/phone/risk/",
headers={"x-api-key": os.environ["DIDIT_API_KEY"], "Content-Type": "application/json"},
json={
"phone_number": "+14155552671",
"country_code": "US",
"vendor_data": "lead-123",
"metadata": {"source": "signup_prescreen"},
},
timeout=15,
)
resp.raise_for_status()
result = resp.json()
print(result["status"]) # Approved / In Review / Declined
print(result["phone"]["phone_intelligence"]["score"])const res = await fetch('https://verification.didit.me/v3/phone/risk/', {
method: 'POST',
headers: {
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone_number: '+14155552671',
country_code: 'US',
vendor_data: 'lead-123',
metadata: { source: 'signup_prescreen' },
}),
});
const data = await res.json();
console.log(data.status, data.phone.phone_intelligence?.score);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/phone/risk/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'phone_number' => '+14155552671'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://verification.didit.me/v3/phone/risk/"
payload := strings.NewReader("{\n \"phone_number\": \"+14155552671\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://verification.didit.me/v3/phone/risk/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"phone_number\": \"+14155552671\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/phone/risk/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"phone_number\": \"+14155552671\"\n}"
response = http.request(request)
puts response.read_body{
"request_id": "4fd09d2e-9bc9-4c4e-9c46-7f625ac0ab62",
"status": "Approved",
"phone": {
"status": "Approved",
"phone_number_prefix": "+1",
"phone_number": "4155552671",
"full_number": "+14155552671",
"country_code": "US",
"country_name": "United States",
"carrier": {
"name": "Example Mobile",
"type": "mobile"
},
"is_disposable": false,
"is_virtual": false,
"verification_method": null,
"verification_attempts": 0,
"verified_at": null,
"warnings": [],
"lifecycle": [],
"matches": [],
"phone_intelligence": {
"score": 3,
"phone_type_risk": "Low",
"phone_trust_index": 97,
"network_stability_index": 95,
"is_disposable": false,
"is_ported": false,
"is_recently_ported": false,
"carrier_type": "mobile",
"reason_codes": []
},
"enrichment": {
"score": 3,
"phone_type_risk": "Low",
"phone_trust_index": 97,
"network_stability_index": 95,
"is_disposable": false,
"is_ported": false,
"is_recently_ported": false,
"carrier_type": "mobile",
"reason_codes": []
}
},
"vendor_data": "lead-123",
"metadata": {
"source": "signup_prescreen"
},
"created_at": "2026-09-01T10:30:00.123456+00:00"
}POST /v3/phone/risk/ when you need phone intelligence before, instead of, or outside an OTP flow.
It does not send a code to the user. It creates an API session, enriches the number, applies your phone-risk rules, and returns the same normalized phone block used by Phone Verification in one synchronous response.
When the request is saved, Didit can also use the scored phone number as aggregate evidence in Networks. Network graphs may show high-risk phone intelligence, porting and line-type context on shared phone signals, but they do not reveal the raw phone number to other organizations.
Interpret the response
statusis the final decision for this API session. It is normallyApproved; the risk evaluation can produceIn RevieworDeclined.phone.full_numberis the normalized E.164 number.phone.phone_number_prefixandphone.phone_numbersplit it into the international prefix and national number.phone.is_disposableandphone.is_virtualare the stable yes/no signals for application logic. The carrier lookup addscarrier.nameandcarrier.type(mobile,voip, and similar).phone.phone_intelligence.scoreuses a 0-100 risk scale where a higher number means higher risk.phone_type_risk(Low,Medium,High) andphone_trust_index(inverse of the score) are derived views.phone.phone_intelligenceandphone.enrichmentare compatibility aliases with the same normalized object. New integrations can readphone.enrichment.phone.matcheslists other sessions of your application where the same number was used by a different user. Use it for duplicate-account detection.request_idis the API session id. Store it withvendor_dataif you need to correlate the result with later webhooks or console activity.
phone.phone_intelligence and phone.enrichment are best-effort fields. A completed lookup can omit both when no usable intelligence data is returned for that number, country, or plan. Build rules on the stable normalized fields first and treat missing intelligence as “unknown”, not “safe”.Social footprint add-on
Setenable_social to true to add a phone_social block to the response under phone: the online platforms this phone number is registered on, grouped by category, with the summary counts and any profile details our data partners return.
phone.phone_social.profiles_registeredandphone.phone_social.profiles_checkedare the headline numbers: platforms where the phone number is confirmed registered, out of the platforms evaluated.phone.phone_social.registered_platformsandphone.phone_social.not_registered_platformslist each platform with itscategoryandscope(global, orlocalfor region-specific platforms).phone.phone_social.categoriesgives the registered count and ratio per category, andphone.phone_social.profilescarries per-platform profile details when a platform exposes them (name, photo URL, about text, privacy status, business-account flag).- Summary indexes (
digital_footprint_diversity,digital_sophistication_index,engagement_depth_index,subscription_affordability_index) are 0-10 composites. Every count can benullwhen the check returned no data for it.
profiles_registered: 0 is a real answer, not a failure: the platforms were checked and the phone number was found on none of them, which is a common synthetic-identity signal. This endpoint does not act on it by itself - use phone_no_social_presence_action in a workflow to turn it into a Review or Decline verdict.
The block is absent when enable_social is not set, and also when the social check could not be completed - in which case it is not billed.
Sandbox behavior
Sandbox keys validate the request and return deterministic approved data. They do not send an OTP, consume credits, create a session, or contribute to Networks. Withenable_social set, they also return a deterministic phone_social block.
Billing
Phone Risk API calls use Phone Risk API pricing, lower than full Phone Verification because no OTP is sent. A live request is billable once the lookup starts, even when some best-effort fields are unavailable. The social footprint add-on is billed separately: onephone_social unit per request on top of the Phone Risk API price, whenever the check completes. The credit check before the lookup covers both.Authorizations
Body
Phone number to score. It is validated and normalized to E.164.
20"+14155552671"
Optional ISO 3166-1 alpha-2 or alpha-3 country hint for intelligence coverage.
3"US"
Optional device and network context observed by your application. All fields are optional. Passing them feeds cross-session match detection in Networks.
Show child attributes
Show child attributes
Your stable reference for this request. Stored on the API session and echoed in the response.
Your non-sensitive JSON metadata. Stored on the API session and echoed in the response.
When true, also look up the social footprint of the number - the messaging, social, e-commerce and professional platforms it is registered on. Billed as one phone_social unit per request in addition to this endpoint's own price.
true
Response
The risk evaluation completed. Inspect status for the decision; HTTP is always 200 for completed lookups.
Id of the API session created for this request. Store it with vendor_data if you need to correlate the result with later webhooks or console activity.
Final decision for this API session. Normally Approved; the risk evaluation can produce In Review or Declined.
Approved, In Review, Declined Timestamp of this response.
Echo of the vendor_data you sent, null when you did not send one.
Echo of the metadata you sent, null when you did not send one.
Normalized phone report, the same block used by Phone Verification responses.
Show child attributes
Show child attributes