Server API
Use Geelab Device Fingerprint v2 Server API to query device identification, device information and risk signals
Overview
Use the client SDK's device_token to query the device fingerprint and obtain device identification, device information, and risk signals.
Interface
| Method | Path | Purpose |
|---|---|---|
POST | /api/v2/fp_query/{public_key} | Query device fingerprint |
Where to get input from
| Field | Used in | Where to get |
|---|---|---|
public_key | Path /api/v2/fp_query/{public_key} | Public application identifier from the console, used to locate the application and Region. It is not an authentication key. |
secret | Authorization: Bearer <secret> | Server API authentication secret from the console. |
device_token | Request body | Client SDK interface. |
Supported clients
iOS, Android, and Web/H5.
Regional restrictions
Each application belongs to only one region and is configured by the background. The request must be sent to the node in the region where the application belongs.
| Region | Description |
|---|---|
GLB | Global |
NA | North America |
EU | Europe |
Requests sent to a node in another Region return 404 with message: "integration not found".
Response envelope
Use Content-Type: application/json. The HTTP status code and JSON code have the same value.
Success:
{ "code": 200, "data": {}, "message": "Success" }Failure:
{ "code": 400, "data": {}, "message": "Invalid request" }When validation fails, data contains:
{
"errors": [
{ "field": "device_token", "reason": "Field required", "type": "missing" }
]
}Error code
HTTP / code | message | Meaning |
|---|---|---|
| 400 | Invalid request | The request body is invalid, or device_token is invalid |
| 401 | Invalid bearer token | Authentication failed; check the server-side secret |
| 403 | Forbidden | The application is unavailable or does not pass the IP whitelist |
| 404 | integration not found | public_key is invalid, or the request did not reach the node for the application's Region |
| 500 | Internal server error | Server error |
POST /api/v2/fp_query/{public_key} Query the device fingerprint. Pass in the return from the client SDK device_token, obtain device identification, device information and risk signals.
| Method | POST |
| Path | /api/v2/fp_query/{public_key} |
| Auth | Authorization: Bearer <secret> |
| Content-Type | application/json |
| Success | HTTP 200, code=200, message=Success |
Request
http
POST /api/v2/fp_query/{public_key}
Authorization: Bearer <secret>
Content-Type: application/jsonPath
| Field | Type | Required | Meaning | Where to get |
|---|---|---|---|---|
public_key | string | yes | application public identifier | backend |
Headers
| Field | Required | Meaning | Where to get it |
|---|---|---|---|
Authorization | Yes | Bearer <secret>, server-side query authentication | secret: get from backend |
Content-Type | Yes | application/json | — |
Body
{
"device_token": "<from-client-sdk>",
"metadata": {
"account_id": "account-001",
"phone_num": "+8613800000000",
"phone_sha256": "opaque-hash-value",
"email": "[email protected]"
},
"event_type": "login",
"event_time": "2026-08-20T10:30:00+08:00"
}| Field | Type | Required | Meaning | Where to get |
|---|---|---|---|---|
device_token | string | Yes | Device credentials for this query | Client SDK interface |
metadata | object | No | Business side related information, see the table below | The caller fills in |
event_type | string | No | Business event type, such as login | Caller-provided |
event_time | string | No | Event time in RFC 3339 format (with a time zone or Z) | Caller-provided |
metadata
Both are optional strings.
| Field | Meaning |
|---|---|
account_id | Account ID |
phone_num | Clear text of mobile phone number |
phone_sha256 | Mobile phone number hash |
phone_country_code | Country Code |
phone_prefix | Number prefix |
email | Email plain text |
email_sha256 | Email Hash |
email_domain | Email domain name |
ip_addr_v4 | IPv4 |
ip_addr_v6 | IPv6 |
user_agent | User-Agent |
ja3 | JA3 |
ja4 | JA4 |
mac_prefix | MAC prefix |
wifi_bssid_prefix | Wi-Fi BSSID Prefix |
tls_cipher | TLS cipher |
Minimum request body:
{ "device_token": "<from-client-sdk>" }Response (200)
{
"code": 200,
"data": {
"request_id": "req_0198c7a1-5b2e-7c10-8d44-1234567890ab",
"event_id": "evt_0198c7a1-5b2e-7c10-8d44-1234567890ab",
"fp_detail": {
"device_id": "GEE4-xxxxxx",
"version": "1.0"
},
"signals": [
{
"signal": "CLOUD_PHONE",
"level": "HIGH",
"confidence": 0.8
}
],
"detail": {
"client_type": "Android",
"device_basic": {
"os": "Android",
"pla": "arm64-v8a",
"mod": "Pixel 8",
"osv": "14"
},
"ip_info": {
"ip": "1.1.1.1"
}
}
},
"message": "Success"
}data
| Field | Type | Meaning |
|---|---|---|
request_id | string | Identification request ID, formatted as req_ + UUID v7. Multiple queries with the same device_token have the same value. |
event_id | string | ID of this query, formatted as evt_ + UUID v7. Each query has a different value. |
fp_detail | object | Device fingerprint details |
signals | array | Hit signal list; [] when no signal is hit |
detail | object | Client type, device information, and IP information |
fp_detail
| Field | Type | Meaning |
|---|---|---|
device_id | string | device fingerprint |
version | string | Fingerprint version, currently"1.0" |
signals[]
| Field | Type | Meaning |
|---|---|---|
signal | string | signal identifier, for exampleCLOUD_PHONE |
level | string | LOW/MEDIUM/HIGH |
confidence | number | 0.0–1.0 |
See "Signals" below for the values and descriptions of each signal.
detail
| Field | Type | Meaning |
|---|---|---|
client_type | string | Android, iOS, or Web/H5 |
device_basic | object | Basic device information; its structure varies by client_type |
ip_info | object | { "ip": "<string>" } |
Android/iOS device_basic:
{
"os": "Android",
"pla": "arm64-v8a",
"mod": "Pixel 8",
"osv": "14"
}| Field | Meaning |
|---|---|
os | Operating system |
pla | Architecture |
mod | Model |
osv | System version |
Web/H5device_basic:
{
"browser": { "name": "Chrome", "version": "145.0.0.0", "major": "145" },
"device": { "model": "Macintosh", "vendor": "Apple" },
"os": { "name": "macOS", "version": "10.15.7" }
}Error
The HTTP status code equals code. message is the exact string shown in the table below.
| HTTP | message | data | Meaning |
|---|---|---|---|
| 400 | Invalid request | { "errors": [ { "field", "reason", "type" } ] } | Missing field, wrong type, or invalid event_time |
| 400 | Invalid request | { "errors": [{ "field": "device_token", "reason": "Invalid token", "type": "value_error" }] } | device_token is invalid |
| 401 | Invalid bearer token | {} | Authentication failed |
| 403 | Forbidden | {} | The application is unavailable or does not pass the IP whitelist |
| 404 | integration not found | {} | public_key is invalid, or the request did not reach the node for the application's Region |
| 500 | Internal server error | {} | Server error |
{
"code": 400,
"data": {
"errors": [
{ "field": "device_token", "reason": "Field required", "type": "missing" }
]
},
"message": "Invalid request"
}{
"code": 401,
"data": {},
"message": "Invalid bearer token"
}Example
Copy {public_key} and {secret} from the console. Get {device_token} from the client SDK, and send the request to the node for the application's Region.
curl -sS -X POST "https://{host}/api/v2/fp_query/{public_key}" \
-H "Authorization: Bearer {secret}" \
-H "Content-Type: application/json" \
-d '{
"device_token": "{device_token}",
"metadata": { "account_id": "account-001" },
"event_type": "login",
"event_time": "2026-08-20T10:30:00+08:00"
}'Signal
In a successful fp_query response, the signal list is in data.signals[]. When no signal is hit, the array is [].
| Field | Type | Meaning |
|---|---|---|
signal | string | signal identifier, for exampleCLOUD_PHONE |
level | string | LOW/MEDIUM/HIGH |
confidence | number | 0.0–1.0 |
Signal List (51)
signal | level | confidence | Description |
|---|---|---|---|
BEING_DEBUGGED | HIGH | 1 | The device has the risk of being debugged, and reverse analysis, cracking, and group control automation can be performed |
DEBUG_MODE_OR_TEST_APP | LOW | 1 | The device has debug mode turned on or a debug/cracked version of an application package not downloaded from the store is used |
EMULATOR | HIGH | 0.95 | Legacy emulator risk detected |
CLOUD_PHONE | HIGH | 0.8 | Cloud phone (or ARM server) risk detected |
RUNNING_ON_MACOS | MEDIUM | 1 | Risks detected when running apps on Mac |
VPN_ENABLED | LOW | 1 | The device is turning on VPN |
NETWORK_PROXY | MEDIUM | 1 | The device is turning on the network proxy |
INVALID_PACKAGE | LOW | 1 | Package name tampering or repackaging detected |
TOKEN_EXPIRED | MEDIUM | 0.9 | device_token is expired or reused |
LIMIT_EXCEED | MEDIUM | 1 | Limit exceeded |
SCREEN_SHARING | LOW | 1 | The device is sharing screen |
VOICE_CONNECTED | LOW | 1 | The device is in a voice call |
WHITELIST_ACCOUNT_ID | HIGH | 1 | User account blacklist |
WHITELIST_IP | HIGH | 1 | IP Blacklist |
WHITELIST_DEVICE_FINGERPRINT | HIGH | 1 | Device fingerprint blacklist |
IP_CRAWLER_OR_BOT | MEDIUM | 0.8 | The IP has malicious cracking or crawling behavior |
IP_MALICIOUS_ATTACK | HIGH | 0.6 | IP has malicious attacks |
IP_SUSPICIOUS_PROXY | MEDIUM | 0.8 | IP suspected proxy IP |
BLACKLIST_ACCOUNT_ID | LOW | 1 | User account whitelist |
BLACKLIST_IP | LOW | 1 | IP whitelist |
BLACKLIST_DEVICE_FINGERPRINT | LOW | 1 | Device fingerprint whitelist |
DEVICE_JAILBREAK | HIGH | 1 | iOS devices are jailbroken |
DEVICE_ROOTED | HIGH | 1 | Android devices have root behavior |
SUSPICIOUS_CUSTOM_ROM | HIGH | 0.8 | Android devices using questionable custom ROMs |
SUSPICIOUS_OPEN_SOURCE_ROM | HIGH | 0.9 | Android Device ROM for Android Open Source Project |
BROWSER_COOKIE_FEATURE_DISABLED | MEDIUM | 0.9 | Browser cookie not available |
PSEUDO_BROWSER_ENV | HIGH | 0.9 | Fake browser environment |
BROWSER_INCOGNITO_MODE | LOW | 0.8 | Browser in incognito mode |
DEVICE_BOOTLOADER_UNLOCKED | HIGH | 0.8 | Device bootloader detected and unlocked |
SUSPICIOUS_DEVICE_RESET | HIGH | 0.8 | Suspected device reset |
SYSTEM_VERSION_TOO_LOW | MEDIUM | 0.6 | The device system version is too low |
DEVICE_WITHOUT_SIM | LOW | 0.4 | No SIM card is detected in the device |
HOOK_TAMPERING_LOW | MEDIUM | 1 | The device has a low risk of code tampering. Using this label requires excluding self-development and tampering |
HOOK_TAMPERING_MEDIUM | HIGH | 1 | The device is at risk of code tampering, and the code logic can be tampered with |
HOOK_TAMPERING_HIGH | HIGH | 1 | The device has a high risk of code tampering |
SUSPICIOUS_DEVICE_INFO_TAMPERED | HIGH | 0.8 | The device has the risk of information forgery, and device attributes or fingerprints do not match |
ANTIDETECT_BROWSER | HIGH | 0.8 | Device is running an anti-detection browser |
APP_CLONE_TOOL_INSTALLED | LOW | 1 | There is a risk of installing multiple tools on the device |
TAMPER_TOOL_INSTALLED | LOW | 1 | The risk of detecting that the device has modification tools installed |
AUTOMATION_TOOL_INSTALLED | LOW | 1 | The risk of group control/automation tools installed on the device is detected, which can enable large-scale black production operations |
REVERSE_ENGINEERING_TOOL_INSTALLED | LOW | 1 | Risk of device installation reverse tool detected |
NETWORK_TAMPER_TOOL_INSTALLED | LOW | 1 | The device is at risk of using network tampering tools |
GAME_TAMPER_TOOL_INSTALLED | LOW | 1 | The device is at risk of using game modifier tools |
VIRTUAL_LOCATION_TOOL_INSTALLED | LOW | 1 | Detected that the device has a virtual positioning risk installed |
RUNNING_IN_VIRTUAL_MACHINE | HIGH | 1 | The current device is in a virtual machine environment |
RUNNING_IN_CLONED_APP | HIGH | 1 | Currently in a multi-open environment |
USING_DEVICE_TAMPERING_TOOL | HIGH | 1 | Currently using modified or risky tools |
USING_AUTOMATION_TOOL | HIGH | 0.95 | Currently using group control or automation tools |
USING_REVERSE_ENGINEERING_TOOL | HIGH | 1 | Currently using reverse tampering tools |
USING_VIRTUAL_LOCATION | HIGH | 1 | Currently using the virtual positioning tool |
RUNNING_IN_SYSTEM_CLONED | LOW | 0.9 | Risk of over-opening of device and systems |
OpenAPI 3.1
When you need to generate a client or request a validator, you can download the [Device Fingerprint v2 OpenAPI 3.1 description file](/openapi/device-fingerprint-v2. yaml).