> ## 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 Kirim OTP Email: Verifikasi Email

> Kirim kode verifikasi sekali pakai via POST /v3/email/send/ dari Didit. Coba ulang otomatis, berlaku 5 menit, bayar per panggilan, tanpa minimum bulanan.



## OpenAPI

````yaml id/openapi-25.json POST /v3/email/send/
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/email/send/:
    post:
      tags:
        - Standalone APIs
      summary: Kirim Kode Email
      description: >-
        Kirim kode sekali pakai (OTP) ke alamat email, lalu verifikasi dengan
        [`POST /v3/email/check/`](/id/standalone-apis/email-check).


        **Cara kerja pasangan pengiriman dan pemeriksaan.** Status verifikasi
        dikaitkan berdasarkan aplikasi Anda ditambah alamat `email` —
        pemanggilan periksa tidak memerlukan `request_id`. Setiap pengiriman
        baru membuat verifikasi tertunda yang berlaku selama **5 menit**:
        panggil periksa dengan alamat yang sama dan kode yang diterima pengguna
        sebelum batas waktu berakhir. Memanggil pengiriman lagi untuk alamat
        yang sama saat verifikasi masih tertunda akan menghasilkan kode baru
        untuk verifikasi yang sama tersebut (`status: "Retry"`, `request_id`
        yang sama); kode sebelumnya tidak lagi berfungsi. Paling banyak satu
        coba lagi yang dilampirkan dengan cara ini (total dua pengiriman);
        pengiriman berikutnya akan memulai verifikasi baru dengan `request_id`
        baru. Batas waktu 5 menit dihitung dari pengiriman pertama dan tidak
        diperpanjang oleh coba lagi.


        **Pra-pemeriksaan keterkiriman.** Sebelum apa pun dikirim, alamat
        melewati validasi sintaks dan DNS/MX. Alamat yang tidak dapat menerima
        email mengembalikan `200` dengan `status: "Undeliverable"` dan `reason:
        "email_can_not_be_delivered"` — tidak ada email yang dikirim, tidak ada
        biaya yang ditagihkan, dan verifikasi segera diselesaikan sebagai
        `Declined` (pemeriksaan lanjutan mengembalikan `Expired or Not Found`).
        Pengiriman yang gagal karena alasan selain alamat (email tidak dapat
        diserahkan untuk pengiriman) mengembalikan `503`: tidak ada kode yang
        dikirim, tidak ada biaya yang ditagihkan, verifikasi tetap terbuka, dan
        permintaan yang sama dapat diulang kembali.


        **Format kode dan branding.** Kode terdiri dari 4–8 karakter
        (`options.code_size`, default 6), berupa angka secara default; atur
        `options.alphanumeric_code: true` untuk huruf besar dan angka
        (perbandingan saat periksa tidak membedakan huruf besar/kecil). Templat
        email dilokalkan melalui `options.locale` (54 bahasa yang didukung) dan
        dapat menggunakan branding White Label aplikasi Anda melalui
        `options.use_white_label_customization`.


        **Penagihan.** Satu kredit API Verifikasi Email per pengiriman yang
        berhasil (`status: "Success"`), ditagihkan pada saat pengiriman.
        Pengiriman `Retry` dan `Undeliverable` gratis, dan pemeriksaan gratis.


        **Persistensi sesi.** Setiap verifikasi baru disimpan secara persisten
        sebagai sesi bertipe API: `request_id` adalah id sesi nyata yang dapat
        Anda teruskan ke `GET /v3/session/{sessionId}/decision/`, verifikasi
        muncul di Business Console, dan webhook `status.updated` terpicu seiring
        perkembangannya.


        **Sandbox.** Kunci API sandbox melewati pengiriman dan penagihan:
        setelah validasi permintaan (input yang salah format tetap mengembalikan
        `400`), endpoint mengembalikan payload `Success` statis dengan
        `request_id` acak; tidak ada email yang dikirim dan tidak ada yang
        disimpan secara persisten. Gunakan kode `123456` pada pemeriksaan
        sandbox.


        **Autentikasi.** Kirim kunci API aplikasi Anda di header `x-api-key`.
        Kredensial yang hilang atau tidak valid mengembalikan `403` (`{"detail":
        "You do not have permission to perform this action."}`) — API ini tidak
        pernah mengembalikan `401`.


        **Batas laju.** Kuota bersama untuk permintaan tulis sebesar 300
        permintaan/menit per kunci API di seluruh endpoint POST/PATCH/DELETE;
        melebihi batas ini mengembalikan `429`.
      operationId: post_v3email_send
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  description: >-
                    Alamat email penerima. Alamat dengan format yang salah
                    mengembalikan `400`; alamat dengan sintaks yang valid tetapi
                    tidak dapat menerima email (validasi DNS/MX gagal)
                    mengembalikan `200` dengan `status: "Undeliverable"`.
                  example: alice@example.com
                options:
                  type: object
                  description: >-
                    Opsi format, lokalisasi, dan branding OTP. Semua kolom
                    bersifat opsional.
                  properties:
                    code_size:
                      type: integer
                      minimum: 4
                      maximum: 8
                      default: 6
                      description: >-
                        Jumlah karakter dalam OTP (secara default berupa digit;
                        huruf besar dan digit ketika `alphanumeric_code`
                        bernilai `true`).
                    alphanumeric_code:
                      type: boolean
                      default: false
                      description: >-
                        Jika `true`, OTP terdiri dari huruf besar `A–Z` dan
                        angka `0–9`, bukan hanya angka. Perbandingan
                        `/v3/email/check/` bersifat tidak peka huruf
                        besar/kecil.
                    locale:
                      type: string
                      maxLength: 5
                      enum:
                        - en
                        - ar
                        - bn
                        - bg
                        - bs
                        - ca
                        - cs
                        - da
                        - de
                        - el
                        - es
                        - et
                        - fa
                        - fi
                        - fr
                        - he
                        - hi
                        - hr
                        - hu
                        - hy
                        - id
                        - it
                        - ja
                        - ka
                        - kk
                        - ko
                        - ky
                        - lt
                        - lv
                        - cnr
                        - mk
                        - mn
                        - ms
                        - nl
                        - 'no'
                        - pl
                        - pt-BR
                        - pt
                        - ro
                        - ru
                        - sk
                        - sl
                        - so
                        - sq
                        - sr
                        - sv
                        - th
                        - tr
                        - uk
                        - uz
                        - vi
                        - zh-CN
                        - zh-TW
                        - zh
                      description: >-
                        Bahasa templat email OTP. Default adalah `en`. Nilai
                        yang tidak didukung mengembalikan `400` yang
                        mencantumkan semua lokal yang didukung.
                      example: en
                    use_white_label_customization:
                      type: boolean
                      default: false
                      description: >-
                        Jika `true`, email OTP menggunakan kustomisasi White
                        Label aplikasi Anda (logo, warna, branding pengirim)
                        alih-alih templat default Didit.
                signals:
                  type: object
                  description: >-
                    Sinyal perangkat dan jaringan opsional mengenai pengguna
                    akhir, yang diteruskan ke lapisan anti-fraud untuk
                    meningkatkan deteksi lalu lintas yang menyalahgunakan sistem
                    atau dihasilkan secara otomatis. Semua kolom bersifat
                    opsional.
                  properties:
                    ip:
                      type: string
                      description: Alamat IP perangkat pengguna akhir. IPv4 atau IPv6.
                      example: 192.0.2.1
                    device_id:
                      type: string
                      maxLength: 255
                      description: >-
                        Pengenal unik perangkat pengguna akhir. Android:
                        `ANDROID_ID`; iOS: `identifierForVendor`.
                      example: 8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2
                    device_platform:
                      type: string
                      enum:
                        - android
                        - ios
                        - ipados
                        - tvos
                        - web
                      description: Platform perangkat pengguna akhir.
                    device_model:
                      type: string
                      maxLength: 255
                      description: Model perangkat pengguna akhir.
                      example: iPhone17,2
                    os_version:
                      type: string
                      maxLength: 64
                      description: Versi sistem operasi dari perangkat pengguna akhir.
                      example: 18.0.1
                    app_version:
                      type: string
                      maxLength: 64
                      description: Versi aplikasi Anda.
                      example: 1.2.34
                    user_agent:
                      type: string
                      maxLength: 512
                      description: User agent dari browser atau aplikasi pengguna akhir.
                      example: >-
                        Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X)
                        AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3
                        Mobile/15E148 Safari/604.1
                vendor_data:
                  type: string
                  description: >-
                    Pengidentifikasi opsional yang dikontrol pemanggil (id
                    pengguna internal Anda, email, UUID, dll.) yang disimpan
                    pada sesi dan dikembalikan dalam respons pengiriman, respons
                    pemeriksaan kecocokan, webhook, dan Business Console.
                    Gunakan ini untuk menghubungkan `request_id` Didit dengan
                    data pengguna Anda.
                metadata:
                  type: object
                  nullable: true
                  description: >-
                    Objek JSON bentuk bebas opsional yang disimpan pada sesi dan
                    dikembalikan dalam respons pengiriman, respons pemeriksaan
                    pencocokan, webhook, dan Business Console.
              required:
                - email
            examples:
              Numeric 6-digit code:
                summary: Default — kode numerik 6 digit dalam bahasa Inggris
                value:
                  email: alice@example.com
                  options:
                    locale: en
                  vendor_data: user-1234
              Alphanumeric 8-character code:
                summary: Huruf besar + digit, templat Spanyol
                value:
                  email: bob@example.com
                  options:
                    code_size: 8
                    alphanumeric_code: true
                    locale: es
              White-label branding:
                summary: Kirim email OTP dengan kustomisasi White Label aplikasi Anda
                value:
                  email: carol@example.com
                  options:
                    locale: en
                    use_white_label_customization: true
                  vendor_data: user-5678
      responses:
        '200':
          description: >-
            Pengiriman dikonfirmasi. Periksa `status`: `Success` dan `Retry`
            berarti kode sedang dikirim; `Undeliverable` berarti alamat tidak
            dapat menerima surat dan verifikasi telah difinalisasi sebagai
            `Declined`. `request_id` adalah id sesi yang disimpan (id yang sama
            pada `Retry`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailVerificationSendResponse'
              examples:
                Success:
                  summary: OTP dikirimkan melalui email untuk verifikasi baru (ditagih)
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Success
                    reason: null
                    vendor_data: user-1234
                    metadata: null
                Retry:
                  summary: >-
                    Pengiriman kedua dalam jendela 5 menit — kode baru,
                    request_id yang sama, gratis
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Retry
                    reason: null
                    vendor_data: user-1234
                    metadata: null
                Undeliverable:
                  summary: >-
                    Alamat gagal validasi DNS/MX — verifikasi diselesaikan
                    dengan status Ditolak, tidak ada tagihan
                  value:
                    request_id: cb1a5011-344d-444d-bdce-218904745d7f
                    status: Undeliverable
                    reason: email_can_not_be_delivered
                    vendor_data: user-1234
                    metadata: null
        '400':
          description: >-
            Kesalahan validasi — envelope kesalahan kolom DRF: satu array pesan
            per kolom yang bermasalah, bersarang di bawah `options` untuk
            kesalahan opsi.
          content:
            application/json:
              examples:
                Invalid email:
                  summary: Alamat email salah format
                  value:
                    email:
                      - Enter a valid email address.
                Unsupported locale:
                  summary: '`options.locale` berada di luar set yang didukung'
                  value:
                    options:
                      locale:
                        - >-
                          Invalid locale. Supported locales are en, ar, bn, bg,
                          bs, ca, cs, da, de, el, es, et, fa, fi, fr, he, hi,
                          hr, hu, hy, id, it, ja, ka, kk, ko, ky, lt, lv, cnr,
                          mk, mn, ms, nl, no, pl, pt-BR, pt, ro, ru, sk, sl, so,
                          sq, sr, sv, th, tr, uk, uz, vi, zh-CN, zh-TW, zh.
                Code size out of range:
                  summary: '`options.code_size` berada di luar rentang 4–8'
                  value:
                    options:
                      code_size:
                        - Ensure this value is less than or equal to 8.
        '403':
          description: >-
            Izin ditolak. Dikembalikan ketika header `x-api-key` tidak ada
            (`{"detail": ...}`); kunci yang salah, dicabut, atau kedaluwarsa
            mengembalikan `401`. Juga dikembalikan sebelum pengiriman apa pun
            ketika saldo organisasi tidak dapat mencukupi biaya satu kredit API
            Verifikasi Email (`{"error": ...}`).
          content:
            application/json:
              examples:
                Missing or invalid API key:
                  summary: >-
                    Tidak ada header `x-api-key`, atau kuncinya tidak
                    valid/dicabut
                  value:
                    detail: You do not have permission to perform this action.
                Not enough credits:
                  summary: Saldo organisasi tidak mencukupi untuk harga pengiriman
                  value:
                    error: You don't have enough credits to perform this request.
        '429':
          description: >-
            Batas laju terlampaui. Endpoint POST/PATCH/DELETE berbagi anggaran
            300 permintaan penulisan per menit per kunci API (pembuatan
            transaksi dan ingesti event memiliki anggaran terpisah sebesar 600).
            Respons menyertakan header `X-RateLimit-Limit`,
            `X-RateLimit-Remaining`, `X-RateLimit-Reset`, dan `Retry-After`.
          content:
            application/json:
              examples:
                Write rate limit exceeded:
                  summary: Lebih dari 300 permintaan tulis pada menit ini
                  value:
                    detail: >-
                      Write request rate limit exceeded. You can make up to 300
                      requests per minute.
              schema:
                type: object
                properties:
                  detail:
                    type: string
        '503':
          description: >-
            Email tidak dapat dikirim karena alasan yang tidak terkait dengan
            alamat tersebut (penyedia email tidak dapat dihubungi, waktu habis,
            atau menolak pengiriman itu sendiri), sehingga tidak ada kode yang
            dikirim dan tidak ada yang ditagihkan atau dihitung sebagai upaya
            pengiriman. Ulangi permintaan yang sama.
          content:
            application/json:
              examples:
                Email delivery unavailable:
                  summary: Penyedia email gagal setelah satu kali coba lagi otomatis
                  value:
                    detail: >-
                      Email delivery is temporarily unavailable. Please try
                      again.
              schema:
                type: object
                properties:
                  detail:
                    type: string
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X POST https://verification.didit.me/v3/email/send/ \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "email": "alice@example.com",
                "options": { "code_size": 6, "locale": "en" },
                "vendor_data": "user-1234"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.email.send_code(
                email="alice@example.com",
                options={
                    "locale": "en",
                },
                vendor_data="user-1234",
            )
            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.email.sendCode({
              email: "alice@example.com",
              options: {
                locale: "en",
              },
              vendor_data: "user-1234",
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Email.SendCode(ctx, didit.EmailSendCodeParams{\n\tEmail: \"alice@example.com\",\n\tOptions: didit.Some(didit.EmailSendCodeParamsOptions{\n\t\tLocale: didit.Some(didit.EmailSendCodeParamsOptionsLocale(\"en\")),\n\t}),\n\tVendorData: didit.String(\"user-1234\"),\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.EmailSendCodeParams;

            // Reads DIDIT_API_KEY.
            Didit client = new Didit();

            var result = client.email().sendCode(EmailSendCodeParams.builder()
                    .email("alice@example.com")
                    .options(EmailSendCodeParams.Options.builder()
                            .locale(EmailSendCodeParams.Options.Locale.of("en"))
                            .build())
                    .vendorData("user-1234")
                    .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->email->sendCode([
                'email' => 'alice@example.com',
                'options' => [
                    'locale' => 'en',
                ],
                'vendor_data' => 'user-1234',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

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

            result = didit.email.send_code(
              email: "alice@example.com",
              options: {
                locale: "en",
              },
              vendor_data: "user-1234"
            )
            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.Email.SendCodeAsync(new
            EmailSendCodeParams

            {
                Email = "alice@example.com",
                Options = new EmailSendCodeParamsOptions
                {
                    Locale = new EmailSendCodeParamsOptionsLocale("en"),
                },
                VendorData = "user-1234",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    EmailVerificationSendResponse:
      type: object
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            ID sesi verifikasi. Pengiriman `Retry` mengembalikan `request_id`
            yang sama dengan pengiriman asli. ID ini muncul di Business Console,
            dikembalikan lagi oleh `POST /v3/email/check/` yang telah selesai
            diproses, dan dapat diteruskan ke `GET
            /v3/session/{sessionId}/decision/`.
        status:
          type: string
          enum:
            - Success
            - Retry
            - Undeliverable
          description: >-
            `Success` — OTP dikirim via email untuk verifikasi baru (ditagih).
            `Retry` — OTP baru dikirim via email untuk verifikasi tertunda yang
            dibuat dari pengiriman sebelumnya (gratis). `Undeliverable` — alamat
            gagal dalam validasi keterkiriman atau pesan tidak dapat dikirim;
            verifikasi langsung diselesaikan sebagai `Declined` dan tidak ada
            biaya yang ditagih.
        reason:
          type: string
          nullable: true
          enum:
            - email_can_not_be_delivered
            - null
          description: >-
            `email_can_not_be_delivered` ketika `status` bernilai
            `Undeliverable`; selain itu `null`.
        vendor_data:
          type: string
          nullable: true
          description: >-
            Salinan `vendor_data` yang disimpan pada sesi (dari pengiriman
            pertama).
        metadata:
          type: object
          nullable: true
          description: >-
            Salinan `metadata` yang disimpan pada sesi (dari pengiriman
            pertama).
  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.