> ## 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 risc d'IP: geolocalització, VPN i centres de dades

> Puntua el risc d'una adreça IP amb geolocalització, ISP, senyals de VPN/Tor, centres de dades, amenaces i discrepàncies de país. API de Didit.

Utilitza `POST /v3/ip/risk/` quan el teu backend ja tingui una adreça IP i necessiti una decisió de risc de servidor a servidor.

La resposta inclou la geolocalització, la titularitat de la xarxa, els indicadors de VPN/Tor i de centre de dades, les dades d'amenaça i `country_mismatch` quan envies un país declarat.

## Interpretar la resposta

* `status` és `In Review` quan el país resolt entra en conflicte amb `claimed_country`, o quan l'adreça està associada a infraestructura de VPN, Tor o centre de dades. En cas contrari, és `Approved`.
* `ip.ip_country_code` conté el codi del país resolt. Compara els països a través de `ip.country_mismatch` en lloc de comparar tu mateix les cadenes de país sense processar.
* `ip.latitude` i `ip.longitude` són una geolocalització de xarxa aproximada, no una ubicació precisa del dispositiu.
* `ip.is_vpn_or_tor`, `ip.is_data_center`, `ip.proxy_type` i `ip.threat` aporten evidència de risc de xarxa.
* `ip.asn_number`, `ip.asn_organization`, `ip.connection_type` i `ip.carrier` descriuen la xarxa a la qual pertany l'adreça.
* `request_id` és l'identificador de la sessió de l'API. Emmagatzema'l amb `vendor_data` si necessites correlacionar el resultat amb webhooks posteriors o amb l'activitat de la consola.

> [!NOTE]
>
> L'enriquiment d'IP es fa tan bé com es pot. Si cap font d'enriquiment retorna dades utilitzables, l'endpoint retorna una resposta aprovada amb `ip.ip_address: null`, `ip.country_mismatch: null` i un objecte `ip.threat` buit. Els camps d'enriquiment individuals també poden ser `null` quan no estiguin disponibles.

## Intel·ligència del dispositiu

L'API de risc d'IP és un endpoint pur de servidor a servidor. La identificació del dispositiu (empremta digital del dispositiu) tampoc no és exclusivament de servidor a servidor, perquè un backend no pot observar per si mateix els senyals del navegador o del dispositiu. Per a les sessions del flux allotjat i del SDK, Didit exposa els camps del dispositiu ja recollits a la resposta de la sessió, inclosos `device_fingerprint`, els detalls del dispositiu i del navegador, `user_agent`, les dades del dispositiu en brut i les coincidències entre sessions.

## Comportament del sandbox

Les claus de sandbox validen la sol·licitud i retornen dades aprovades deterministes. No contacten amb serveis externs d'intel·ligència, no consumeixen crèdits, no creen una sessió i no contribueixen a Networks.

## Facturació

Les crides a l'API de risc d'IP costen \$0.02 al preu de llista. Una sol·licitud de producció es factura en el moment en què comença la consulta.


## OpenAPI

````yaml ca/openapi-25.json POST /v3/ip/risk/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API de verificació d'identitat. Autentica't amb la capçalera x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/ip/risk/:
    post:
      tags:
        - Standalone APIs
      summary: Calcular la puntuació de risc d'una adreça IP
      description: >-
        Retorna geolocalització, titularitat de la xarxa, indicadors de VPN/Tor
        i centre de dades, dades d'amenaces i `country_mismatch` per a una
        adreça proporcionada. L'endpoint crea una sessió d'API i retorna el seu
        identificador com a `request_id`.


        **Decisió.** `status` és `In Review` quan el país resolt entra en
        conflicte amb `claimed_country`, o quan l'adreça està associada amb
        infraestructura de VPN, Tor o centre de dades. En cas contrari, és
        `Approved`.


        **Millor esforç.** L'enriquiment d'IP es fa amb el millor esforç. Si cap
        font d'enriquiment no retorna dades utilitzables, l'endpoint retorna una
        resposta aprovada amb `ip.ip_address: null`, `ip.country_mismatch: null`
        i un objecte `ip.threat` buit.


        **Facturació.** Les crides en producció utilitzen els preus d'IP Risk
        API. La sol·licitud és facturable un cop comença la cerca.


        **Sandbox.** Les claus de sandbox validen la sol·licitud i retornen
        dades aprovades deterministes sense consumir crèdits, crear cap sessió
        ni contribuir a Networks.


        **Autenticació.** Envia la clau d'API de la teva aplicació a
        `x-api-key`. Les credencials absents o no vàlides retornen `403` -
        aquesta API mai retorna `401`.


        **Límit de freqüència.** Pressupost d'escriptura compartit de 300
        sol·licituds per minut per clau d'API entre els endpoints
        POST/PATCH/DELETE (la creació de transaccions i la ingesta
        d'esdeveniments tenen un pressupost separat de 600).
      operationId: post_v3ip_risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IPRiskRequest'
            examples:
              Minimal:
                summary: Puntua una adreça amb els valors per defecte
                value:
                  ip_address: 8.8.8.8
              With claimed country:
                summary: Puntua amb un país declarat per a la detecció de discrepàncies
                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: >-
            S'ha completat l'avaluació de risc. Inspecciona `status` per
            conèixer la decisió; la resposta HTTP sempre és `200` per a
            consultes completades.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IPRiskResponse'
              examples:
                Clean residential IP:
                  summary: Adreça de residència, el país declarat coincideix
                  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: Adreça del centre de dades en conflicte amb el país declarat
                  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: Adreça IPv4 o IPv6 a puntuar.
          example: 8.8.8.8
        claimed_country:
          type: string
          maxLength: 3
          description: >-
            País ISO 3166-1 alfa-2 o alfa-3 opcional declarat per l'usuari o la
            sessió. S'utilitza per calcular `country_mismatch`.
          example: ESP
        user_agent:
          type: string
          maxLength: 512
          description: >-
            Agent d'usuari observat pel teu back-end. S'emmagatzema com a
            context de la sol·licitud; no proporciona empremta digital del
            dispositiu.
        vendor_data:
          type: string
          description: >-
            La teva referència estable per a aquesta sol·licitud. S'emmagatzema
            a la sessió de l'API i es retorna a la resposta.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Les teves metadades JSON no sensibles. S'emmagatzemen a la sessió de
            l'API i es retornen a la resposta.
    IPRiskResponse:
      type: object
      required:
        - request_id
        - status
        - created_at
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            Identificador de la sessió d'API creada per a aquesta sol·licitud.
            Emmagatzema'l amb `vendor_data` si necessites correlacionar el
            resultat amb webhooks posteriors o amb l'activitat a la consola.
        status:
          type: string
          enum:
            - Approved
            - In Review
          description: >-
            Decisió per a aquesta sessió de l'API: `In Review` per risc de xarxa
            o discrepància de país, en cas contrari `Approved`.
        vendor_data:
          type: string
          nullable: true
          description: >-
            Ressò de les `vendor_data` que has enviat, `null` si no n'has enviat
            cap.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Ressò de les `metadata` que has enviat, `null` si no n'has enviat
            cap.
        created_at:
          type: string
          format: date-time
          description: Marca de temps d'aquesta resposta.
        ip:
          type: object
          description: >-
            Resultat de risc d'IP. Els camps d'enriquiment individuals poden ser
            `null` quan la cerca no ha retornat dades utilitzables.
          required:
            - status
            - threat
          properties:
            status:
              type: string
              enum:
                - Approved
                - In Review
              description: >-
                `In Review` quan el país resolt entra en conflicte amb
                `claimed_country`, o quan l'adreça està associada a una
                infraestructura de VPN, Tor o centre de dades. En cas contrari,
                `Approved`.
            ip_address:
              type: string
              nullable: true
              description: >-
                L'adreça puntuada. `null` quan cap font d'enriquiment ha
                retornat dades utilitzables.
            ip_country:
              type: string
              nullable: true
              description: Nom del país resolt.
            ip_country_code:
              type: string
              nullable: true
              description: >-
                Codi de país resolt. Compara els països mitjançant
                `country_mismatch` en lloc de comparar cadenes de país en brut
                pel teu compte.
            ip_state:
              type: string
              nullable: true
              description: Estat o regió resolts.
            ip_city:
              type: string
              nullable: true
              description: Ciutat resolta.
            latitude:
              type: number
              nullable: true
              description: >-
                Geolocalització de xarxa aproximada, no una ubicació precisa del
                dispositiu.
            longitude:
              type: number
              nullable: true
              description: >-
                Geolocalització de xarxa aproximada, no una ubicació precisa del
                dispositiu.
            isp:
              type: string
              nullable: true
              description: Proveïdor de serveis d'Internet que presta servei a l'adreça.
            organization:
              type: string
              nullable: true
              description: Organització propietària del bloc d'adreces.
            is_vpn_or_tor:
              type: boolean
              nullable: true
              description: >-
                `true` quan l'adreça està associada amb infraestructura VPN o
                Tor.
            is_data_center:
              type: boolean
              nullable: true
              description: >-
                `true` quan l'adreça pertany a una xarxa d'allotjament o de
                centre de dades.
            time_zone:
              type: string
              nullable: true
              description: Zona horària de la ubicació resolta.
            time_zone_offset:
              type: string
              nullable: true
              description: Desfasament UTC de la ubicació resolta.
            asn_number:
              type: number
              nullable: true
              description: Número de sistema autònom.
            asn_organization:
              type: string
              nullable: true
              description: Organització que opera el sistema autònom.
            connection_type:
              type: string
              nullable: true
              description: Classificació de la connexió (p. ex., `cellular`, `hosting`).
            carrier:
              type: string
              nullable: true
              description: Operador mòbil quan l'adreça pertany a una xarxa mòbil.
            proxy_type:
              type: string
              nullable: true
              description: Classificació de proxy quan l'adreça és darrere d'un proxy.
            claimed_country:
              type: string
              nullable: true
              description: Ressò del `claimed_country` que has enviat.
            country_mismatch:
              type: boolean
              nullable: true
              description: >-
                `true` quan el país resolt difereix de `claimed_country`. `null`
                quan no hi ha dades d'enriquiment o cap país declarat
                disponible.
            threat:
              type: object
              additionalProperties: true
              description: >-
                Evidència d'amenaces de xarxa en format lliure de la font
                d'enriquiment (p. ex., `is_proxy`, `is_tor`). Objecte buit quan
                no hi ha dades d'enriquiment disponibles. Tracta-ho com a detall
                de diagnòstic, no com un contracte estable.
  responses:
    IPRiskValidationError:
      description: Ha fallat la validació de la sol·licitud.
      content:
        application/json:
          examples:
            Missing IP address:
              summary: Falta l'adreça IP
              value:
                ip_address:
                  - This field is required.
            Invalid IP address:
              summary: Adreça IP no vàlida
              value:
                ip_address:
                  - Enter a valid IPv4 or IPv6 address.
            Country hint too long:
              summary: Indicació de país massa llarga
              value:
                claimed_country:
                  - Ensure this field has no more than 3 characters.
    RiskPermissionDenied:
      description: >-
        Falta la clau d'API o no és vàlida, o l'organització no pot cobrir la
        consulta en temps real. Aquesta API mai no retorna `401`.
      content:
        application/json:
          examples:
            Missing or invalid API key:
              summary: >-
                Sense capçalera `x-api-key`, o la clau no és vàlida o s'ha
                revocat
              value:
                detail: You do not have permission to perform this action.
            Not enough credits:
              summary: El saldo de l'organització no pot cobrir el preu de la consulta
              value:
                error: You don't have enough credits to perform this request.
    RateLimitedWrite:
      description: >-
        S'ha superat el límit compartit d'escriptura de 300 sol·licituds per
        minut per clau d'API. Respecta `Retry-After` abans de reintentar.
      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 clau d'API de la teva aplicació, des de Developers -> API keys a la
        Business Console. La clau primària té accés complet. Una clau amb nom
        pot tenir l'abast limitat: cap, lectura o escriptura per recurs,
        limitada a determinats fluxos de treball o a sessions aprovades, a una
        llista d'adreces IP i a una data de caducitat. 401 significa que la clau
        és incorrecta, revocada o caducada; 403 significa que no s'ha enviat cap
        clau, que la clau no té accés a aquest recurs o acció, o que la
        sol·licitud prové d'una adreça fora de la seva llista d'IP; 404 en una
        ruta de sessió significa que la sessió està fora dels fluxos de treball
        o estats de la clau. Una clau sense accés a fitxers multimèdia rep els
        URL d'imatge, vídeo i PDF com a null, i una clau sense permís
        d'escriptura de sessions rep els enllaços de sessió i els tokens com a
        null. Consulta https://docs.didit.me/console/api-keys.

````

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