Events API
Intégrez cside Device Intelligence dans votre application. Collectez les signaux du navigateur, générez des tokens de session et récupérez des informations détaillées sur les visiteurs depuis votre backend.
Ce guide vous accompagne dans l’intégration de l’Events API de cside Device Intelligence de bout en bout : chargement du script client, génération d’un token de session, envoi au backend et interprétation de la réponse.
Flux d’intégration
Ajoutez le script à votre page
Si votre app est construite avec un bundler, installez le package NPM et appelez initDeviceIntelligence({ teamID }) aussi tôt que votre app le permet. Sinon, incluez le bootstrap navigateur tolérant aux pannes en haut du <head>, avant les autres scripts, et remplacez sa valeur script.src par l’URL de votre équipe depuis le tableau de bord cside. Le bootstrap charge client.js de manière asynchrone, met en file les appels précoces et les rejette si cside échoue ou expire, afin que la page reste utilisable.
Envoyez la télémétrie et recevez un token de session
Une fois le script chargé, la fonction globale sendClientTelemetry devient disponible (le package NPM renvoie la même fonction depuis initDeviceIntelligence). Charger le script ne crée pas de fingerprint de session tout seul. Appelez sendClientTelemetry(externalIds?) pour envoyer la télémétrie vers https://edge.csidefd.com/client et recevoir un token de session. Passez un objet externalIds facultatif si vous voulez attacher vos propres identifiants.
const result = await sendClientTelemetry({
email: "user@example.com",
userId: "1234567890",
});
// Ou appelez-la sans arguments
// const result = await sendClientTelemetry();
if (result.errors) {
console.error(result.errors);
throw new Error("La requête de télémétrie a échoué.");
}
const token = result.token;Paramètres
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
externalIds | Record<string, string> | Non | Identifiants facultatifs que vous souhaitez attacher au fingerprint, comme userId, orderId, paymentCardId ou email. |
Pour recevoir le signal d’e-mail jetable (fingerprint_enrichment.throwaway_email_detected sur /token/v2/verify), transmettez l’adresse e-mail dans cet objet avec la clé email. Les règles de compte et l’Identity graph s’appuient sur userId (l’Identity graph accepte aussi teamId ou customerId), et la règle de test de cartes s’appuie sur paymentCardId ; consultez Récupérer les datapoints pour le format.
Valeur de retour
La fonction renvoie un objet JSON (déjà analysé, vous n’avez donc pas besoin d’appeler .json() dessus) :
{
"token": "eyJhbGciOiJIUzI1NiIs..."
}Le champ token contient le token de session de fingerprint. Si la collecte de la télémétrie rencontre des problèmes, l’objet inclut également un tableau facultatif errors que vous pouvez journaliser ; avec le package NPM, sendClientTelemetry n’est jamais rejeté et se résout plutôt avec { token: null, errors }. Extrayez result.token et envoyez uniquement cette chaîne de token de session à votre backend.
Récupérez les données de fingerprint depuis votre backend
Générez une clé API de Device Intelligence réservée au backend dans le dashboard cside, stockez-la comme secret côté serveur, puis utilisez-la pour échanger le token de session avec cside. La clé API est affichée une seule fois et ne doit pas être exposée dans le code navigateur.
if (!token) {
throw new Error("Le token de session de fingerprint n'a pas été renvoyé.");
}
const response = await fetch("https://api.cside.com/token/v2/verify", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CSIDE_FINGERPRINT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ token }),
});
const data = await response.json();Corps de la requête
Envoyez du JSON au format { "token": "<token de session>" }, où la valeur est result.token de l’étape précédente. Seuls les endpoints /token/v2/* acceptent du JSON ; les endpoints /token/v1/* prennent le token de session brut dans un body text/plain.
Options de lookup du token
Utilisez l’endpoint authentifié pour les échanges server-to-server de production. Les endpoints publics restent disponibles lorsqu’une intégration a spécifiquement besoin du flux de lookup non authentifié.
| Endpoint | Auth | Body de la requête | À utiliser lorsque |
|---|---|---|---|
/token/v2/verify | Clé API | JSON { "token" } | Vous avez besoin d’une récupération backend authentifiée avec une clé API de Device Intelligence. |
/token/v2/device/entries | Clé API | JSON { "token", "limit", "offset" } | Vous avez besoin des évaluations terminées pour le même ID d’appareil qu’un token de session. |
/token/v1/client | Aucune | Token brut, text/plain | Vous avez besoin du payload public de réponse de fingerprinting. |
/token/v1/clientId | Aucune | Token brut, text/plain | Vous avez seulement besoin de l’ID stable de fingerprint depuis le flux de lookup public. |
Chaque endpoint renvoie 202 Accepted avec { "status": "pending" } tant que l’évaluation est en cours de traitement, puis 200 OK une fois terminée. /token/v2/device/entries accepte { "token": "...", "limit": 100, "offset": 0 } et renvoie { "device_id": "...", "entries": [...], "next_offset": 100, "has_more": true }, où chaque entrée utilise la forme de réponse de /token/v2/verify. limit est facultatif, vaut 500 par défaut et est limité à 500. /token/v1/clientId renvoie du JSON { "status": "completed", "device_id": "..." }. Si aucun ID de fingerprint n’existe pour le token de session, il renvoie 404.
Erreurs et limites de débit
Les réponses d’erreur portent un body JSON { "error": "<message>", "code": <statut HTTP> } :
| Statut | Signification |
|---|---|
400 | Body mal formé, ou token de session impossible à décoder. |
401 | Clé API manquante ou invalide, token expiré, ou token émis pour une autre équipe que celle de la clé API. |
404 | Aucune évaluation n’existe pour le token (token not found), ou, sur /token/v1/clientId, aucun ID de fingerprint (fingerprint id not found). |
429 | Limite de débit dépassée. La réponse porte un header retry-after: 60. La limite par défaut est de 1 000 requêtes par minute et par équipe. |
Une évaluation terminée qui a échoué n’est pas une erreur HTTP : elle renvoie 200 OK avec "status": "failed" et un champ error_message. Vérifiez status avant de lire les champs d’enrichissement.
Exemple de requête backend
const csideResponse = await fetch("https://api.cside.com/token/v2/verify", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CSIDE_FINGERPRINT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ token }),
});
const data = await csideResponse.json();Interprétez la réponse du backend
Votre backend renvoie une réponse JSON contenant le résultat d’identification et les signaux associés. Consultez la référence complète de la réponse ci-dessous.
Réponse de /token/v2/verify
L’endpoint authentifié renvoie un payload JSON plat. Chaque entrée de /token/v2/device/entries utilise la même forme.
| Champ | Type | Description |
|---|---|---|
status | string | pending, completed ou failed. Les champs d’enrichissement ne sont présents que lorsque le statut est completed. |
error_message | string | Raison de l’échec de l’évaluation. Présent uniquement lorsque status vaut failed. |
created_at | number | Horodatage Unix (millisecondes) de la création de l’évaluation. |
updated_at | number | Horodatage Unix (millisecondes) de la dernière mise à jour. |
fingerprint | object | Le fingerprint complet de l’appareil : signaux de navigateur, de matériel, de rendu, d’environnement et d’automatisation, plus les external_ids que vous avez attachés. Mêmes champs que l’objet fingerprint de l’export S3. |
network_client_metrics | object | Caractéristiques TCP et TLS de la connexion. |
geo_data | object | Géolocalisation au niveau de la ville pour l’IP du visiteur. |
ip_enrichment | object | Données d’ASN, de géo et de confidentialité (hosting, proxy, relay, tor, vpn, signaux de datacenter) pour l’IP du visiteur. |
vpn_evaluation | object | is_vpn, vpn_probability, vpn_confidence, reasons, features et context. |
bot | object | Le verdict bot : is_bot, bot_probability, bot_confidence, bot_agent_id, reasons, scores et seuils par modèle, et session_event_count. Consultez Détection d’agents IA. |
fingerprint_enrichment | object | Signaux dérivés du fingerprint. throwaway_email_detected vaut true lorsque l’identifiant externe email utilise un domaine jetable. |
rule_evaluations | object | Résultats des règles legacy (rules, policy_version). Vide sur les évaluations créées après le 27/08/2026 ; conservé dans la réponse pour que les anciens enregistrements restent décodables. |
rule_evaluations_v2 | object | Résultats du moteur de règles : un tableau values dont chaque élément enveloppe une evaluation avec rule_slug, rule_version, outcome, evaluated_as (live ou shadow), transition et evaluated_at. |
Les objets imbriqués correspondent à la structure d’un enregistrement de l’export S3, où chaque champ est documenté en détail.
rule_evaluations_v2
Le tableau ci-dessus résume ce champ. Il porte le résultat de chaque règle exécutée pour le domaine, imbriqué à trois niveaux de profondeur dans rule_evaluations_v2.values[].evaluation, et les valeurs sont des entiers plutôt que des chaînes, ce qui mérite d’être détaillé. Il ne fait pas partie du payload /token/v1/client documenté plus bas.
| Champ | Type | Description |
|---|---|---|
rule_slug | string | L’identifiant de la règle, par exemple "account_shared_detected". |
outcome | number | Le résultat de l’évaluation. Voir le tableau ci-dessous. |
evaluated_as | number | L’état du cycle de vie de la règle au moment de l’évaluation. Voir le tableau ci-dessous. |
transition | number | Indique si le résultat a changé lors de cette évaluation, indépendamment du résultat lui-même. 2 signifie inchangé depuis la dernière évaluation, 3 signifie qu’il a changé lors de celle-ci. Combiné à outcome: 1, un 3 signifie que la règle vient de commencer à matcher ; combiné à outcome: 2, cela signifie qu’elle vient d’arrêter de matcher. 1 n’est jamais produit. |
key.key_hash | string | Un hash de la valeur sur laquelle la règle s’est appuyée. C’est une chaîne JSON, pas un nombre, elle survit donc à JSON.parse sans perte de précision. Elle ne porte pas l’id de compte lui-même. |
event_time, evaluated_at | object | { seconds, nanos }, contrairement aux champs racine created_at et updated_at de la réponse, qui sont des horodatages en millisecondes. |
outcome et evaluated_as sont des entiers bruts, pas des chaînes :
outcome | Signification | Quand vous l’observerez |
|---|---|---|
0 | Non spécifié | Jamais produit |
1 | Vrai | En continu, à chaque évaluation tant que la condition est vraie |
2 | Faux | En continu, à chaque évaluation tant qu’elle ne l’est pas. C’est l’état stable d’une règle saine qui ne matche pas, pas une transition rare |
3 | Absent (structurel) | En continu, à chaque évaluation où la règle ne peut pas lire le champ dont elle a besoin, par exemple une mauvaise clé d’id externe. Persistant, pas un incident ponctuel |
4 | En attente (transitoire) | Lorsqu’une mesure requise existe mais n’est pas encore prête. Distinct d’un status racine à pending : réinterroger le même token ne le résoudra pas, mais une évaluation ultérieure de la même entité peut renvoyer 1 ou 2 |
evaluated_as | Signification |
|---|---|
1 | Brouillon |
2 | Shadow (une expérience ; peut apparaître à tout moment) |
3 | Active |
4 | Archivée |
Chaque règle évaluée et publiée rapporte une entrée à chaque événement, quel que soit le résultat. rule_evaluations_v2 est un registre de ce qui a été évalué, pas un flux de notifications, donc outcome: 2 (faux) et outcome: 3 (absent) ne sont pas masqués : ils voyagent dans le tableau tout aussi fiablement que outcome: 1. transition est ce qui vous indique si ce résultat a changé depuis l’évaluation précédente.
Une entrée absente pour un rule_slug donné signifie que la règle n’a pas été évaluée du tout : elle n’est pas activée pour le domaine, il s’agit d’une règle de mesure seule qui ne publie pas, ou l’évaluation n’a pas tourné pour cet événement. Cela ne signifie pas “évaluée à faux”, ce cas correspond à outcome: 2, présent dans le tableau comme tout le reste. Consultez Détecter le partage de compte pour un exemple complet qui lit ce champ de bout en bout.
Référence de la réponse de /token/v1/client
Cette référence s’applique à l’endpoint public /token/v1/client. C’est une vue plus ancienne et plus plate de la même évaluation. Beaucoup de ses champs sont des valeurs fixes conservées pour la rétrocompatibilité ; l’encadré ci-dessous les liste. Pour les nouvelles intégrations, préférez /token/v2/verify.
Ces champs sont présents dans chaque réponse mais ne sont jamais calculés :
identification.confidenceetsupplementary_id_high_recall.confidencevalent toujours{ "score": 0.0, "version": "unknown" }identification.visitor_foundvaut toujoursfalse;first_seen_atetlast_seen_atsont égaux autimestampde l’événementproximityvaut toujours{ "id": "unknown", "precision_radius": 0, "confidence": 0.0 }client_referrervaut toujours"unknown"ip_blocklist.email_spametip_blocklist.attack_sourcevalent toujoursfalse(seultor_nodeest renseigné)raw_device_attributes.mathvaut toujours"unknown"
Ne construisez pas de logique de détection ou de fraude dessus.
Champs de niveau supérieur
| Champ | Type | Description |
|---|---|---|
linked_id | string | L’ID de session du navigateur, ou l’ID de l’événement lorsqu’aucun ID de session n’a été capturé. Ce n’est pas un identifiant que vous avez fourni ; vos externalIds apparaissent sous tags en tant que external_id:<clé>. |
tags | object | Une map de diagnostic cside, pas des métadonnées client : domain_id, team_id, request_id, session_id, fingerprint_match, network_match, des indicateurs de prise en charge des détections comme incognito_support, et vos externalIds sous forme d’entrées external_id:<clé>. |
timestamp | number | Horodatage Unix (millisecondes) de l’événement. |
event_id | string | Identifiant unique pour cet événement de fingerprinting. |
url | string | L’URL de la page où le fingerprint a été collecté. |
ip_address | string | L’adresse IP du visiteur. |
user_agent | string | La chaîne User-Agent brute du navigateur du visiteur. |
client_referrer | string | Toujours "unknown". |
status | string | completed ou failed. |
error_message | string | Présent lorsque status vaut failed. |
domain_id, team_id, session_id, request_id | string | Métadonnées d’évaluation copiées depuis l’enregistrement interne. |
created_at | string | Heure de l’évaluation sous forme de chaîne RFC 3339 (contrairement à /token/v2/verify, qui utilise des millisecondes). |
La réponse contient aussi les objets network_client_metrics, vpn_evaluation, proxy_details, tampering_details, tampering_anomaly_score, velocity et sdk. Les compteurs de velocity sont dérivés du seul événement courant (sa fenêtre events.24_hours est la seule valeur historique) ; sdk indique platform: "js" avec version: "unknown". Ils figurent dans l’exemple complet mais ne font pas partie du contrat stable.
browser_details
Détails sur le navigateur et le système d’exploitation du visiteur.
| Champ | Type | Description |
|---|---|---|
browser_name | string | Nom du navigateur (par exemple "Chrome"). |
browser_major_version | string | Numéro de version majeure. |
browser_full_version | string | Chaîne de version complète. |
os | string | Nom du système d’exploitation. |
os_version | string | Version du système d’exploitation. |
device | string | Type d’appareil (par exemple "Other", "Mobile"). |
identification
Le résultat d’identification principal du visiteur.
| Champ | Type | Description |
|---|---|---|
visitor_id | string | L’ID d’appareil stable de ce visiteur. C’est le seul champ calculé de l’objet. |
confidence.score | number | Toujours 0.0. |
confidence.version | string | Toujours "unknown". |
visitor_found | boolean | Toujours false. |
first_seen_at | number | Toujours égal à timestamp. |
last_seen_at | number | Toujours égal à timestamp. |
supplementary_id_high_recall
Un identifiant secondaire dérivé de vos externalIds (en privilégiant userId, puis accountId) pour qu’un même compte puisse être relié entre plusieurs appareils. Il retombe sur l’ID d’appareil lorsqu’aucun identifiant externe n’a été attaché.
| Champ | Type | Description |
|---|---|---|
visitor_id | string | Hash de l’identifiant externe retenu, ou l’ID d’appareil lorsqu’aucun n’a été attaché. |
visitor_found | boolean | true lorsqu’un identifiant externe a été attaché, sinon false. |
confidence.score | number | Toujours 0.0. |
confidence.version | string | Toujours "unknown". |
first_seen_at | number | Toujours égal à timestamp. |
last_seen_at | number | Toujours égal à timestamp. |
proximity
Non renseigné. Vaut toujours { "id": "unknown", "precision_radius": 0, "confidence": 0.0 }. Utilisez geo_data et ip_enrichment sur /token/v2/verify pour la localisation.
ip_info
Informations sur l’adresse IP du visiteur.
| Champ | Type | Description |
|---|---|---|
v4.address | string | Adresse IPv4. |
v6.address | string | Adresse IPv6. |
ip_blocklist
Si l’IP du visiteur apparaît sur des listes de blocage connues.
| Champ | Type | Description |
|---|---|---|
email_spam | boolean | Non renseigné ; toujours false. |
attack_source | boolean | Non renseigné ; toujours false. |
tor_node | boolean | L’IP est un nœud de sortie Tor. |
Signaux de fraude et d’environnement
Signaux indiquant des attributs suspects ou notables du visiteur.
root_apps, emulator, jailbroken, frida, mitm_attack, replayed, high_activity_device, cloned_app, privacy_settings et location_spoofing sont presents dans la reponse mais ne sont jamais definis. Ils renvoient toujours false (factory_reset_timestamp vaut toujours 0).
Ne construisez pas de logique de detection ou de fraude dessus. Chacun est signale dans le tableau ci-dessous.
| Champ | Type | Description |
|---|---|---|
bot | string | Une simple chaîne dérivée uniquement du User-Agent : "detected" lorsqu’il contient bot, crawler, spider ou headless ; "unknown" lorsqu’aucun User-Agent n’a été capturé ; sinon "not_detected". Ce n’est pas le modèle de bot. Utilisez bot.is_bot sur /token/v2/verify pour le vrai verdict. Consultez Détection d’agents IA. |
root_apps | boolean | L’appareil a des applications root/superutilisateur installées. Non renseigne actuellement ; toujours false. |
emulator | boolean | L’appareil est un émulateur. Non renseigne actuellement ; toujours false. |
proxy | boolean | Le visiteur utilise un proxy, un relais ou une IP de datacenter. |
proxy_confidence | string | "low", "medium" ou "high" lorsque proxy vaut true ; "unknown" sinon. |
vpn | boolean | Le visiteur utilise un VPN. |
vpn_confidence | string | "low", "medium" ou "high" lorsque le modèle VPN s’est exécuté ; "unknown" sinon. |
vpn_origin_timezone | string | Fuseau horaire IANA indiqué par le navigateur. |
vpn_origin_country | string | Pays déduit de l’enrichissement de l’adresse IP, ou "unknown" s’il n’est pas disponible. |
vpn_methods | object | Signaux propres à chaque méthode de détection pour les VPN et le trafic anonymisé. Consultez la sous-section ci-dessous. |
incognito | boolean | Le navigateur est en mode incognito/privé. |
tampering | boolean | Les attributs du navigateur ont été falsifiés. |
jailbroken | boolean | L’appareil est jailbreaké. Non renseigne actuellement ; toujours false. |
frida | boolean | Toolkit d’instrumentation Frida détecté. Non renseigne actuellement ; toujours false. |
virtual_machine | boolean | Le visiteur s’exécute dans une machine virtuelle. |
developer_tools | boolean | Les outils de développement du navigateur sont ouverts. |
mitm_attack | boolean | Attaque man-in-the-middle détectée. Non renseigne actuellement ; toujours false. |
replayed | boolean | La requête est une répétition d’une requête précédente. Non renseigne actuellement ; toujours false. |
high_activity_device | boolean | Nombre inhabituellement élevé d’identifications depuis cet appareil. Non renseigne actuellement ; toujours false. |
Le signal d’e-mail jetable ne fait pas partie de cette réponse. Lisez plutôt fingerprint_enrichment.throwaway_email_detected depuis /token/v2/verify.
vpn_methods
vpn_methods contient les signaux propres à chaque méthode de détection liés aux VPN et au trafic anonymisé. Utilisez le champ de niveau supérieur vpn comme verdict global. Une méthode peut valoir true lorsque vpn vaut false, par exemple lorsque cside détecte un trafic de proxy ou de relais que le modèle VPN ne classe pas comme un VPN.
| Champ | Type | Description |
|---|---|---|
timezone_mismatch | boolean | Le fuseau horaire du navigateur ne correspond pas à la géolocalisation de l’adresse IP. |
public_vpn | boolean | L’adresse IP correspond à un VPN public connu ou à un signal de centre de données. |
auxiliary_mobile | boolean | Réservé à la détection spécifique aux appareils mobiles. Ce champ vaut actuellement false pour les événements collectés dans un navigateur. |
os_mismatch | boolean | Le système d’exploitation du navigateur ne correspond pas à la signature réseau. |
relay | boolean | cside a détecté un relais d’anonymisation, un proxy ou un trafic apparenté à un relais. |
Certains pipelines de données préfixent et aplatissent les champs imbriqués. Dans ces jeux de données, vpn_methods.relay peut apparaître sous la forme cside_fingerprint_vpn_methods_relay.
raw_device_attributes
Composants de bas niveau du fingerprint du navigateur.
| Champ | Type | Description |
|---|---|---|
math | string | Non renseigné ; toujours "unknown". |
vendor | string | Chaîne du fournisseur GPU/graphique. |
Exemple complet de réponse
Une réponse /token/v1/client terminée. Les objets imbriqués qui ne font pas partie du contrat stable (network_client_metrics, vpn_evaluation, velocity) sont abrégés.
{
"linked_id": "b3f1c9e2-4d7a-4b0e-9f1a-2c8d7e6f5a41",
"tags": {
"domain_id": "7371466449724252160",
"team_id": "7196353823991660544",
"request_id": "01J9ZK3Q8W",
"session_id": "b3f1c9e2-4d7a-4b0e-9f1a-2c8d7e6f5a41",
"fingerprint_match": "7371466449724252160",
"external_id:userId": "1234567890",
"incognito_support": "supported",
"developer_tools_support": "supported",
"virtual_machine_support": "heuristic",
"tor_support": "ipinfo_privacy",
"visit_summary_source": "recent_fingerprint.available"
},
"timestamp": 1708102555327,
"event_id": "289076244130249728",
"url": "http://www.example.com/login",
"ip_address": "61.127.217.15",
"user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ...",
"client_referrer": "unknown",
"browser_details": {
"browser_name": "Chrome",
"browser_major_version": "74",
"browser_full_version": "74.0.3729",
"os": "Windows",
"os_version": "7",
"device": "Other"
},
"identification": {
"visitor_id": "Ibk1527CUFmcnjLwIs4A9",
"confidence": { "score": 0.0, "version": "unknown" },
"visitor_found": false,
"first_seen_at": 1708102555327,
"last_seen_at": 1708102555327
},
"supplementary_id_high_recall": {
"visitor_id": "3HNey93AkBW6CRbxV6xP",
"visitor_found": true,
"confidence": { "score": 0.0, "version": "unknown" },
"first_seen_at": 1708102555327,
"last_seen_at": 1708102555327
},
"proximity": {
"id": "unknown",
"precision_radius": 0,
"confidence": 0.0
},
"bot": "not_detected",
"root_apps": false,
"emulator": false,
"ip_info": {
"v4": { "address": "94.142.239.124" },
"v6": { "address": "2001:db8:3333:4444:5555:6666:7777:8888" }
},
"ip_blocklist": {
"email_spam": false,
"attack_source": false,
"tor_node": false
},
"proxy": true,
"proxy_confidence": "low",
"proxy_details": {
"proxy_type": "datacenter",
"last_seen_at": 1708102555327,
"provider": "Example Hosting"
},
"vpn": false,
"vpn_confidence": "high",
"vpn_origin_timezone": "Europe/Amsterdam",
"vpn_origin_country": "NL",
"vpn_methods": {
"timezone_mismatch": false,
"public_vpn": true,
"auxiliary_mobile": false,
"os_mismatch": false,
"relay": true
},
"vpn_evaluation": { "is_vpn": false, "vpn_probability": 0.04, "vpn_confidence": 0.91 },
"incognito": false,
"tampering": false,
"tampering_anomaly_score": 0.0,
"tampering_anti_detect_browser": false,
"tampering_details": { "anomaly_score": 0.0, "anti_detect_browser": false },
"cloned_app": false,
"factory_reset_timestamp": 0,
"jailbroken": false,
"frida": false,
"privacy_settings": false,
"virtual_machine": false,
"location_spoofing": false,
"velocity": {
"distinct_ip": { "5_minutes": 1, "1_hour": 1, "24_hours": 1 },
"distinct_country": { "5_minutes": 0, "1_hour": 0, "24_hours": 0 },
"events": { "5_minutes": 1, "1_hour": 1, "24_hours": 3 },
"ip_events": { "5_minutes": 1, "1_hour": 1, "24_hours": 1 },
"distinct_ip_by_linked_id": { "5_minutes": 1, "1_hour": 1, "24_hours": 1 },
"distinct_visitor_id_by_linked_id": { "5_minutes": 1, "1_hour": 1, "24_hours": 1 }
},
"developer_tools": false,
"mitm_attack": false,
"sdk": { "platform": "js", "version": "unknown", "integrations": [] },
"replayed": false,
"high_activity_device": false,
"raw_device_attributes": {
"math": "unknown",
"vendor": "Google Inc."
},
"network_client_metrics": { "client_ip": "61.127.217.15", "tls_ja4": "t13d1516h2_8daaf6152771_b186095e22b6" },
"status": "completed",
"domain_id": "7371466449724252160",
"team_id": "7196353823991660544",
"session_id": "b3f1c9e2-4d7a-4b0e-9f1a-2c8d7e6f5a41",
"request_id": "01J9ZK3Q8W",
"created_at": "2024-02-16T17:35:55.327Z"
} Thanks for your feedback!