> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# API de risque IP : géolocalisation, VPN et datacenter

> Évaluez le risque d'une adresse IP avec la géolocalisation, le FAI, les signaux VPN/Tor, datacenter, menace et pays déclaré de Didit.

Utilisez `POST /v3/ip/risk/` lorsque votre backend dispose déjà d'une adresse IP et a besoin d'une décision de risque serveur à serveur.

La réponse comprend la géolocalisation, le propriétaire du réseau, les indicateurs VPN/Tor et de centre de données, les données de menace, ainsi que `country_mismatch` lorsque vous envoyez un pays déclaré.

## Interpréter la réponse

* `status` vaut `In Review` lorsque le pays résolu est en conflit avec `claimed_country`, ou lorsque l'adresse est associée à une infrastructure VPN, Tor ou de centre de données. Sinon, il vaut `Approved`.
* `ip.ip_country_code` contient le code pays résolu. Comparez les pays via `ip.country_mismatch` plutôt que de comparer vous-même les chaînes de pays brutes.
* `ip.latitude` et `ip.longitude` correspondent à une géolocalisation réseau approximative, et non à une localisation précise de l'appareil.
* `ip.is_vpn_or_tor`, `ip.is_data_center`, `ip.proxy_type` et `ip.threat` fournissent les éléments de risque réseau.
* `ip.asn_number`, `ip.asn_organization`, `ip.connection_type` et `ip.carrier` décrivent le réseau auquel appartient l'adresse.
* `request_id` est l'identifiant de session de l'API. Stockez-le avec `vendor_data` si vous devez corréler le résultat avec des webhooks ultérieurs ou une activité dans la console.

> [!NOTE]
>
> L'enrichissement IP est effectué dans la mesure du possible. Si aucune source d'enrichissement ne renvoie de données exploitables, l'endpoint renvoie une réponse approuvée avec `ip.ip_address: null`, `ip.country_mismatch: null` et un objet `ip.threat` vide. Certains champs d'enrichissement peuvent aussi valoir `null` lorsqu'ils sont indisponibles.

## Intelligence de l'appareil

L'API IP Risk est un endpoint strictement serveur à serveur. La collecte de l'empreinte de l'appareil ne peut pas être effectuée uniquement serveur à serveur, car un backend ne peut pas observer seul les signaux du navigateur ou de l'appareil. Pour les sessions de parcours hébergé et de SDK, Didit expose sur la réponse de session les champs d'appareil déjà collectés, notamment `device_fingerprint`, les détails de l'appareil et du navigateur, `user_agent`, les données brutes de l'appareil et les correspondances entre sessions.

## Comportement du sandbox

Les clés sandbox valident la requête et renvoient des données approuvées déterministes. Elles ne contactent pas de services externes d'intelligence, ne consomment pas de crédits, ne créent pas de session et ne contribuent pas à Networks.

## Facturation

Les appels à l'API IP Risk coûtent \$0.02 au tarif public. Une requête en production est facturable dès que la recherche démarre.


## OpenAPI

````yaml fr/openapi-25.json POST /v3/ip/risk/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API de vérification d'identité. Authentifiez-vous avec l'en-tête x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/ip/risk/:
    post:
      tags:
        - Standalone APIs
      summary: Calculer le score de risque d'une adresse IP
      description: >-
        Renvoie la géolocalisation, la propriété du réseau, les indicateurs
        VPN/Tor et centre de données, les données sur les menaces et
        `country_mismatch` pour une adresse IP fournie. L'endpoint crée une
        session d'API et renvoie son identifiant sous forme de `request_id`.


        **Décision.** `status` est `In Review` lorsque le pays résolu entre en
        conflit avec `claimed_country`, ou lorsque l'adresse est associée à une
        infrastructure VPN, Tor ou de centre de données. Sinon, il vaut
        `Approved`.


        **Au mieux.** L'enrichissement d'IP est fourni au mieux. Si aucune
        source d'enrichissement ne renvoie de données exploitables, l'endpoint
        renvoie une réponse approuvée avec `ip.ip_address: null`,
        `ip.country_mismatch: null` et un objet `ip.threat` vide.


        **Facturation.** Les appels en production utilisent les tarifs de l'IP
        Risk API. La requête est facturable dès que la recherche commence.


        **Sandbox.** Les clés de sandbox valident la requête et renvoient des
        données approuvées déterministes sans consommer de crédits, créer de
        session ni contribuer à Networks.


        **Authentification.** Envoyez la clé API de votre application dans
        `x-api-key`. Des identifiants manquants ou invalides renvoient `403` -
        cette API ne renvoie jamais `401`.


        **Limite de débit.** Budget d'écriture partagé de 300 requêtes par
        minute par clé API sur les endpoints POST/PATCH/DELETE (les créations de
        transactions et l'ingestion d'événements disposent d'un budget distinct
        de 600).
      operationId: post_v3ip_risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IPRiskRequest'
            examples:
              Minimal:
                summary: Évaluer une adresse avec les paramètres par défaut
                value:
                  ip_address: 8.8.8.8
              With claimed country:
                summary: Évaluer avec un pays déclaré pour la détection de discordance
                value:
                  ip_address: 8.8.8.8
                  claimed_country: ESP
                  user_agent: >-
                    Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
                    AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4
                    Safari/605.1.15
                  vendor_data: lead-123
      responses:
        '200':
          description: "L'évaluation du risque est terminée. Inspectez `status` pour connaître la décision\_; le code HTTP est toujours `200` pour les recherches terminées."
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IPRiskResponse'
              examples:
                Clean residential IP:
                  summary: Adresse résidentielle, le pays déclaré correspond
                  value:
                    request_id: 9a96ed2a-721e-4b86-8cbf-d61eda529279
                    status: Approved
                    ip:
                      status: Approved
                      ip_address: 192.0.2.10
                      ip_country: Spain
                      ip_country_code: ES
                      ip_state: Madrid
                      ip_city: Madrid
                      latitude: 40.4168
                      longitude: -3.7038
                      isp: Example Telecom
                      organization: Example Telecom SA
                      is_vpn_or_tor: false
                      is_data_center: false
                      time_zone: Europe/Madrid
                      time_zone_offset: '+0200'
                      asn_number: 3352
                      asn_organization: EXAMPLE-TELECOM
                      connection_type: broadband
                      carrier: Example Telecom
                      proxy_type: null
                      claimed_country: ESP
                      country_mismatch: false
                      threat: {}
                    vendor_data: lead-123
                    metadata: null
                    created_at: '2026-09-01T10:30:00.123456+00:00'
                Datacenter mismatch:
                  summary: Adresse du centre de données en conflit avec le pays déclaré
                  value:
                    request_id: 5b1d4e9a-3c7b-4f8e-9a2d-1b0c9d8e7f6a
                    status: In Review
                    ip:
                      status: In Review
                      ip_address: 8.8.8.8
                      ip_country: United States
                      ip_country_code: US
                      ip_state: California
                      ip_city: Mountain View
                      latitude: 37.386
                      longitude: -122.0838
                      isp: Google
                      organization: Google LLC
                      is_vpn_or_tor: true
                      is_data_center: true
                      time_zone: America/Los_Angeles
                      time_zone_offset: '-0700'
                      asn_number: 15169
                      asn_organization: GOOGLE, US
                      connection_type: hosting
                      carrier: null
                      proxy_type: VPN
                      claimed_country: ESP
                      country_mismatch: true
                      threat:
                        is_proxy: true
                        is_data_center: true
                        is_tor: false
                    vendor_data: lead-126
                    metadata: null
                    created_at: '2026-09-01T10:30:00.123456+00:00'
        '400':
          $ref: '#/components/responses/IPRiskValidationError'
        '403':
          $ref: '#/components/responses/RiskPermissionDenied'
        '429':
          $ref: '#/components/responses/RateLimitedWrite'
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X POST https://verification.didit.me/v3/ip/risk/ \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "ip_address": "8.8.8.8",
                "claimed_country": "ESP",
                "user_agent": "Mozilla/5.0",
                "vendor_data": "lead-123"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.ip.assess_risk(
                ip_address="8.8.8.8",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: |-
            import Didit from "@didit-protocol/sdk-node";

            // Reads DIDIT_API_KEY.
            const didit = new Didit();

            const result = await didit.ip.assessRisk({
              ip_address: "8.8.8.8",
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.IP.AssessRisk(ctx, didit.IPRiskRequest{\n\tIPAddress: \"8.8.8.8\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: |-
            import me.didit.Didit;
            import me.didit.types.IPRiskRequest;

            // Reads DIDIT_API_KEY.
            Didit client = new Didit();

            var result = client.ip().assessRisk(IPRiskRequest.builder()
                    .ipAddress("8.8.8.8")
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: |-
            <?php

            require 'vendor/autoload.php';

            use Didit\DiditClient;

            // Reads DIDIT_API_KEY.
            $didit = new DiditClient();

            $result = $didit->ip->assessRisk([
                'ip_address' => '8.8.8.8',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Reads DIDIT_API_KEY.
            didit = Didit::Client.new

            result = didit.ip.assess_risk(ip_address: "8.8.8.8")
            puts result.to_h
        - lang: csharp
          label: .NET
          source: |-
            using System;
            using System.Text.Json;
            using Didit;

            // Reads DIDIT_API_KEY.
            using var client = new DiditClient();

            var result = await client.Ip.AssessRiskAsync(new IPRiskRequest
            {
                IpAddress = "8.8.8.8",
            });
            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    IPRiskRequest:
      type: object
      required:
        - ip_address
      properties:
        ip_address:
          type: string
          format: ip
          description: Adresse IPv4 ou IPv6 à évaluer.
          example: 8.8.8.8
        claimed_country:
          type: string
          maxLength: 3
          description: >-
            Pays ISO 3166-1 alpha-2 ou alpha-3 optionnel déclaré par
            l'utilisateur ou la session. Utilisé pour calculer
            `country_mismatch`.
          example: ESP
        user_agent:
          type: string
          maxLength: 512
          description: "Agent utilisateur observé par votre backend. Enregistré comme contexte de requête\_; il ne fournit pas d'empreinte d'appareil."
        vendor_data:
          type: string
          description: >-
            Votre référence stable pour cette requête. Enregistrée sur la
            session API et renvoyée dans la réponse.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Vos métadonnées JSON non sensibles. Enregistrées sur la session
            d'API et renvoyées dans la réponse.
    IPRiskResponse:
      type: object
      required:
        - request_id
        - status
        - created_at
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            Identifiant de la session d'API créée pour cette requête.
            Enregistrez-le avec `vendor_data` si vous devez faire correspondre
            le résultat avec des webhooks ultérieurs ou l'activité de la
            console.
        status:
          type: string
          enum:
            - Approved
            - In Review
          description: >-
            Décision pour cette session d'API : `In Review` en cas de risque lié
            au réseau ou de discordance de pays, sinon `Approved`.
        vendor_data:
          type: string
          nullable: true
          description: >-
            Écho des `vendor_data` que vous avez envoyées, `null` si vous n'en
            avez pas envoyé.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Écho des `metadata` que vous avez envoyées, `null` si vous n'en avez
            pas envoyé.
        created_at:
          type: string
          format: date-time
          description: Horodatage de cette réponse.
        ip:
          type: object
          description: >-
            Résultat du risque IP. Les champs d'enrichissement individuels
            peuvent être `null` lorsque la recherche n'a renvoyé aucune donnée
            exploitable.
          required:
            - status
            - threat
          properties:
            status:
              type: string
              enum:
                - Approved
                - In Review
              description: >-
                `In Review` lorsque le pays résolu est en conflit avec
                `claimed_country`, ou lorsque l'adresse est associée à une
                infrastructure VPN, Tor ou de centre de données. Sinon
                `Approved`.
            ip_address:
              type: string
              nullable: true
              description: >-
                L'adresse notée. `null` si aucune source d'enrichissement n'a
                renvoyé de données exploitables.
            ip_country:
              type: string
              nullable: true
              description: Nom du pays résolu.
            ip_country_code:
              type: string
              nullable: true
              description: >-
                Code pays résolu. Comparez les pays via `country_mismatch` au
                lieu de comparer vous-même les chaînes de pays brutes.
            ip_state:
              type: string
              nullable: true
              description: État ou région résolu.
            ip_city:
              type: string
              nullable: true
              description: Ville résolue.
            latitude:
              type: number
              nullable: true
              description: >-
                Géolocalisation réseau approximative, et non une localisation
                précise de l'appareil.
            longitude:
              type: number
              nullable: true
              description: >-
                Géolocalisation réseau approximative, et non une localisation
                précise de l'appareil.
            isp:
              type: string
              nullable: true
              description: Fournisseur d'accès à Internet desservant l'adresse.
            organization:
              type: string
              nullable: true
              description: Organisation propriétaire du bloc d'adresses.
            is_vpn_or_tor:
              type: boolean
              nullable: true
              description: >-
                `true` lorsque l'adresse est associée à une infrastructure VPN
                ou Tor.
            is_data_center:
              type: boolean
              nullable: true
              description: >-
                `true` lorsque l'adresse appartient à un réseau d'hébergement ou
                de centre de données.
            time_zone:
              type: string
              nullable: true
              description: Fuseau horaire de la localisation résolue.
            time_zone_offset:
              type: string
              nullable: true
              description: Décalage UTC de l'emplacement résolu.
            asn_number:
              type: number
              nullable: true
              description: Numéro de système autonome.
            asn_organization:
              type: string
              nullable: true
              description: Organisation exploitant le système autonome.
            connection_type:
              type: string
              nullable: true
              description: Classification de la connexion (par ex., `cellular`, `hosting`).
            carrier:
              type: string
              nullable: true
              description: Opérateur mobile lorsque l'adresse est sur un réseau mobile.
            proxy_type:
              type: string
              nullable: true
              description: >-
                Classification du proxy lorsque l'adresse se trouve derrière un
                proxy.
            claimed_country:
              type: string
              nullable: true
              description: Écho du `claimed_country` que vous avez envoyé.
            country_mismatch:
              type: boolean
              nullable: true
              description: >-
                `true` lorsque le pays résolu diffère de `claimed_country`.
                `null` lorsqu'aucune donnée d'enrichissement ou aucun pays
                revendiqué n'est disponible.
            threat:
              type: object
              additionalProperties: true
              description: >-
                Preuves de menaces réseau au format libre issues de la source
                d'enrichissement (par ex. `is_proxy`, `is_tor`). Objet vide
                lorsqu'aucune donnée d'enrichissement n'est disponible. À
                traiter comme un détail de diagnostic, et non comme un contrat
                stable.
  responses:
    IPRiskValidationError:
      description: Échec de la validation de la requête.
      content:
        application/json:
          examples:
            Missing IP address:
              summary: Adresse IP manquante
              value:
                ip_address:
                  - This field is required.
            Invalid IP address:
              summary: Adresse IP non valide
              value:
                ip_address:
                  - Enter a valid IPv4 or IPv6 address.
            Country hint too long:
              summary: Indication de pays trop longue
              value:
                claimed_country:
                  - Ensure this field has no more than 3 characters.
    RiskPermissionDenied:
      description: >-
        La clé API est manquante ou invalide, ou l'organisation ne peut pas
        couvrir la recherche en direct. Cette API ne renvoie jamais `401`.
      content:
        application/json:
          examples:
            Missing or invalid API key:
              summary: Aucun en-tête `x-api-key`, ou la clé est non valide ou révoquée
              value:
                detail: You do not have permission to perform this action.
            Not enough credits:
              summary: >-
                Le solde de l'organisation ne peut pas couvrir le prix de la
                recherche
              value:
                error: You don't have enough credits to perform this request.
    RateLimitedWrite:
      description: >-
        La limite d'écriture partagée de 300 requêtes par minute et par clé API
        a été dépassée. Respectez l'en-tête `Retry-After` avant de réessayer.
      content:
        application/json:
          schema:
            type: object
            required:
              - detail
            properties:
              detail:
                type: string
          example:
            detail: >-
              Write request rate limit exceeded. You can make up to 300 requests
              per minute.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        La clé API de votre application, issue de Développeurs -> Clés API dans
        la Business Console. La clé principale dispose d'un accès complet. Une
        clé nommée peut être restreinte : aucun, lecture ou écriture par
        ressource, limitée à certains workflows ou aux sessions approuvées, à
        une liste d'adresses IP et à une date d'expiration. 401 signifie que la
        clé est incorrecte, révoquée ou expirée ; 403 signifie qu'aucune clé n'a
        été envoyée, que la clé n'a pas accès à cette ressource ou action, ou
        que la requête provient d'une adresse hors de sa liste d'IP ; 404 sur
        une route de session signifie que la session est hors des workflows ou
        des statuts de la clé. Une clé sans accès aux médias reçoit les URL
        d'images, de vidéos et de PDF à null, et une clé sans accès en écriture
        aux sessions reçoit les liens et tokens de session à null. Voir
        https://docs.didit.me/console/api-keys.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.