> ## 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 Membuat Aplikasi: Buat Aplikasi Secara Programatik

> Buat aplikasi Didit per pelanggan, lingkungan, atau unit bisnis via POST /organizations/me/{org_id}/applications/. Mengembalikan client_id dan api_key.



Prompt Pembuatan Aplikasi
        Salin prompt ke papan klip



      
      

\<pre>

\`Create a new Didit application inside one of your organizations — each application has its own client_id and api_key, isolating sessions, webhooks, branding, and billing from sibling applications.

Endpoint:
POST https://apx.didit.me/auth/v2/organizations/me/{org_id}/applications/

Authentication:
Authorization: Bearer <access_token>
The access token must belong to an OWNER or ADMIN of the target organization. Get one via POST /programmatic/login/ or POST /programmatic/verify-email/.

Path parameter:
\- org_id (UUID, required) — Organization that will own the new application. Discover yours via GET /organizations/me/.

Request body (ALL fields optional — omit the body to get a default-named app):
\- name (string, optional) — Display name. Defaults to "<organization name> App".
\- website_url (string, URL, optional) — Public homepage shown in the verification flow.
\- redirect_uris (array of strings, optional) — Allowlisted OAuth-style redirect URIs.
\- terms_url (string, URL, optional) — Terms-of-service link shown in the verification UI.
\- privacy_url (string, URL, optional) — Privacy policy link shown in the verification UI.
\- description (string, optional) — Internal note. Not shown to end users.
\- data_location (string, optional) — Where the application's verification data is stored and processed: "eu" (European Union, Ireland), the default. "au" (Australia, Sydney) and "mx" (Mexico) are coming soon and answer 400 today. Chosen once: it can't be changed after the application is created.

When to call:
\- Resellers — one application per end customer to fully isolate credentials, branding, webhooks, and billing.
\- Multi-brand / multi-product — one application per brand, product, region, or environment (dev / staging / prod).
\- Use-case separation — e.g. one application for ID + selfie KYC, another for AML screening only.

curl example:
curl -X POST "https://apx.didit.me/auth/v2/organizations/me/<ORG_ID>/applications/" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Customer App",
"website_url": "https://acme.example",
"redirect_uris": ["https://acme.example/callback"],
"terms_url": "https://acme.example/terms",
"privacy_url": "https://acme.example/privacy",
"data_location": "eu"
}'

Response (201 Created):
\{
"uuid": "b2c3d4e5-6789-...",
"name": "Acme Customer App",
"client_id": "S9LIYGSoWNuGMLHsvEt9dQ",
"api_key": "sk_live_example_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"website_url": "https://acme.example",
"redirect_uris": ["https://acme.example/callback"],
"terms_url": "https://acme.example/terms",
"privacy_url": "https://acme.example/privacy",
"description": null,
"created_at": "2025-06-01T10:00:00Z",
"data_location": "eu",
"products": [
\{ "product": "identity", "status": "enabled", "modules": { "user_verification": true, "business_verification": true, "case_management": true } },
\{ "product": "transactions", "status": "disabled", "modules": { "travel_rule": true, "case_management": true } },
\{ "product": "authentication", "status": "disabled", "modules": {} }
]
}

What to do with the response:
\- PERSIST api_key SECURELY — use it as the x-api-key header on every https://verification.didit.me/v3/... call (sessions, workflows, billing).
\- Persist uuid (app_id) — required for /organizations/me/{org_id}/applications/{app_id}/ reads and updates.
\- If you lose the api_key, recover it later via GET /organizations/me/{org_id}/applications/{app_id}/ — see /auth-api/get-credentials.
\- products is read-only and always lists identity, transactions and authentication in that order. A new application has identity enabled with every module on, and transactions and authentication disabled. A products key in the request body is ignored.

Failure modes:
\- 400 — { "<field>": ["Enter a valid URL."] } for malformed website_url / redirect_uris / terms_url / privacy_url.
\- 400 — { "data_location": ["This data location is not available yet."] } for "au" or "mx", and { "data_location": ["\\"us\\" is not a valid choice."] } for a location that does not exist. Nothing is created.
\- 401: { "detail": "Invalid access token" } or { "detail": "Expired access token" } when the token is malformed or expired.
\- 403: { "detail": "Only organization owners and admins can manage applications." } when you are a member of the organization but not an owner or admin.
\- 403: { "detail": "Your access to this organization is suspended." } when your membership in the organization is suspended.
\- 403: { "detail": "You do not have permission to perform this action." } when the request has no Authorization header.
\- 404: { "detail": "Organization not found." } when the organization does not exist or you are not a member of it.

Next steps:
\- Configure a workflow inside the new application via POST /v3/workflows/ — see /management-api/workflows/create.
\- Update application metadata later via PATCH /organizations/me/{org_id}/applications/{app_id}/ — see /auth-api/update-application.

For end-to-end Didit integration, paste in the full prompt at /integration/integration-prompt.`

\</pre>



      
      

Tempel ke

Gunakan endpoint ini saat Anda perlu memisahkan trafik verifikasi, kredensial, branding, atau pelaporan dalam organisasi yang sama.Ini sangat berguna untuk **reseller** yang membuat satu aplikasi per pelanggan. Endpoint ini juga cocok ketika perusahaan Anda memiliki beberapa produk, merek, wilayah, lingkungan staging/produksi, atau kasus penggunaan yang tidak boleh berbagi kunci API dan pengaturan tingkat aplikasi yang sama.> [!NOTE]
>
> Semua endpoint Auth API menggunakan `https://apx.didit.me/auth/v2`. Gunakan `api_key` yang dikembalikan sebagai `x-api-key` saat memanggil endpoint `https://verification.didit.me/v3/...` seperti sesi dan alur kerja.## Lokasi dataSetiap aplikasi menyimpan dan memproses data verifikasinya di satu tempat, yaitu lokasi datanya, yang dipilih saat Anda membuat aplikasi dengan `data_location`.
Saat ini satu-satunya lokasi yang tersedia adalah `eu`, Uni Eropa (Irlandia), yang juga menjadi nilai default jika Anda tidak mengisi kolom ini.
Australia (Sydney, `au`) dan Meksiko (`mx`) segera hadir: permintaan yang menyebut lokasi tersebut akan menerima jawaban 400 `This data location is not available yet.` dan tidak ada aplikasi yang dibuat.
Setiap kali aplikasi dibaca, respons menyertakan `data_location`, dan nilai ini tidak dapat diubah setelah aplikasi dibuat.
Lihat [Lokasi data](https://docs.didit.me/id/console/applications.md#lokasi-data).


## OpenAPI

````yaml id/openapi-auth.json POST /organizations/me/{org_id}/applications/
openapi: 3.0.0
info:
  version: 1.0.0
  title: Didit Auth API
  description: >-
    API pendaftaran dan autentikasi terprogram untuk pengembang dan agen AI.
    Daftar dalam 2 panggilan API -- tanpa perlu browser. Platform verifikasi
    identitas yang paling ramah agen.


    ## URL Dasar


    Semua endpoint dalam spesifikasi ini di-hosting di
    `https://apx.didit.me/auth/v2`. Ini adalah host yang berbeda dari API
    verifikasi (`https://verification.didit.me/v3`). Perhatikan perbedaannya:
    host autentikasi ini menerbitkan **token akses JWT** Anda dan memungkinkan
    Anda mencantumkan serta mengelola **organisasi** dan **aplikasi** Anda. Host
    verifikasi adalah tempat Anda memanggil sesi, alur kerja, AML, dll., yang
    diautentikasi dengan **`api_key`** yang dikembalikan oleh API ini.


    ## Cara kerja alur autentikasi


    1. `POST /programmatic/register/` — kirimkan email + kata sandi.

    2. Terima kode alfanumerik 6 karakter melalui email.

    3. `POST /programmatic/verify-email/` — kirimkan kode tersebut. Anda akan
    mendapatkan kembali JWT `access_token`, `refresh_token`, sebuah organisasi,
    dan aplikasi default dengan `client_id` + `api_key`.

    4. Simpan `api_key`. Gunakan sebagai `x-api-key` untuk setiap panggilan ke
    `https://verification.didit.me/v3/...`.

    5. Dari mesin mana pun di masa mendatang, `POST /programmatic/login/`
    menukarkan email + kata sandi Anda dengan JWT baru, lalu panggil `GET
    /organizations/me/` dan endpoint aplikasi untuk memulihkan atau merotasi
    kredensial.


    JWT hanya diperlukan untuk endpoint **Manajemen Akun** dalam spesifikasi
    ini; lalu lintas API verifikasi menggunakan `api_key` yang berjangka
    panjang, bukan JWT.


    ## Konvensi


    - Semua body permintaan dan respons berupa JSON (`Content-Type:
    application/json`).

    - **Gunakan alamat email asli yang dapat menerima pesan saat menguji `POST
    /programmatic/register/`.** Endpoint ini mengirimkan kode verifikasi secara
    sinkron, sehingga alamat pada domain pengujian yang dicadangkan
    (`@example.com`, `@example.org`, `@*.test`, `@*.example`, `@*.invalid`)
    ditolak oleh pengiriman email dan permintaan mengembalikan `500`. Ganti
    placeholder `you@yourdomain.com` dalam contoh dengan kotak masuk yang
    benar-benar dapat Anda baca.

    - Error validasi mengembalikan HTTP `400` dengan salah satu dari dua format:
    `{"field": ["message", ...]}` untuk masalah tingkat kolom, atau `{"detail":
    "message"}` untuk error aturan bisnis. Sejumlah kecil validator (kekuatan
    kata sandi saat mendaftar, kedaluwarsa kode saat verifikasi email) saat ini
    merespons dengan array sederhana `["message"]` alih-alih bentuk dengan kunci
    kolom -- ini adalah inkonsistensi sisi server yang diketahui, sehingga kode
    klien harus menerima kedua bentuk tersebut.

    - Error autentikasi kembali sebagai `{"detail": "..."}` dengan HTTP `401`
    (bearer token tidak valid) atau `403` (bearer token tidak ada / hak istimewa
    tidak memadai).

    - Respons batas laju menyertakan kolom `wait` dengan durasi cooldown dalam
    detik.
servers:
  - url: https://apx.didit.me/auth/v2
    description: Server autentikasi produksi
security: []
tags:
  - name: Programmatic Auth
    description: >-
      Siklus hidup akun dengan email dan kata sandi: daftar, verifikasi, masuk.
      Mengembalikan `access_token` JWT yang Anda gunakan untuk endpoint
      Manajemen Akun, ditambah (saat verifikasi) `client_id` dan `api_key`
      aplikasi pertama Anda.
  - name: Account Management
    description: >-
      Endpoint terautentikasi (JWT bearer) yang mencantumkan organisasi dan
      membuat, mengambil, atau memperbarui aplikasi. Gunakan endpoint ini untuk
      memulihkan atau merotasi `api_key` yang Anda gunakan untuk mengautentikasi
      panggilan API verifikasi.
paths:
  /organizations/me/{org_id}/applications/:
    post:
      tags:
        - Account Management
      summary: Buat Aplikasi
      description: >-
        Buat aplikasi di dalam organisasi, di lokasi data yang Anda pilih
        (`data_location`, Uni Eropa secara default; tidak dapat diubah
        setelahnya). Respons mencakup `api_key`; simpan sekarang (dapat
        dipulihkan melalui GET). Memerlukan JWT milik owner/admin.
      operationId: create_organization_application
      parameters:
        - name: org_id
          in: path
          required: true
          description: UUID organisasi. Cari tahu menggunakan `GET /organizations/me/`.
          schema:
            type: string
            format: uuid
            example: a1b2c3d4-5678-90ab-cdef-111111111111
      requestBody:
        required: false
        description: >-
          Semua kolom bersifat opsional. Menghilangkan isi permintaan akan
          membuat aplikasi dengan nama default `"<organization name> App"` dan
          tanpa URL publik yang dikonfigurasi.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApplicationCreateRequest'
            examples:
              ResellerCustomer:
                summary: Reseller menyiapkan aplikasi dengan cakupan pelanggan
                value:
                  name: Acme Customer App
                  website_url: https://acme.example
                  redirect_uris:
                    - https://acme.example/callback
                  terms_url: https://acme.example/terms
                  privacy_url: https://acme.example/privacy
                  data_location: eu
              Minimal:
                summary: Buat minimal -- terima semua nilai default
                value:
                  name: Sandbox App
              Empty:
                summary: Tidak ada body sama sekali -- default ke <nama org> App
                value: {}
      responses:
        '201':
          description: >-
            Aplikasi dibuat. Respons menyertakan `api_key` jangka panjang;
            simpan sekarang dan gunakan sebagai header `x-api-key` pada setiap
            panggilan `https://verification.didit.me/v3/...`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Application'
              examples:
                Success:
                  value:
                    uuid: b2c3d4e5-6789-01bc-defg-222222222222
                    name: Acme Customer App
                    client_id: S9LIYGSoWNuGMLHsvEt9dQ
                    api_key: sk_live_example_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                    website_url: https://acme.example
                    redirect_uris:
                      - https://acme.example/callback
                    terms_url: https://acme.example/terms
                    privacy_url: https://acme.example/privacy
                    description: null
                    created_at: '2025-06-01T10:00:00Z'
                    data_location: eu
                    products:
                      - product: identity
                        status: enabled
                        modules:
                          user_verification: true
                          business_verification: true
                          case_management: true
                      - product: transactions
                        status: disabled
                        modules:
                          travel_rule: true
                          case_management: true
                      - product: authentication
                        status: disabled
                        modules: {}
        '400':
          description: >-
            Kesalahan validasi pada body permintaan: misalnya URI pengalihan
            salah format, `data_location` yang belum tersedia (`au`, `mx`), atau
            yang tidak ada. Tidak ada yang dibuat.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
              examples:
                InvalidUrl:
                  value:
                    website_url:
                      - Enter a valid URL.
                DataLocationNotAvailable:
                  summary: Lokasi data yang akan segera hadir
                  value:
                    data_location:
                      - This data location is not available yet.
                UnknownDataLocation:
                  summary: Lokasi data yang tidak ada
                  value:
                    data_location:
                      - '"us" is not a valid choice.'
        '401':
          description: >-
            Token akses salah format, tidak valid, atau kedaluwarsa. Dapatkan
            token baru dengan `POST /programmatic/login/`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                InvalidToken:
                  value:
                    detail: Invalid access token
                ExpiredToken:
                  value:
                    detail: Expired access token
        '403':
          description: >-
            Anda tidak dapat membuat aplikasi di organisasi ini. Anggota
            organisasi yang bukan pemilik atau admin mendapatkan `Only
            organization owners and admins can manage applications.` Pemilik
            atau admin yang aksesnya ke organisasi ditangguhkan mendapatkan
            `Your access to this organization is suspended.` Permintaan tanpa
            header `Authorization` mendapatkan `You do not have permission to
            perform this action.` Selama 72 jam setelah Anda memulihkan akun,
            permintaan ditolak dengan `code` `recovery_hold` dan `until`, waktu
            penahanan berakhir.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/AuthError'
                  - $ref: '#/components/schemas/RecoveryHoldError'
              examples:
                NotOwnerOrAdmin:
                  summary: Anggota yang bukan pemilik atau admin
                  value:
                    detail: >-
                      Only organization owners and admins can manage
                      applications.
                Suspended:
                  summary: Keanggotaan ditangguhkan
                  value:
                    detail: Your access to this organization is suspended.
                MissingToken:
                  summary: Tidak ada header Authorization
                  value:
                    detail: You do not have permission to perform this action.
                RecoveryHold:
                  summary: Akun dipulihkan kurang dari 72 jam yang lalu
                  value:
                    detail: This action is on hold because you recovered your account.
                    code: recovery_hold
                    until: '2026-11-04T10:15:00+00:00'
        '404':
          description: Organisasi tidak ada atau Anda bukan anggotanya.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                OrganizationNotFound:
                  summary: Organisasi tidak ditemukan, atau Anda bukan anggota
                  value:
                    detail: Organization not found.
      security:
        - BearerAuth: []
      x-codeSamples:
        - lang: curl
          label: cURL
          source: >-
            curl -X POST
            "https://apx.didit.me/auth/v2/organizations/me/$ORG_ID/applications/"
            \
              -H "Authorization: Bearer $ACCESS_TOKEN" \
              -H "Content-Type: application/json" \
              -d '{
                "name": "Acme Customer App",
                "website_url": "https://acme.example",
                "redirect_uris": ["https://acme.example/callback"],
                "data_location": "eu"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Use the access token that account.login returns.
            client = Didit(account_token="YOUR_ACCESS_TOKEN")

            result = client.account.applications.create(
                "a1b2c3d4-5678-90ab-cdef-111111111111",
                name="Acme Customer App",
                website_url="https://acme.example",
                redirect_uris=["https://acme.example/callback"],
                terms_url="https://acme.example/terms",
                privacy_url="https://acme.example/privacy",
                data_location="eu",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: >-
            import Didit from "@didit-protocol/sdk-node";


            // Use the access token that account.login returns.

            const didit = new Didit({ accountToken: "YOUR_ACCESS_TOKEN" });


            const result = await
            didit.account.applications.create("a1b2c3d4-5678-90ab-cdef-111111111111",
            {
              name: "Acme Customer App",
              website_url: "https://acme.example",
              redirect_uris: ["https://acme.example/callback"],
              terms_url: "https://acme.example/terms",
              privacy_url: "https://acme.example/privacy",
              data_location: "eu",
            });

            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Use the access token that account.login returns.\nclient := didit.NewClient(option.WithAccountToken(\"YOUR_ACCESS_TOKEN\"))\n\nresult, err := client.Account.Applications.Create(ctx, \"a1b2c3d4-5678-90ab-cdef-111111111111\", didit.ApplicationCreateRequest{\n\tName:         didit.String(\"Acme Customer App\"),\n\tWebsiteURL:   didit.String(\"https://acme.example\"),\n\tRedirectURIs: didit.Some([]string{\"https://acme.example/callback\"}),\n\tTermsURL:     didit.String(\"https://acme.example/terms\"),\n\tPrivacyURL:   didit.String(\"https://acme.example/privacy\"),\n\tDataLocation: didit.Some(didit.ApplicationDataLocation(\"eu\")),\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.ApplicationCreateRequest;

            import me.didit.types.ApplicationDataLocation;


            // Use the access token that account.login returns.

            Didit client =
            Didit.builder().accountToken("YOUR_ACCESS_TOKEN").build();


            var result =
            client.account().applications().create("a1b2c3d4-5678-90ab-cdef-111111111111",
            ApplicationCreateRequest.builder()
                    .name("Acme Customer App")
                    .websiteUrl("https://acme.example")
                    .redirectUris(List.of("https://acme.example/callback"))
                    .termsUrl("https://acme.example/terms")
                    .privacyUrl("https://acme.example/privacy")
                    .dataLocation(ApplicationDataLocation.of("eu"))
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: >-
            <?php


            require 'vendor/autoload.php';


            use Didit\DiditClient;


            // Use the access token that account.login returns.

            $didit = new DiditClient(accountToken: 'YOUR_ACCESS_TOKEN');


            $result =
            $didit->account->applications->create('a1b2c3d4-5678-90ab-cdef-111111111111',
            [
                'name' => 'Acme Customer App',
                'website_url' => 'https://acme.example',
                'redirect_uris' => ['https://acme.example/callback'],
                'terms_url' => 'https://acme.example/terms',
                'privacy_url' => 'https://acme.example/privacy',
                'data_location' => 'eu',
            ]);

            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Use the access token that account.login returns.
            didit = Didit::Client.new(account_token: "YOUR_ACCESS_TOKEN")

            result = didit.account.applications.create(
              "a1b2c3d4-5678-90ab-cdef-111111111111",
              name: "Acme Customer App",
              website_url: "https://acme.example",
              redirect_uris: ["https://acme.example/callback"],
              terms_url: "https://acme.example/terms",
              privacy_url: "https://acme.example/privacy",
              data_location: "eu"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Text.Json;

            using Didit;


            // Use the access token that account.login returns.

            using var client = new DiditClient(new DiditClientOptions {
            AccountToken = "YOUR_ACCESS_TOKEN" });


            var result = await
            client.Account.Applications.CreateAsync("a1b2c3d4-5678-90ab-cdef-111111111111",
            new ApplicationCreateRequest

            {
                Name = "Acme Customer App",
                WebsiteUrl = "https://acme.example",
                RedirectUris = new string[] { "https://acme.example/callback" },
                TermsUrl = "https://acme.example/terms",
                PrivacyUrl = "https://acme.example/privacy",
                DataLocation = new ApplicationDataLocation("eu"),
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    ApplicationCreateRequest:
      type: object
      description: >-
        Semua kolom bersifat opsional. Mengirimkan isi permintaan kosong akan
        membuat aplikasi dengan nama default, di Uni Eropa.
      properties:
        name:
          type: string
          description: Nama tampilan aplikasi. Default ke `"<organization name> App"`.
          example: Acme Customer App
        website_url:
          type: string
          description: URL situs web atau aplikasi yang terkait dengan aplikasi ini.
          example: https://acme.example
        redirect_uris:
          type: array
          items:
            type: string
          description: >-
            URI pengalihan yang diizinkan untuk alur pengalihan gaya OAuth dan
            verifikasi.
          example:
            - https://acme.example/callback
        terms_url:
          type: string
          description: URL ketentuan layanan yang ditampilkan dalam alur verifikasi.
          example: https://acme.example/terms
        privacy_url:
          type: string
          description: URL kebijakan privasi yang ditampilkan dalam alur verifikasi.
          example: https://acme.example/privacy
        description:
          type: string
          description: >-
            Deskripsi internal untuk aplikasi (tidak ditampilkan kepada pengguna
            akhir).
        data_location:
          $ref: '#/components/schemas/ApplicationDataLocation'
    Application:
      type: object
      description: >-
        Catatan aplikasi lengkap. Nilai `uuid`, `client_id`, dan `api_key` tidak
        pernah berubah setelah pembuatan. Begitu pula dengan `data_location`,
        kecuali satu kali pada aplikasi produksi yang dibuat bersama organisasi
        Anda, sebelum digunakan (lihat permintaan pembaruan).
      properties:
        uuid:
          type: string
          format: uuid
          description: >-
            UUID aplikasi. Gunakan sebagai `{app_id}` dalam panggilan
            berikutnya.
          example: b2c3d4e5-6789-01bc-defg-222222222222
        name:
          type: string
          description: Nama tampilan aplikasi yang ditampilkan di konsol Didit.
          example: Acme Production App
        client_id:
          type: string
          description: >-
            Pengenal klien publik, aman untuk disematkan dalam alur bergaya
            OAuth.
          example: S9LIYGSoWNuGMLHsvEt9dQ
        api_key:
          type: string
          description: >-
            Rahasia jangka panjang (juga disebut `client_secret`). Gunakan
            sebagai header `x-api-key` untuk setiap panggilan ke
            `https://verification.didit.me/v3/...` (sesi, alur kerja, AML,
            dll.). Perlakukan sebagai kredensial; jangan pernah mengeksposnya di
            sisi klien. Kunci baru diawali dengan `sk_live_` (aplikasi produksi)
            atau `sk_test_` (aplikasi sandbox), diikuti oleh 43 karakter
            aman-URL (huruf, angka, `-`, dan `_`). Kunci yang dibuat sebelum
            format ini tidak memiliki awalan dan tetap berfungsi tanpa
            perubahan. Selama 72 jam setelah Anda memulihkan akun, operasi
            daftar, ambil, dan perbarui mengembalikan string kosong di sini
            alih-alih kunci.
          example: sk_live_example_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        website_url:
          type: string
          nullable: true
          description: URL situs web atau aplikasi yang terkait dengan aplikasi ini.
          example: https://acme.example
        redirect_uris:
          type: array
          items:
            type: string
          description: >-
            URI pengalihan yang diizinkan untuk alur pengalihan gaya OAuth dan
            verifikasi.
          example:
            - https://acme.example/callback
        terms_url:
          type: string
          nullable: true
          description: URL ketentuan layanan yang ditampilkan dalam alur verifikasi.
          example: https://acme.example/terms
        privacy_url:
          type: string
          nullable: true
          description: URL kebijakan privasi yang ditampilkan dalam alur verifikasi.
          example: https://acme.example/privacy
        description:
          type: string
          nullable: true
          description: >-
            Deskripsi internal untuk aplikasi (tidak ditampilkan kepada pengguna
            akhir).
        created_at:
          type: string
          format: date-time
          example: '2025-06-01T10:00:00Z'
        data_location:
          $ref: '#/components/schemas/ApplicationDataLocation'
        products:
          type: array
          readOnly: true
          description: >-
            Produk aplikasi. Selalu ketiganya, dalam urutan ini: `identity`,
            `transactions`, `authentication`. Aplikasi baru memiliki `identity`
            yang diaktifkan dengan semua modul aktif, serta `transactions` dan
            `authentication` dinonaktifkan. Hanya baca: kunci `products` dalam
            body pembuatan atau pembaruan akan diabaikan.
          items:
            $ref: '#/components/schemas/ApplicationProduct'
          example:
            - product: identity
              status: enabled
              modules:
                user_verification: true
                business_verification: true
                case_management: true
            - product: transactions
              status: disabled
              modules:
                travel_rule: true
                case_management: true
            - product: authentication
              status: disabled
              modules: {}
    ValidationError:
      description: >-
        Isi kesalahan validasi. Envelope yang diharapkan adalah pemetaan
        `{field: ["message", ...]}` untuk kesalahan tingkat kolom atau envelope
        kunci tunggal `{detail: "..."}` untuk kesalahan aturan bisnis. Sejumlah
        kecil validator (kekuatan kata sandi saat mendaftar, validitas kode pada
        verifikasi email) saat ini merespons dengan array polos `["message"]` --
        inkonsistensi sisi server yang sudah diketahui. Skema di bawah ini
        mempertahankan cabang array polos tersebut sehingga kode klien yang
        dihasilkan dari spesifikasi ini mendeserialisasi respons saat ini, namun
        kode klien baru harus memperlakukannya sebagai bentuk dengan kunci kolom
        yang relevan (`{password: [...]}` atau `{code: [...]}`) dan kontrak
        server akan disesuaikan ke bentuk tersebut.
      oneOf:
        - type: object
          additionalProperties:
            type: array
            items:
              type: string
          example:
            email:
              - Enter a valid email address.
        - type: object
          properties:
            detail:
              type: string
          example:
            detail: An account with this email already exists.
        - type: array
          items:
            type: string
          example:
            - Invalid or expired verification code.
    AuthError:
      type: object
      description: Struktur respons error autentikasi / otorisasi / tidak ditemukan.
      properties:
        detail:
          type: string
          example: Invalid access token
    RecoveryHoldError:
      type: object
      description: >-
        Dikembalikan selama 72 jam setelah akun dipulihkan (metode masuk yang
        hilang diatur ulang). Tindakan yang membuat organisasi, aplikasi, atau
        rahasia ditolak hingga `until`; operasi baca tetap berfungsi.
      required:
        - detail
        - code
        - until
      properties:
        detail:
          type: string
          example: This action is on hold because you recovered your account.
        code:
          type: string
          enum:
            - recovery_hold
          example: recovery_hold
        until:
          type: string
          format: date-time
          description: >-
            Waktu ketika penahanan berakhir (ISO 8601). Coba lagi permintaan
            setelah waktu ini.
          example: '2026-11-04T10:15:00+00:00'
    ApplicationDataLocation:
      type: string
      enum:
        - eu
        - au
        - mx
      description: >-
        Tempat data verifikasi aplikasi disimpan dan diproses, dipilih saat
        aplikasi dibuat. `eu` adalah Uni Eropa (Irlandia), sebagai default. `au`
        (Australia, Sydney) dan `mx` (Meksiko) akan segera hadir: permintaan
        yang mencantumkannya akan menghasilkan respons 400 `This data location
        is not available yet.` Aplikasi Sandbox suatu organisasi selalu berada
        di Uni Eropa.
      example: eu
    ApplicationProduct:
      type: object
      description: >-
        Satu produk dari suatu aplikasi beserta statusnya. Hanya-baca: endpoint
        aplikasi mengembalikannya dan mengabaikannya dalam body permintaan.
      properties:
        product:
          type: string
          enum:
            - identity
            - transactions
            - authentication
          description: >-
            `identity` (Verifikasi identitas), `transactions` (Pemantauan
            transaksi) atau `authentication` (Autentikasi).
          example: identity
        status:
          type: string
          enum:
            - enabled
            - early_access
            - disabled
          description: >-
            Apakah produk aktif untuk aplikasi ini. `early_access` hanya berlaku
            untuk `authentication`, yang diaktifkan Didit untuk Anda.
          example: enabled
        modules:
          type: object
          additionalProperties:
            type: boolean
          description: >-
            Sakelar modul produk, masing-masing bernilai `true` atau `false`.
            `identity` memiliki `user_verification`, `business_verification`,
            dan `case_management`. `transactions` memiliki `travel_rule` dan
            `case_management`. `authentication` tidak memilikinya (`{}`).
            `case_management` adalah satu pengaturan yang ditampilkan di bawah
            `identity` dan `transactions`, sehingga memiliki nilai yang sama
            pada keduanya.
          example:
            user_verification: true
            business_verification: true
            case_management: true
      required:
        - product
        - status
        - modules
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        `access_token` JWT bertanda tangan RS256 yang dikembalikan oleh `POST
        /programmatic/login/` atau `POST /programmatic/verify-email/`. Kirim
        sebagai `Authorization: Bearer <access_token>`. Masa berlaku default
        adalah 86400 detik (24 jam). Token ini hanya valid untuk endpoint
        Manajemen Akun di `apx.didit.me/auth/v2`. Sebagai gantinya, API
        verifikasi (`verification.didit.me/v3`) menggunakan `api_key` berjangka
        panjang sebagai `x-api-key`.

````

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