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

# Konfigurasi OpenID Didit | Didit Authentication API

> GET /.well-known/openid-configuration mengembalikan dokumen discovery OpenID Connect aplikasi Anda: issuer, endpoint, grant, ES256, dan claim di Didit.

> [!WARNING]
>
> Autentikasi adalah fitur baru. Endpoint ini dilayani oleh penerbit aplikasi Anda, misalnya `https://<name>.auth.didit.me`, dan tidak pernah menerima kunci API Didit Anda.

Ambil informasi discovery dari penerbit yang Anda konfigurasikan, jangan pernah dari URL yang Anda baca di dalam token. Respons dapat di-cache selama 5 menit. Lihat [Token dan JWKS](https://docs.didit.me/id/authentication/tokens-and-jwks.md#penemuan-dan-kunci) untuk makna setiap kolom bagi integrasi Anda.


## OpenAPI

````yaml id/openapi-authentication.json GET /.well-known/openid-configuration
openapi: 3.0.3
info:
  title: Didit Authentication API
  version: 1.0.0
  description: >-
    Endpoint yang menghadap ke server dari Didit Authentication, produk masuk
    (sign-in) untuk pengguna akhir aplikasi Anda. Authentication adalah fitur
    **baru** dan akan tersedia di lingkungan produksi pada rilis 2026-11-01.


    ## Base URL


    Setiap aplikasi adalah penerbit (issuer) OpenID Connect miliknya sendiri,
    dan setiap endpoint di bawah ini dilayani di root dari penerbit tersebut:


    - `https://<name>.auth.didit.me` untuk aplikasi live, atau
    `https://<name>.sandbox.auth.didit.me` untuk aplikasi sandbox.

    - Domain kustom Anda sendiri, setelah aktif. Domain tersebut kemudian
    menggantikan host default sebagai penerbit: token baru mencantumkannya di
    `iss`, discovery mengarah ke sana, dan kunci yang dapat dipublikasikan
    berubah. Token akses yang diterbitkan di bawah host default akan gagal di
    `/session/`, `/step-up/`, dan `/monitoring-token/` hingga token tersebut
    diperbarui.


    Lingkungan live dan sandbox adalah aplikasi terpisah, sehingga keduanya
    merupakan penerbit terpisah dengan kunci terpisah. Kunci yang dapat
    dipublikasikan adalah `pk_live_` (live) atau `pk_test_` (sandbox) diikuti
    oleh encoding base64url tanpa padding dari penerbit, tanpa garis miring
    penutup: lakukan decode untuk menemukan penerbitnya. Kunci ini adalah
    pengidentifikasi publik, bukan kredensial.


    Endpoint JSON yang sama juga dilayani di bawah
    `https://apx.didit.me/auth/v2/authentication/{application_id}/`. Token
    selalu mencantumkan penerbit di atas, alamat mana pun yang menerbitkannya.


    ## Kredensial


    Endpoint ini tidak pernah menerima kunci API Didit Anda atau token konsol.


    - Discovery, JWKS, dan `POST /token/` tidak memerlukan kredensial. Klien
    bersifat publik: tidak ada client secret, dan kode otorisasi terikat pada
    verifier PKCE-nya (`S256`). `client_id` adalah ID aplikasi Anda.

    - `/session/`, `/step-up/`, dan `/monitoring-token/` menerima token akses
    pengguna: `Authorization: Bearer <access_token>`. Setiap panggilan yang
    berhasil dihitung sebagai aktivitas pada sesi, sehingga memulai ulang batas
    waktu tidak aktif (idle timeout) sesi tersebut.


    ## Body permintaan


    Setiap endpoint yang menerima body mendukung format JSON, form-encoded, dan
    multipart. Dokumen ini mencantumkan JSON, ditambah form-encoded untuk `POST
    /token/` sebagaimana yang dikirimkan oleh klien OAuth. Kolom yang tidak
    diterima oleh endpoint akan menghasilkan `400 {"<field>": "unknown_field"}`.


    ## Token


    - **Token akses**: JWT ES256 dengan header `typ: at+jwt`, berlaku paling
    lama 5 menit dan tidak pernah lebih lama dari sesinya. Klaim:
    `AccessTokenClaims`.

    - **Token ID**: JWT ES256 dengan header `typ: JWT`. Klaim: `IDTokenClaims`.
    Token ini tidak pernah diterima sebagai token akses.

    - **Token pembaruan**: string acak yang dirotasi pada setiap penggunaan.
    Mengirimkan token pembaruan yang sudah digunakan kembali akan mencabut sesi.


    Verifikasi token dengan kunci dari `GET /.well-known/jwks.json`: algoritma
    harus berupa `ES256`, `typ` harus cocok dengan tipe token, `iss` harus sama
    dengan penerbit yang Anda konfigurasikan, dan `aud` harus sama dengan ID
    aplikasi Anda. Verifikasi offline hanya melihat sesi yang dicabut setelah
    token aksesnya kedaluwarsa; `GET /session/` adalah pemeriksaan instan.


    ## Error


    | Body | Kapan |

    | --- | --- |

    | `{"error": "<code>"}` | Error dari `POST /token/`, semuanya dengan status
    `400`, dalam bentuk body [RFC 6749 bagian
    5.2](https://www.rfc-editor.org/rfc/rfc6749#section-5.2): `invalid_grant`,
    `invalid_client`, dan `mfa_required` dari Didit. Error layanan:
    `temporarily_unavailable`, `monitoring_unavailable`, `monitoring_disabled`.
    |

    | `{"<field>": ["<message>"]}` atau `{"<field>": "<code>"}` | Kolom
    permintaan gagal divalidasi. `non_field_errors` menunjukkan aturan lintas
    kolom, dan `unknown_field` menunjukkan kolom yang tidak diterima oleh
    endpoint. |

    | `{"detail": "<message>"}` | `401` (`invalid_token`), `403`
    (`origin_not_allowed`), `404` (aplikasi atau step-up tidak dikenal), dan
    `429` (batas laju). Juga `400` untuk body yang tidak dapat di-parse (`JSON
    parse error - ...`), `405` untuk metode yang tidak dilayani oleh endpoint,
    dan `415` untuk `Content-Type` yang tidak didukung. |


    Status `401` juga membawa `WWW-Authenticate: Bearer`, dan `429` membawa
    `Retry-After` dalam detik.


    Ada dua penolakan yang bukan berupa JSON. Alamat yang bukan merupakan
    penerbit akan ditolak sebelum mencapai endpoint ini, misalnya dengan `404`
    kosong untuk nama `*.auth.didit.me` yang tidak digunakan. `step_up_id` yang
    bukan merupakan UUID akan menghasilkan halaman `404`.


    ## Batas laju


    Sebuah permintaan harus melewati dua lapisan.


    **Batas endpoint**, dihitung per alamat IP klien, per aplikasi, dan per
    endpoint:


    - Discovery dan JWKS: 1,200 permintaan per menit dan 12,000 per jam.

    - Setiap endpoint lainnya: 30 permintaan per menit dan 300 per jam. `GET`
    dan `DELETE /session/` berbagi satu hitungan.


    Melebihi batas: `429 {"detail": "Too many requests from this IP address.
    Please wait before trying again. Expected available in 60 seconds."}`, atau
    `3600 seconds` untuk batas per jam.


    **Proteksi bot**, pada setiap `POST` dan `DELETE`. Bucket-nya digunakan
    bersama oleh semua permintaan `POST` dan `DELETE` aplikasi, termasuk langkah
    masuk yang di-hosting, dan diisi ulang terus-menerus:


    - 60 permintaan per menit per alamat IP klien.

    - 30 permintaan per menit per perangkat, untuk permintaan yang
    mengidentifikasi perangkatnya, seperti yang dilakukan oleh SDK browser dan
    native.

    - 3,000 permintaan per menit untuk seluruh aplikasi, di seluruh alamat IP.
    Pembaruan token (`POST /token/` dengan `grant_type=refresh_token`)
    menggunakan bucket tersendiri: 6,000 per menit untuk seluruh aplikasi.


    Melebihi bucket: `429 {"detail": "rate_limited Expected available in N
    seconds."}` (`1 second.` jika N bernilai 1). Bucket per IP mencakup seluruh
    endpoint, sehingga satu alamat yang mencampur panggilan token, step-up, dan
    keluar (sign-out) dapat mengosongkannya sebelum mencapai batas endpoint apa
    pun. Bucket aplikasi menghitung setiap klien dari aplikasi tersebut,
    termasuk browser.


    Kedua lapisan merespons sebelum endpoint dijalankan, sehingga permintaan
    yang mendapatkan `429` tidak dijalankan: coba lagi setelah `Retry-After`,
    termasuk pembaruan.


    ## Permintaan browser


    Permintaan yang membawa header `Origin` harus berasal dari salah satu origin
    milik aplikasi itu sendiri atau origin yang diizinkan, atau akan mendapatkan
    `403 origin_not_allowed`. Permintaan server-ke-server tidak mengirimkan
    `Origin`.


    ## Tidak dibahas di sini


    Rute-rute ini melayani halaman yang di-hosting, SDK browser dan native,
    serta agen AI. Rute ini bukan bagian dari kontrak server, dan SDK server
    tidak memanggilnya:


    - Langkah masuk: `POST /authorize/`, `POST /password/`, `/email/*`,
    `/phone/*`, `/password-reset/*`, `/passkeys/*`, `/mfa/*`, `/social/*`, dan
    `/protection/complete/`.

    - Halaman yang di-hosting dan callback: `/sign-in`, `/magic`, `/invite`,
    `/reset`, `/verify/`, `/sso/*`, `/wallet/callback/`, `/logo/`, serta file
    asosiasi aplikasi native di bawah `/.well-known/`.

    - Akses agen: `/agents/*` dan `/grants/`, termasuk `GET /agents/session/`,
    pemeriksaan live untuk token akses agen AI. Akses agen bukan bagian dari
    versi kontrak ini.

    - API manajemen konsol untuk Authentication, yang menggunakan sesi konsol.


    Event Authentication belum dikirimkan sebagai webhook, sehingga dokumen ini
    tidak mendefinisikan webhook apa pun.
servers:
  - url: https://{issuer}
    description: 'Penerbit aplikasi Anda: asal proses masuknya.'
    variables:
      issuer:
        default: your-app.auth.didit.me
        description: >-
          Host penerbit: `<name>.auth.didit.me` (produksi),
          `<name>.sandbox.auth.didit.me` (sandbox), atau domain kustom aktif
          Anda.
security: []
tags:
  - name: Issuer
    description: Kunci penemuan dan penandatanganan, untuk memverifikasi token.
  - name: Tokens
    description: Grant untuk kode otorisasi dan refresh.
  - name: Sessions
    description: Periksa dan akhiri sesi yang terkait dengan token akses.
  - name: Step-ups
    description: Verifikasi sebelum tindakan sensitif.
  - name: Monitoring
    description: Kredensial perangkat untuk event pemantauan transaksi.
paths:
  /.well-known/openid-configuration:
    get:
      tags:
        - Issuer
      summary: Dapatkan konfigurasi OpenID
      description: >-
        Dokumen penemuan penerbit: endpoint, grant, algoritma penandatanganan,
        dan klaimnya. Ambil dari penerbit yang Anda konfigurasikan, jangan
        pernah dari URL yang ditemukan di dalam token. Simpan di cache hingga 5
        menit, sesuai petunjuk `Cache-Control`.
      operationId: authentication_get_openid_configuration
      responses:
        '200':
          description: Dokumen penemuan.
          headers:
            Cache-Control:
              description: >-
                `public, max-age=300`: Anda dan cache bersama dapat menyimpan
                respons yang berhasil selama 5 menit, yaitu masa berlaku satu
                token akses.
              schema:
                type: string
                example: public, max-age=300
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OpenIDConfiguration'
              examples:
                Discovery:
                  summary: Aplikasi live
                  value:
                    issuer: https://your-app.auth.didit.me
                    authorization_endpoint: https://your-app.auth.didit.me/sign-in
                    token_endpoint: https://your-app.auth.didit.me/token/
                    jwks_uri: https://your-app.auth.didit.me/.well-known/jwks.json
                    response_types_supported:
                      - code
                    response_modes_supported:
                      - query
                    grant_types_supported:
                      - authorization_code
                      - refresh_token
                    subject_types_supported:
                      - public
                    id_token_signing_alg_values_supported:
                      - ES256
                    token_endpoint_auth_methods_supported:
                      - none
                    code_challenge_methods_supported:
                      - S256
                    scopes_supported:
                      - openid
                      - email
                      - phone
                      - profile
                      - offline_access
                    claims_supported:
                      - iss
                      - aud
                      - sub
                      - sid
                      - auth_time
                      - nonce
                      - vendor_data
                      - amr
                      - org
                      - verified
                      - act
                      - email
                      - email_verified
                      - name
                      - phone_number
        '403':
          $ref: '#/components/responses/OriginNotAllowed'
        '404':
          $ref: '#/components/responses/ApplicationNotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/TemporarilyUnavailable'
      security:
        - {}
components:
  schemas:
    OpenIDConfiguration:
      type: object
      description: >-
        Dokumen penemuan OpenID Connect penerbit. Baca endpoint dari sini
        daripada menyusunnya secara manual.
      required:
        - issuer
        - authorization_endpoint
        - token_endpoint
        - jwks_uri
        - response_types_supported
        - response_modes_supported
        - grant_types_supported
        - subject_types_supported
        - id_token_signing_alg_values_supported
        - token_endpoint_auth_methods_supported
        - code_challenge_methods_supported
        - scopes_supported
        - claims_supported
      properties:
        issuer:
          type: string
          format: uri
          description: >-
            Penerbit: origin proses masuk aplikasi, tanpa garis miring di akhir.
            `iss` setiap token sama dengannya.
          example: https://your-app.auth.didit.me
        authorization_endpoint:
          type: string
          format: uri
          description: Halaman masuk yang di-hosting (`/sign-in`).
          example: https://your-app.auth.didit.me/sign-in
        token_endpoint:
          type: string
          format: uri
          example: https://your-app.auth.didit.me/token/
        jwks_uri:
          type: string
          format: uri
          example: https://your-app.auth.didit.me/.well-known/jwks.json
        response_types_supported:
          type: array
          items:
            type: string
          example:
            - code
        response_modes_supported:
          type: array
          items:
            type: string
          example:
            - query
        grant_types_supported:
          type: array
          items:
            type: string
          example:
            - authorization_code
            - refresh_token
        subject_types_supported:
          type: array
          items:
            type: string
          example:
            - public
        id_token_signing_alg_values_supported:
          type: array
          items:
            type: string
          example:
            - ES256
        token_endpoint_auth_methods_supported:
          type: array
          items:
            type: string
          description: '`none`: klien bersifat publik dan tidak mengirimkan rahasia.'
          example:
            - none
        code_challenge_methods_supported:
          type: array
          items:
            type: string
          example:
            - S256
        scopes_supported:
          type: array
          items:
            type: string
          example:
            - openid
            - email
            - phone
            - profile
            - offline_access
        claims_supported:
          type: array
          items:
            type: string
          example:
            - iss
            - aud
            - sub
            - sid
            - auth_time
            - nonce
            - vendor_data
            - amr
            - org
            - verified
            - act
            - email
            - email_verified
            - name
            - phone_number
    Detail:
      type: object
      required:
        - detail
      properties:
        detail:
          type: string
          example: invalid_token
    OAuthError:
      title: OAuth error
      type: object
      description: Error OAuth (RFC 6749 bagian 5.2) atau error layanan.
      required:
        - error
      properties:
        error:
          type: string
          example: invalid_grant
  responses:
    OriginNotAllowed:
      description: >-
        Permintaan membawa `Origin` yang bukan milik aplikasi dan tidak terdapat
        dalam daftar origin yang diizinkan. Permintaan server tidak mengirimkan
        `Origin`.
      headers:
        Cache-Control:
          description: 'Selalu `no-store`: jangan pernah menyimpan respons ini dalam cache.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Selalu `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            OriginNotAllowed:
              summary: Asal tidak diizinkan
              value:
                detail: origin_not_allowed
    ApplicationNotFound:
      description: >-
        Alamat milik suatu aplikasi, tetapi Autentikasi tidak aktif untuk
        aplikasi tersebut; pada alamat `apx.didit.me`, ID aplikasi tidak
        diketahui. Alamat yang bukan milik aplikasi mana pun ditolak sebelum
        mencapai endpoint, dan respons tersebut bukan JSON.
      headers:
        Cache-Control:
          description: 'Selalu `no-store`: jangan pernah menyimpan respons ini dalam cache.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Selalu `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            ApplicationNotFound:
              summary: Aplikasi tidak dikenal
              value:
                detail: No Configuration matches the given query.
    RateLimited:
      description: >-
        Terlalu banyak permintaan dari alamat ini untuk endpoint ini, atau, pada
        `POST` atau `DELETE`, bucket perlindungan bot kosong. Tidak ada yang
        dijalankan: tunggu selama `Retry-After` detik, lalu coba lagi.
      headers:
        Retry-After:
          description: Detik untuk menunggu sebelum mencoba lagi.
          schema:
            type: integer
            example: 60
        Cache-Control:
          description: 'Selalu `no-store`: jangan pernah menyimpan respons ini dalam cache.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Selalu `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Detail'
          examples:
            RateLimited:
              summary: Batas endpoint
              value:
                detail: >-
                  Too many requests from this IP address. Please wait before
                  trying again. Expected available in 60 seconds.
            BotProtection:
              summary: Batas perlindungan bot (POST dan DELETE)
              value:
                detail: rate_limited Expected available in 2 seconds.
    TemporarilyUnavailable:
      description: >-
        Layanan yang dibutuhkan permintaan sedang tidak tersedia untuk
        sementara. Coba lagi dengan backoff.
      headers:
        Cache-Control:
          description: 'Selalu `no-store`: jangan pernah menyimpan respons ini dalam cache.'
          schema:
            type: string
            example: no-store
        Pragma:
          description: Selalu `no-cache`.
          schema:
            type: string
            example: no-cache
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/OAuthError'
          examples:
            TemporarilyUnavailable:
              summary: Coba lagi nanti
              value:
                error: temporarily_unavailable

````

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