> ## 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 Risiko IP: Deteksi VPN, Proxy & Datacenter

> Nilai risiko alamat IP dengan geolokasi, ISP, sinyal VPN/Tor, datacenter, ancaman, dan ketidaksesuaian negara dari Didit.

Gunakan `POST /v3/ip/risk/` saat backend Anda sudah memiliki alamat IP dan memerlukan keputusan risiko server-ke-server.

Respons mencakup geolokasi, kepemilikan jaringan, indikator VPN/Tor dan pusat data, data ancaman, serta `country_mismatch` saat Anda mengirim negara yang diklaim.

## Interpretasi respons

* `status` bernilai `In Review` jika negara hasil resolusi bertentangan dengan `claimed_country`, atau jika alamat terkait dengan infrastruktur VPN, Tor, atau pusat data. Selain itu, nilainya `Approved`.
* `ip.ip_country_code` berisi kode negara hasil resolusi. Bandingkan negara melalui `ip.country_mismatch` alih-alih membandingkan string negara mentah sendiri.
* `ip.latitude` dan `ip.longitude` adalah geolokasi jaringan perkiraan, bukan lokasi perangkat yang presisi.
* `ip.is_vpn_or_tor`, `ip.is_data_center`, `ip.proxy_type`, dan `ip.threat` memuat bukti risiko jaringan.
* `ip.asn_number`, `ip.asn_organization`, `ip.connection_type`, dan `ip.carrier` menjelaskan jaringan tempat alamat tersebut berada.
* `request_id` adalah ID sesi API. Simpan bersama `vendor_data` jika Anda perlu mengorelasikan hasil dengan webhook berikutnya atau aktivitas konsol.

> [!NOTE]
>
> Pengayaan IP bersifat upaya terbaik. Jika tidak ada sumber pengayaan yang mengembalikan data yang dapat digunakan, endpoint mengembalikan respons yang disetujui dengan `ip.ip_address: null`, `ip.country_mismatch: null`, dan objek `ip.threat` yang kosong. Kolom pengayaan individual juga dapat bernilai `null` jika tidak tersedia.

## Intelijen perangkat

IP Risk API adalah endpoint server-ke-server murni. Pembuatan sidik jari perangkat tidak bersifat demikian, karena backend tidak dapat mengamati sinyal browser atau perangkat dengan sendirinya. Untuk sesi alur yang di-hosting dan SDK, Didit menampilkan kolom perangkat yang sudah dikumpulkan pada respons sesi, termasuk `device_fingerprint`, detail perangkat dan browser, `user_agent`, data perangkat mentah, serta kecocokan lintas sesi.

## Perilaku sandbox

Kunci sandbox memvalidasi permintaan dan mengembalikan data yang disetujui secara deterministik. Kunci tersebut tidak menghubungi layanan intelijen eksternal, tidak menggunakan kredit, tidak membuat sesi, dan tidak berkontribusi ke Networks.

## Penagihan

Panggilan IP Risk API berbiaya \$0.02 pada harga daftar. Permintaan produksi dikenai biaya setelah pencarian dimulai.


## OpenAPI

````yaml id/openapi-25.json POST /v3/ip/risk/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API Verifikasi Identitas. Lakukan autentikasi dengan header x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/ip/risk/:
    post:
      tags:
        - Standalone APIs
      summary: Memberi skor risiko pada alamat IP
      description: >-
        Mengembalikan geolokasi, kepemilikan jaringan, penanda VPN/Tor dan pusat
        data, data ancaman, serta `country_mismatch` untuk alamat IP yang
        diberikan. Endpoint ini membuat sesi API dan mengembalikan id-nya
        sebagai `request_id`.


        **Keputusan.** `status` bernilai `In Review` jika negara yang
        teridentifikasi bertentangan dengan `claimed_country`, atau saat alamat
        dikaitkan dengan infrastruktur VPN, Tor, atau pusat data. Jika tidak,
        nilainya adalah `Approved`.


        **Upaya terbaik.** Pengayaan IP dilakukan dengan upaya terbaik. Jika
        tidak ada sumber pengayaan yang mengembalikan data yang dapat digunakan,
        endpoint mengembalikan respons disetujui dengan `ip.ip_address: null`,
        `ip.country_mismatch: null`, dan objek `ip.threat` kosong.


        **Penagihan.** Panggilan produksi menggunakan harga IP Risk API.
        Permintaan dikenakan biaya begitu pencarian dimulai.


        **Sandbox.** Kunci sandbox memvalidasi permintaan dan mengembalikan data
        deterministik berstatus disetujui tanpa menggunakan kredit, membuat
        sesi, atau berkontribusi ke Networks.


        **Autentikasi.** Kirim kunci API aplikasi Anda di `x-api-key`.
        Kredensial yang hilang atau tidak valid akan mengembalikan `403` - API
        ini tidak pernah mengembalikan `401`.


        **Batas laju.** Anggaran tulis bersama sebesar 300 permintaan per menit
        per kunci API di seluruh endpoint POST/PATCH/DELETE (pembuatan transaksi
        dan ingesti event memiliki anggaran terpisah sebesar 600).
      operationId: post_v3ip_risk
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IPRiskRequest'
            examples:
              Minimal:
                summary: Beri skor alamat dengan pengaturan default
                value:
                  ip_address: 8.8.8.8
              With claimed country:
                summary: >-
                  Beri skor dengan negara yang diklaim untuk deteksi
                  ketidakcocokan
                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: >-
            Evaluasi risiko selesai. Periksa `status` untuk melihat
            keputusannya; HTTP selalu `200` untuk pencarian yang selesai.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IPRiskResponse'
              examples:
                Clean residential IP:
                  summary: Alamat tempat tinggal, negara yang diklaim cocok
                  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: Alamat pusat data bentrok dengan negara yang diklaim
                  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: Alamat IPv4 atau IPv6 yang akan dinilai.
          example: 8.8.8.8
        claimed_country:
          type: string
          maxLength: 3
          description: >-
            Negara ISO 3166-1 alpha-2 atau alpha-3 opsional yang diklaim oleh
            pengguna atau sesi. Digunakan untuk menghitung `country_mismatch`.
          example: ESP
        user_agent:
          type: string
          maxLength: 512
          description: >-
            User agent yang diamati oleh backend Anda. Disimpan sebagai konteks
            permintaan; ini tidak menyediakan fingerprinting perangkat.
        vendor_data:
          type: string
          description: >-
            Referensi stabil Anda untuk permintaan ini. Disimpan pada sesi API
            dan ditampilkan kembali dalam respons.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Metadata JSON non-sensitif Anda. Disimpan pada sesi API dan
            dikembalikan dalam respons.
    IPRiskResponse:
      type: object
      required:
        - request_id
        - status
        - created_at
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            Id dari sesi API yang dibuat untuk permintaan ini. Simpan bersama
            `vendor_data` jika Anda perlu mengorelasikan hasilnya dengan webhook
            atau aktivitas konsol berikutnya.
        status:
          type: string
          enum:
            - Approved
            - In Review
          description: >-
            Keputusan untuk sesi API ini: `In Review` untuk risiko jaringan atau
            ketidakcocokan negara, jika tidak maka `Approved`.
        vendor_data:
          type: string
          nullable: true
          description: >-
            Salinan `vendor_data` yang Anda kirimkan, atau `null` jika Anda
            tidak mengirimkannya.
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Salinan `metadata` yang Anda kirimkan, atau `null` jika Anda tidak
            mengirimkannya.
        created_at:
          type: string
          format: date-time
          description: Cap waktu respons ini.
        ip:
          type: object
          description: >-
            Hasil risiko IP. Kolom pengayaan individual dapat bernilai `null`
            jika pencarian tidak mengembalikan data yang dapat digunakan.
          required:
            - status
            - threat
          properties:
            status:
              type: string
              enum:
                - Approved
                - In Review
              description: >-
                `In Review` ketika negara yang teridentifikasi bertentangan
                dengan `claimed_country`, atau ketika alamat dikaitkan dengan
                infrastruktur VPN, Tor, atau pusat data. Jika tidak, `Approved`.
            ip_address:
              type: string
              nullable: true
              description: >-
                Alamat yang dinilai. `null` jika tidak ada sumber pengayaan yang
                mengembalikan data yang dapat digunakan.
            ip_country:
              type: string
              nullable: true
              description: Nama negara hasil resolusi.
            ip_country_code:
              type: string
              nullable: true
              description: >-
                Kode negara yang terselesaikan. Bandingkan negara melalui
                `country_mismatch` alih-alih membandingkan string negara mentah
                sendiri.
            ip_state:
              type: string
              nullable: true
              description: Negara bagian atau wilayah hasil resolusi.
            ip_city:
              type: string
              nullable: true
              description: Kota hasil resolusi.
            latitude:
              type: number
              nullable: true
              description: >-
                Geolokasi jaringan perkiraan, bukan lokasi perangkat yang
                presisi.
            longitude:
              type: number
              nullable: true
              description: >-
                Geolokasi jaringan perkiraan, bukan lokasi perangkat yang
                presisi.
            isp:
              type: string
              nullable: true
              description: Penyedia layanan internet yang melayani alamat tersebut.
            organization:
              type: string
              nullable: true
              description: Organisasi yang memiliki blok alamat.
            is_vpn_or_tor:
              type: boolean
              nullable: true
              description: '`true` jika alamat dikaitkan dengan infrastruktur VPN atau Tor.'
            is_data_center:
              type: boolean
              nullable: true
              description: >-
                `true` jika alamat termasuk dalam jaringan hosting atau pusat
                data.
            time_zone:
              type: string
              nullable: true
              description: Zona waktu dari lokasi hasil resolusi.
            time_zone_offset:
              type: string
              nullable: true
              description: Offset UTC dari lokasi yang ditentukan.
            asn_number:
              type: number
              nullable: true
              description: Nomor sistem otonom.
            asn_organization:
              type: string
              nullable: true
              description: Organisasi yang mengoperasikan sistem otonom.
            connection_type:
              type: string
              nullable: true
              description: Klasifikasi koneksi (misalnya, `cellular`, `hosting`).
            carrier:
              type: string
              nullable: true
              description: Operator seluler ketika alamat berada di jaringan seluler.
            proxy_type:
              type: string
              nullable: true
              description: Klasifikasi proksi saat alamat berada di balik proksi.
            claimed_country:
              type: string
              nullable: true
              description: Salinan `claimed_country` yang Anda kirimkan.
            country_mismatch:
              type: boolean
              nullable: true
              description: >-
                `true` saat negara yang teridentifikasi berbeda dari
                `claimed_country`. `null` saat tidak ada data pengayaan atau
                tidak ada negara yang diklaim yang tersedia.
            threat:
              type: object
              additionalProperties: true
              description: >-
                Bukti ancaman jaringan bentuk bebas dari sumber pengayaan
                (misalnya, `is_proxy`, `is_tor`). Objek kosong jika tidak ada
                data pengayaan yang tersedia. Perlakukan sebagai detail
                diagnostik, bukan kontrak yang stabil.
  responses:
    IPRiskValidationError:
      description: Validasi permintaan gagal.
      content:
        application/json:
          examples:
            Missing IP address:
              summary: Alamat IP tidak ada
              value:
                ip_address:
                  - This field is required.
            Invalid IP address:
              summary: Alamat IP tidak valid
              value:
                ip_address:
                  - Enter a valid IPv4 or IPv6 address.
            Country hint too long:
              summary: Petunjuk negara terlalu panjang
              value:
                claimed_country:
                  - Ensure this field has no more than 3 characters.
    RiskPermissionDenied:
      description: >-
        Kunci API tidak ada atau tidak valid, atau organisasi tidak dapat
        menanggung biaya pencarian langsung. API ini tidak pernah mengembalikan
        `401`.
      content:
        application/json:
          examples:
            Missing or invalid API key:
              summary: >-
                Tidak ada header `x-api-key`, atau kunci tidak valid atau
                dicabut
              value:
                detail: You do not have permission to perform this action.
            Not enough credits:
              summary: Saldo organisasi tidak mencukupi untuk harga pencarian
              value:
                error: You don't have enough credits to perform this request.
    RateLimitedWrite:
      description: >-
        Batas tulis bersama sebesar 300 permintaan per menit per kunci API telah
        terlampaui. Patuhi `Retry-After` sebelum mencoba lagi.
      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: >-
        Kunci API aplikasi Anda, dari Developers -> API keys di Business
        Console. Kunci utama memiliki akses penuh. Kunci bernama dapat diberi
        cakupan: none, read, atau write per sumber daya, dibatasi pada beberapa
        alur kerja atau pada sesi yang disetujui, pada daftar alamat IP, dan
        pada tanggal kedaluwarsa. 401 berarti kuncinya salah, dicabut, atau
        kedaluwarsa; 403 berarti tidak ada kunci yang dikirimkan, kunci tidak
        memiliki akses ke sumber daya atau tindakan ini, atau permintaan datang
        dari alamat di luar daftar IP-nya; 404 pada rute sesi berarti sesi
        berada di luar alur kerja atau status kunci tersebut. Kunci tanpa akses
        media menerima URL gambar, video, dan PDF sebagai null, dan kunci tanpa
        izin tulis sesi menerima tautan sesi dan token sebagai null. Lihat
        https://docs.didit.me/console/api-keys.

````

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