> ## 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 Rischio IP: Geolocalizzazione, VPN e Datacenter

> Didit: punteggio di rischio per indirizzo IP con geolocalizzazione, ISP, segnali VPN/Tor e datacenter, minacce e incongruenze del paese dichiarato.

Usa `POST /v3/ip/risk/` quando il tuo backend dispone già di un indirizzo IP e ha bisogno di una decisione sul rischio server-to-server.

La risposta include geolocalizzazione, proprietà della rete, indicatori VPN/Tor e data center, dati sulle minacce e `country_mismatch` quando invii un paese dichiarato.

## Interpreta la risposta

* `status` è `In Review` quando il paese risolto è in conflitto con `claimed_country`, oppure quando l'indirizzo è associato a infrastrutture VPN, Tor o data center. Altrimenti è `Approved`.
* `ip.ip_country_code` contiene il codice del paese risolto. Per confrontare i paesi usa `ip.country_mismatch` invece di confrontare tu stesso le stringhe dei paesi.
* `ip.latitude` e `ip.longitude` sono una geolocalizzazione di rete approssimativa, non la posizione precisa del dispositivo.
* `ip.is_vpn_or_tor`, `ip.is_data_center`, `ip.proxy_type` e `ip.threat` contengono gli elementi di rischio della rete.
* `ip.asn_number`, `ip.asn_organization`, `ip.connection_type` e `ip.carrier` descrivono la rete a cui appartiene l'indirizzo.
* `request_id` è l'ID della sessione API. Salvalo in `vendor_data` se ti serve correlare il risultato con webhook successivi o con l'attività nella console.

> [!NOTE]
>
> L'arricchimento IP è di tipo best effort. Se nessuna fonte di arricchimento restituisce dati utilizzabili, l'endpoint restituisce una risposta approvata con `ip.ip_address: null`, `ip.country_mismatch: null` e un oggetto `ip.threat` vuoto. Anche i singoli campi di arricchimento possono essere `null` quando non sono disponibili.

## Informazioni sul dispositivo

L'API IP Risk è un endpoint puramente server-to-server. Il fingerprinting del dispositivo non lo è, perché un backend da solo non può osservare i segnali del browser o del dispositivo. Per le sessioni dei flussi ospitati e degli SDK, Didit espone sulla risposta della sessione i campi del dispositivo già raccolti, tra cui `device_fingerprint`, i dettagli del dispositivo e del browser, `user_agent`, i dati grezzi del dispositivo e le corrispondenze tra sessioni diverse.

## Comportamento in sandbox

Le chiavi sandbox convalidano la richiesta e restituiscono dati approvati deterministici. Non contattano servizi esterni di analisi, non consumano crediti, non creano una sessione e non contribuiscono a Networks.

## Fatturazione

Ogni chiamata all'API IP Risk costa \$0.02 al prezzo di listino. Una richiesta in ambiente di produzione è fatturabile nel momento in cui inizia la ricerca.


## OpenAPI

````yaml it/openapi-25.json POST /v3/ip/risk/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API di verifica dell'identità. Autenticati con l'intestazione x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/ip/risk/:
    post:
      tags:
        - Standalone APIs
      summary: Calcola il punteggio di rischio di un indirizzo
      description: >-
        Restituisce geolocalizzazione, assetto proprietario della rete, flag
        VPN/Tor e data center, dati sulle minacce e `country_mismatch` per
        l'indirizzo IP fornito. L'endpoint crea una sessione API e restituisce
        il suo id come `request_id`.


        **Decisione.** Il valore di `status` è `In Review` quando il paese
        individuato è in conflitto con `claimed_country`, oppure quando
        l'indirizzo è associato a un'infrastruttura VPN, Tor o data center.
        Altrimenti è `Approved`.


        **Con ogni ragionevole sforzo.** L'arricchimento dell'IP viene eseguito
        con ogni ragionevole sforzo. Se nessuna fonte di arricchimento
        restituisce dati utilizzabili, l'endpoint restituisce una risposta
        approvata con `ip.ip_address: null`, `ip.country_mismatch: null` e un
        oggetto `ip.threat` vuoto.


        **Fatturazione.** Le chiamate in produzione utilizzano i prezzi dell'API
        IP Risk. La richiesta è fatturabile a partire dall'avvio della ricerca.


        **Sandbox.** Le chiavi sandbox convalidano la richiesta e restituiscono
        dati approvati deterministici senza consumare crediti, creare una
        sessione o contribuire a Networks.


        **Autenticazione.** Invia la chiave API della tua applicazione
        nell'intestazione `x-api-key`. Credenziali mancanti o non valide
        restituiscono `403`: questa API non restituisce mai `401`.


        **Limite di frequenza.** Budget di scrittura condiviso di 300 richieste
        al minuto per chiave API su tutti gli endpoint POST/PATCH/DELETE (la
        creazione di transazioni e l'ingestione di eventi hanno un budget
        separato di 600).
      operationId: post_v3ip_risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IPRiskRequest'
            examples:
              Minimal:
                summary: Calcola il punteggio di un indirizzo con i valori predefiniti
                value:
                  ip_address: 8.8.8.8
              With claimed country:
                summary: >-
                  Calcola il punteggio con un paese dichiarato per il
                  rilevamento di discrepanze
                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: >-
            La valutazione del rischio è completata. Ispeziona `status` per la
            decisione; il codice HTTP è sempre `200` per le ricerche completate.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IPRiskResponse'
              examples:
                Clean residential IP:
                  summary: Indirizzo di residenza, il paese dichiarato corrisponde
                  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: >-
                    Indirizzo del data center in conflitto con il paese
                    dichiarato
                  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: Indirizzo IPv4 o IPv6 a cui assegnare un punteggio.
          example: 8.8.8.8
        claimed_country:
          type: string
          maxLength: 3
          description: >-
            Paese opzionale ISO 3166-1 alpha-2 o alpha-3 dichiarato dall'utente
            o dalla sessione. Utilizzato per calcolare `country_mismatch`.
          example: ESP
        user_agent:
          type: string
          maxLength: 512
          description: >-
            User agent rilevato dal tuo backend. Memorizzato come contesto della
            richiesta; non fornisce il fingerprinting del dispositivo.
        vendor_data:
          type: string
          description: >-
            Il tuo riferimento stabile per questa richiesta. Memorizzato nella
            sessione API e restituito nella risposta.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            I tuoi metadati JSON non sensibili. Memorizzati nella sessione API e
            restituiti nella risposta.
    IPRiskResponse:
      type: object
      required:
        - request_id
        - status
        - created_at
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            ID della sessione API creata per questa richiesta. Memorizzalo con
            `vendor_data` se hai bisogno di correlare il risultato con i webhook
            successivi o con l'attività nella console.
        status:
          type: string
          enum:
            - Approved
            - In Review
          description: >-
            Decisione per questa sessione API: `In Review` in caso di rischio di
            rete o mancata corrispondenza del paese, altrimenti `Approved`.
        vendor_data:
          type: string
          nullable: true
          description: Eco del `vendor_data` inviato, `null` se non ne hai inviato alcuno.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: Eco del `metadata` inviato, `null` se non ne hai inviato alcuno.
        created_at:
          type: string
          format: date-time
          description: Timestamp di questa risposta.
        ip:
          type: object
          description: >-
            Risultato del rischio IP. I singoli campi di arricchimento possono
            essere `null` quando la ricerca non ha restituito dati utilizzabili.
          required:
            - status
            - threat
          properties:
            status:
              type: string
              enum:
                - Approved
                - In Review
              description: >-
                `In Review` quando il paese rilevato è in conflitto con
                `claimed_country` o quando l'indirizzo è associato a
                un'infrastruttura VPN, Tor o data center. Altrimenti `Approved`.
            ip_address:
              type: string
              nullable: true
              description: >-
                L'indirizzo valutato. `null` quando nessuna fonte di
                arricchimento ha restituito dati utilizzabili.
            ip_country:
              type: string
              nullable: true
              description: Nome del paese risolto.
            ip_country_code:
              type: string
              nullable: true
              description: >-
                Codice paese risolto. Confronta i paesi tramite
                `country_mismatch` invece di confrontare manualmente le stringhe
                dei paesi non elaborate.
            ip_state:
              type: string
              nullable: true
              description: Stato o regione determinati.
            ip_city:
              type: string
              nullable: true
              description: Città risolta.
            latitude:
              type: number
              nullable: true
              description: >-
                Geolocalizzazione di rete approssimativa, non la posizione
                precisa del dispositivo.
            longitude:
              type: number
              nullable: true
              description: >-
                Geolocalizzazione di rete approssimativa, non la posizione
                precisa del dispositivo.
            isp:
              type: string
              nullable: true
              description: >-
                Provider di servizi Internet che fornisce il servizio
                all'indirizzo.
            organization:
              type: string
              nullable: true
              description: Organizzazione proprietaria del blocco di indirizzi.
            is_vpn_or_tor:
              type: boolean
              nullable: true
              description: >-
                `true` quando l'indirizzo è associato a un'infrastruttura VPN o
                Tor.
            is_data_center:
              type: boolean
              nullable: true
              description: >-
                `true` quando l'indirizzo appartiene a una rete di hosting o
                data center.
            time_zone:
              type: string
              nullable: true
              description: Fuso orario della posizione risolta.
            time_zone_offset:
              type: string
              nullable: true
              description: Offset UTC della posizione risolta.
            asn_number:
              type: number
              nullable: true
              description: Numero di sistema autonomo.
            asn_organization:
              type: string
              nullable: true
              description: Organizzazione che gestisce il sistema autonomo.
            connection_type:
              type: string
              nullable: true
              description: >-
                Classificazione della connessione (ad es. `cellular`,
                `hosting`).
            carrier:
              type: string
              nullable: true
              description: Operatore mobile quando l'indirizzo si trova su una rete mobile.
            proxy_type:
              type: string
              nullable: true
              description: >-
                Classificazione proxy quando l'indirizzo si trova dietro un
                proxy.
            claimed_country:
              type: string
              nullable: true
              description: Eco del `claimed_country` inviato.
            country_mismatch:
              type: boolean
              nullable: true
              description: >-
                `true` quando il paese determinato differisce da
                `claimed_country`. `null` quando non sono disponibili dati di
                arricchimento o non è disponibile alcun paese dichiarato.
            threat:
              type: object
              additionalProperties: true
              description: >-
                Evidenze di minaccia di rete a struttura libera dalla fonte di
                arricchimento (ad es. `is_proxy`, `is_tor`). Oggetto vuoto
                quando non sono disponibili dati di arricchimento. Consideralo
                un dettaglio diagnostico, non un contratto stabile.
  responses:
    IPRiskValidationError:
      description: Validazione della richiesta non riuscita.
      content:
        application/json:
          examples:
            Missing IP address:
              summary: Indirizzo IP mancante
              value:
                ip_address:
                  - This field is required.
            Invalid IP address:
              summary: Indirizzo IP non valido
              value:
                ip_address:
                  - Enter a valid IPv4 or IPv6 address.
            Country hint too long:
              summary: Suggerimento del paese troppo lungo
              value:
                claimed_country:
                  - Ensure this field has no more than 3 characters.
    RiskPermissionDenied:
      description: >-
        La chiave API è mancante o non valida, oppure l'organizzazione non può
        coprire la ricerca in tempo reale. Questa API non restituisce mai `401`.
      content:
        application/json:
          examples:
            Missing or invalid API key:
              summary: >-
                Nessuna intestazione `x-api-key`, oppure la chiave non è valida
                o è stata revocata
              value:
                detail: You do not have permission to perform this action.
            Not enough credits:
              summary: >-
                Il saldo dell'organizzazione non è sufficiente per coprire il
                prezzo della ricerca
              value:
                error: You don't have enough credits to perform this request.
    RateLimitedWrite:
      description: >-
        Il limite di scrittura condiviso di 300 richieste al minuto per chiave
        API è stato superato. Rispetta `Retry-After` prima di riprovare.
      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 chiave API della tua applicazione, da Developers -> API keys nella
        Business Console. La chiave primaria ha accesso completo. Una chiave con
        nome può avere un ambito definito: nessuno, lettura o scrittura per
        risorsa, limitata ad alcuni workflow o a sessioni approvate, a un elenco
        di indirizzi IP e a una data di scadenza. 401 indica che la chiave è
        errata, revocata o scaduta; 403 indica che non è stata inviata alcuna
        chiave, che la chiave non ha accesso a questa risorsa o azione, oppure
        che la richiesta proviene da un indirizzo non incluso nel suo elenco IP;
        404 su una route di sessione indica che la sessione non rientra nei
        workflow o negli stati previsti dalla chiave. Una chiave senza accesso
        ai media riceve gli URL di immagini, video e PDF come null, e una chiave
        senza permessi di scrittura sulle sessioni riceve link e token di
        sessione come null. Consulta https://docs.didit.me/console/api-keys.

````

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