> ## 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.

# Terbitkan Token SDK Pemantauan API

> Terbitkan kredensial perangkat berumur pendek untuk satu subjek agar aplikasi dapat mengirim event pemantauan ke Didit tanpa membuka kunci API.



Prompt API Pembuatan Token SDK Pemantauan
        Salin prompt ke papan klip



      
      

\<pre>

\`Mint a short-lived device credential so my web or mobile app can send monitoring events for one user straight to Didit.

Endpoint:
POST https://verification.didit.me/v3/events/sdk-token/

Authentication:
Use the x-api-key header with my Didit API key. This call runs on MY BACKEND only - the API key must never ship in an app. Only the returned monitoring_token travels to the device. A scoped key needs transactions: write.

Goal:
\- Get a monitoring_token for the signed-in user. The app sends it in the X-Monitoring-Token header to the device lane (POST /v1/events/ and POST /v1/events/batch/).

Request body (application/json):
\{
"vendor_data": "user-42",                                  // required - the subject every event belongs to
"entity_type": "individual",                               // optional - company binds a company; any other value an individual (default)
"allowed_event_categories": ["auth", "session", "gameplay"], // optional - omit or [] for every category
"ttl_seconds": 900,                                        // optional - 60 to 86400, default 900
"max_uses": 1000,                                          // optional - events it may submit, default 1000, null for no cap
"bind_to_origin": "https://app.example.com"                // optional - browser Origin must match exactly
}
camelCase aliases (vendorData, entityType, allowedEventCategories, ttlSeconds, maxUses, bindToOrigin) are also accepted.

Behavior:
\- The subject is bound server-side: whatever subject the app sends is overwritten with vendor_data.
\- One use per submitted event, also inside a batch: a 500-event flush spends 500 uses, and events the device lane rejects spend uses too.
\- An event outside allowed_event_categories is rejected by the device lane with 400.
\- With bind_to_origin set, a device request with a different Origin, or none, is refused.
\- Minting does not create a user.
\- Event ingestion must be switched on for the application, otherwise this call returns 403 with code event_monitoring_disabled.

Example call:
curl -X POST "https://verification.didit.me/v3/events/sdk-token/" \
-H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"vendor_data":"user-42","allowed_event_categories":["auth","session","gameplay"],"ttl_seconds":900,"max_uses":1000}'

What to read from the response:
\- monitoring_token - hand it to the app; treat it as a secret for its lifetime.
\- expires_at - mint a fresh credential per user session before it expires.
\- allowed_event_categories ([] means every category), max_uses (null means no cap), bind_to_origin.

Failure modes:
\- 400 - missing vendor_data, ttl_seconds outside 60-86400, max_uses below 1, or an unknown category.
\- 401 - the API key has expired.
\- 403 - missing API key (a wrong, revoked or expired key gets 401), a scoped key without transactions: write, or code event_monitoring_disabled.

Side effects: creates one credential. Nothing else changes.

For the full client-side submission guide, see /transaction-monitoring/sdk-event-submission.`

\</pre>



      
      

Tempel ke

Kredensial ini digunakan oleh jalur perangkat, yang dijelaskan dalam [Pengiriman event SDK](https://docs.didit.me/id/transaction-monitoring/sdk-event-submission.md). Halaman tersebut juga mencantumkan persyaratan apa saja yang diberlakukan oleh server pada setiap permintaan perangkat dan event mana yang aman untuk dibuang saat terjadi backpressure.


## OpenAPI

````yaml id/openapi-25.json POST /v3/events/sdk-token/
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/events/sdk-token/:
    post:
      tags:
        - Monitoring Events
      summary: Buat token SDK pemantauan
      description: >-
        Buat kredensial perangkat berumur pendek yang terikat pada satu subjek,
        sehingga aplikasi web atau seluler Anda dapat mengirim event pengguna
        tersebut langsung ke Didit tanpa kunci API. Aplikasi mengirimkan
        `monitoring_token` yang dikembalikan dalam header `X-Monitoring-Token`
        ke jalur perangkat (`POST /v1/events/` dan `POST /v1/events/batch/`), di
        mana subjek selalu ditimpa dengan `vendor_data` ini, event di luar
        `allowed_event_categories` ditolak, setiap event yang dikirimkan
        menghabiskan satu penggunaan, dan permintaan yang `Origin`-nya tidak
        sama dengan `bind_to_origin` ditolak. Panggil endpoint ini hanya dari
        backend Anda; pembuatan hanya membuat kredensial dan tidak ada yang lain
        (tidak ada pengguna yang dibuat). Penerimaan event harus diaktifkan
        untuk aplikasi, jika tidak, endpoint ini mengembalikan `403` dengan
        `code: event_monitoring_disabled` daripada membuat kredensial yang tidak
        akan pernah bisa menulis. Kunci API dengan pembatasan cakupan memerlukan
        `transactions: write`. Lihat [Pengiriman event
        SDK](https://docs.didit.me/id/transaction-monitoring/sdk-event-submission).
      operationId: create_monitoring_event_sdk_token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: >-
                alias camelCase diterima: `vendorData`, `entityType`,
                `allowedEventCategories`, `ttlSeconds`, `maxUses`,
                `bindToOrigin`.
              required:
                - vendor_data
              properties:
                vendor_data:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: >-
                    ID Anda untuk subjek yang memiliki setiap event yang
                    dikirimkan dengan kredensial ini.
                entity_type:
                  type: string
                  maxLength: 32
                  default: individual
                  description: >-
                    `company` mengikat subjek perusahaan; nilai lainnya (default
                    `individual`) mengikat perorangan.
                allowed_event_categories:
                  type: array
                  items:
                    type: string
                    enum:
                      - auth
                      - session
                      - gameplay
                      - bonus
                      - affiliate
                      - payment
                      - dispute
                      - security
                      - responsible_gambling
                      - custom
                  description: >-
                    Kategori yang dapat dikirimkan oleh kredensial. Hilangkan
                    atau kirim `[]` untuk mengizinkan setiap kategori.
                ttl_seconds:
                  type: integer
                  minimum: 60
                  maximum: 86400
                  default: 900
                  description: Masa berlaku kredensial dalam detik.
                max_uses:
                  type: integer
                  minimum: 1
                  nullable: true
                  default: 1000
                  description: >-
                    Jumlah event yang dapat dikirimkan oleh kredensial (satu
                    batch menggunakan satu penggunaan untuk setiap event). Kirim
                    `null` untuk tanpa batas dalam masa berlaku.
                bind_to_origin:
                  type: string
                  maxLength: 255
                  nullable: true
                  description: >-
                    Jika diatur, header `Origin` browser dari setiap permintaan
                    perangkat harus sama persis dengan nilai ini; permintaan
                    tanpa `Origin` akan ditolak.
            example:
              vendor_data: user-42
              allowed_event_categories:
                - auth
                - session
                - gameplay
              ttl_seconds: 900
              max_uses: 1000
              bind_to_origin: https://app.example.com
      responses:
        '201':
          description: >-
            Kredensial telah diterbitkan. Berikan `monitoring_token` ke aplikasi
            dan perlakukan sebagai rahasia hingga `expires_at`.
          content:
            application/json:
              schema:
                type: object
                required:
                  - monitoring_token
                  - expires_at
                  - allowed_event_categories
                  - max_uses
                  - bind_to_origin
                properties:
                  monitoring_token:
                    type: string
                    description: >-
                      Kredensial perangkat (token URL-safe 43 karakter). Kirim
                      kredensial ini di header `X-Monitoring-Token`.
                  expires_at:
                    type: string
                    format: date-time
                    description: Waktu ketika kredensial tidak lagi diterima.
                  allowed_event_categories:
                    type: array
                    items:
                      type: string
                      enum:
                        - auth
                        - session
                        - gameplay
                        - bonus
                        - affiliate
                        - payment
                        - dispute
                        - security
                        - responsible_gambling
                        - custom
                    description: >-
                      Kategori yang dapat dikirimkan oleh kredensial; `[]`
                      berarti setiap kategori.
                  max_uses:
                    type: integer
                    nullable: true
                    description: >-
                      Anggaran peristiwa kredensial; null berarti tidak ada
                      batas.
                  bind_to_origin:
                    type: string
                    nullable: true
                    description: Asal tempat kredensial terikat, atau null.
              example:
                monitoring_token: q7ZtR2xKp9VbN4mWc8LdH1sYfJ3gT6uEaQ0oPiXzBkC
                expires_at: '2026-10-17T09:30:02.481000Z'
                allowed_event_categories:
                  - auth
                  - session
                  - gameplay
                max_uses: 1000
                bind_to_origin: https://app.example.com
        '400':
          description: >-
            Validasi gagal: `vendor_data` tidak ada, `ttl_seconds` di luar 60
            hingga 86400, `max_uses` di bawah 1, atau kategori tidak dikenal
            (diindeks berdasarkan posisinya dalam array).
          content:
            application/json:
              examples:
                Missing vendor_data:
                  value:
                    vendor_data:
                      - This field is required.
                ttl_seconds too short:
                  value:
                    ttl_seconds:
                      - Ensure this value is greater than or equal to 60.
                Unknown category:
                  value:
                    allowed_event_categories:
                      '1':
                        - '"login" is not a valid choice.'
        '401':
          description: >-
            Kunci API dengan cakupan terbatas telah kedaluwarsa. Hanya kunci
            yang kedaluwarsa yang menerima `401`; kunci yang hilang atau tidak
            valid menerima `403`.
          content:
            application/json:
              examples:
                Expired key:
                  value:
                    detail: This API key has expired.
        '403':
          description: >-
            `x-api-key` tidak ada (kunci yang salah, dicabut, atau kedaluwarsa
            menghasilkan `401`), kunci dengan pembatasan cakupan tanpa
            `transactions: write`, kunci yang dibatasi pada alur kerja tertentu
            atau pada sesi yang disetujui (kunci semacam itu tidak pernah
            mengakses data pemantauan transaksi), atau permintaan dari luar
            allowlist IP milik kunci tersebut. Juga dikembalikan dengan `code:
            event_monitoring_disabled` saat penyerapan event dinonaktifkan untuk
            aplikasi; tidak ada yang disimpan dalam kasus tersebut, dan
            pemeriksaan berjalan sebelum body divalidasi.
          content:
            application/json:
              examples:
                Event monitoring disabled:
                  value:
                    detail: >-
                      Event monitoring is not enabled for this application. Turn
                      on event ingestion in the transaction monitoring settings
                      before submitting events.
                    code: event_monitoring_disabled
                Missing or invalid API key:
                  value:
                    detail: You do not have permission to perform this action.
                Scoped key without access:
                  value:
                    detail: This API key has no write access to transactions.
                Key limited to workflows or approved sessions:
                  value:
                    detail: >-
                      This API key only reaches sessions inside its workflow or
                      status limits, so it can't use this endpoint.
                IP not allowed:
                  value:
                    detail: This API key can't be used from this IP address.
        '429':
          description: >-
            Batas laju terlampaui: permintaan tulis (`POST`, `PATCH`, `DELETE`)
            berbagi anggaran sebanyak 300 permintaan per menit per kunci API.
            Tunggu `Retry-After` detik, lalu coba lagi.
          headers:
            Retry-After:
              description: Detik untuk menunggu sebelum mencoba lagi.
              schema:
                type: integer
                minimum: 1
                example: 30
          content:
            application/json:
              examples:
                Throttled:
                  value:
                    detail: >-
                      Write request rate limit exceeded. You can make up to 300
                      requests per minute.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X POST 'https://verification.didit.me/v3/events/sdk-token/' \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "vendor_data": "user-42",
                "allowed_event_categories": ["auth", "session", "gameplay"],
                "ttl_seconds": 900,
                "max_uses": 1000,
                "bind_to_origin": "https://app.example.com"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.monitoring_events.create_sdk_token(
                vendor_data="user-42",
                allowed_event_categories=["auth", "session", "gameplay"],
                ttl_seconds=900,
                max_uses=1000,
                bind_to_origin="https://app.example.com",
            )
            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.monitoringEvents.createSdkToken({
              vendor_data: "user-42",
              allowed_event_categories: ["auth", "session", "gameplay"],
              ttl_seconds: 900,
              max_uses: 1000,
              bind_to_origin: "https://app.example.com",
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.CreateSDKToken(ctx, didit.MonitoringEventsCreateSDKTokenParams{\n\tVendorData:             \"user-42\",\n\tAllowedEventCategories: didit.Some([]didit.MonitoringEventsCreateSDKTokenParamsAllowedEventCategories{\"auth\", \"session\", \"gameplay\"}),\n\tTTLSeconds:             didit.Int(900),\n\tMaxUses:                didit.Int(1000),\n\tBindToOrigin:           didit.String(\"https://app.example.com\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: >-
            import java.util.List;

            import me.didit.Didit;

            import me.didit.types.MonitoringEventsCreateSdkTokenParams;


            // Reads DIDIT_API_KEY.

            Didit client = new Didit();


            var result =
            client.monitoringEvents().createSdkToken(MonitoringEventsCreateSdkTokenParams.builder()
                    .vendorData("user-42")
                    .allowedEventCategories(List.of(MonitoringEventsCreateSdkTokenParams.AllowedEventCategories.of("auth"), MonitoringEventsCreateSdkTokenParams.AllowedEventCategories.of("session"), MonitoringEventsCreateSdkTokenParams.AllowedEventCategories.of("gameplay")))
                    .ttlSeconds(900L)
                    .maxUses(1000L)
                    .bindToOrigin("https://app.example.com")
                    .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->monitoringEvents->createSdkToken([
                'vendor_data' => 'user-42',
                'allowed_event_categories' => ['auth', 'session', 'gameplay'],
                'ttl_seconds' => 900,
                'max_uses' => 1000,
                'bind_to_origin' => 'https://app.example.com',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

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

            result = didit.monitoring_events.create_sdk_token(
              vendor_data: "user-42",
              allowed_event_categories: ["auth", "session", "gameplay"],
              ttl_seconds: 900,
              max_uses: 1000,
              bind_to_origin: "https://app.example.com"
            )
            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.MonitoringEvents.CreateSdkTokenAsync(new
            MonitoringEventsCreateSdkTokenParams

            {
                VendorData = "user-42",
                AllowedEventCategories = new MonitoringEventsCreateSdkTokenParamsAllowedEventCategories[] { "auth", "session", "gameplay" },
                TtlSeconds = 900,
                MaxUses = 1000,
                BindToOrigin = "https://app.example.com",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  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.