> ## 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：Email OTP 一次性验证码

> 通过 Didit 的 POST /v3/email/send/ 发送一次性验证码。无法送达时自动重试，有效期 5 分钟，按量计费，无月度最低消费。



## OpenAPI

````yaml zh/openapi-25.json POST /v3/email/send/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: 身份证件验证 API。使用 x-api-key 请求头进行身份验证。
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/email/send/:
    post:
      tags:
        - Standalone APIs
      summary: 发送邮箱验证码
      description: >-
        向邮箱地址发送一次性验证码（OTP），然后通过 [`POST
        /v3/email/check/`](/zh/standalone-apis/email-check) 进行核验。


        **发送与核验的配对机制。** 验证状态由您的应用加上 `email` 地址作为键，核验调用不需要传入
        `request_id`。每次新的发送都会创建一个处于待处理状态的验证，有效期为 **5
        分钟**：在窗口期关闭前，使用相同的地址以及用户收到的验证码调用核验。在验证处于待处理状态期间再次针对同一地址调用发送，会为该同一验证生成一个全新验证码（`status:
        "Retry"`，相同的
        `request_id`）；先前的验证码随即失效。通过这种方式最多可关联一次重试（共两次发送）；后续再次发送则会开启一个带有全新
        `request_id` 的新验证。5 分钟的有效窗口从首次发送开始计算，不会因重试而延长。


        **可投递性预检。** 在发送任何内容之前，该地址都会通过语法以及 DNS/MX 验证。无法接收邮件的地址将返回 `200`，且
        `status: "Undeliverable"`，`reason:
        "email_can_not_be_delivered"`：不会发送任何邮件，不收取任何费用，并且该验证会立即定为
        `Declined`（后续核验将返回 `Expired or Not Found`）。如果发送因非地址原因失败（邮件无法交接投递），则返回
        `503`：不会发送验证码，不收取任何费用，验证保持开启状态，并且可以重复相同的请求。


        **验证码格式与品牌定制。** 验证码长度为 4–8 个字符（`options.code_size`，默认为 6），默认是纯数字；设置
        `options.alphanumeric_code: true` 可使用大写字母和数字（核验比对不区分大小写）。邮件模板可通过
        `options.locale` 进行本地化（支持 54 种语言），并可通过
        `options.use_white_label_customization` 使用您应用的白标品牌定制。


        **计费。** 每次成功发送（`status: "Success"`）消耗一个邮箱验证 API 额度，在发送时扣费。`Retry` 和
        `Undeliverable` 发送免费，核验免费。


        **会话持久化。** 每次新验证都会作为 API 类型的会话进行持久化：`request_id` 是一个真实的会话 ID，您可以将其传递给
        `GET /v3/session/{sessionId}/decision/`，该验证会显示在 Business Console
        中，并且随着流程推进会触发 `status.updated` Webhook。


        **沙盒。** 沙盒 API 密钥跳过投递和计费：在请求验证后（格式错误的输入仍返回 `400`），endpoint 返回带有随机
        `request_id` 的静态 `Success` payload；不会发送邮件，也不持久化任何内容。在沙盒核验中使用验证码
        `123456`。


        **身份验证。** 在 `x-api-key` 请求头中发送您应用的 API 密钥。缺失或无效的凭据将返回 `403`（`{"detail":
        "You do not have permission to perform this action."}`），此 API 从不返回
        `401`。


        **速率限制。** 每个 API 密钥在所有 POST/PATCH/DELETE endpoint 间共享 300
        个请求/分钟的写入预算；超出将返回 `429`。
      operationId: post_v3email_send
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                  format: email
                  description: >-
                    收件人邮箱地址。格式错误的地址返回 `400`；语法有效但无法接收邮件（DNS/MX 验证失败）的地址返回
                    `200`，且 `status: "Undeliverable"`。
                  example: alice@example.com
                options:
                  type: object
                  description: 一次性验证码格式、本地化及品牌化选项。所有字段均为可选。
                  properties:
                    code_size:
                      type: integer
                      minimum: 4
                      maximum: 8
                      default: 6
                      description: >-
                        OTP 中的字符数（默认为数字；当 `alphanumeric_code` 为 `true`
                        时为大写字母和数字）。
                    alphanumeric_code:
                      type: boolean
                      default: false
                      description: >-
                        为 `true` 时，一次性验证码由大写字母 `A–Z` 和数字 `0–9`
                        组成，而非仅包含数字。`/v3/email/check/` 比对不区分大小写。
                    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: OTP 邮件模板的语言。默认为 `en`。不支持的值将返回 `400` 并列出所有支持的语言环境。
                      example: en
                    use_white_label_customization:
                      type: boolean
                      default: false
                      description: >-
                        为 `true` 时，一次性验证码邮件将使用您应用的白标定制（logo、配色、发送方品牌标识），而非默认的
                        Didit 模板。
                signals:
                  type: object
                  description: 关于终端用户的可选设备与网络信号，转发至反欺诈层以提升对滥用或自动化流量的检测能力。所有字段均为可选。
                  properties:
                    ip:
                      type: string
                      description: 终端用户设备的 IP 地址。IPv4 或 IPv6。
                      example: 192.0.2.1
                    device_id:
                      type: string
                      maxLength: 255
                      description: >-
                        终端用户设备的唯一标识符。Android：`ANDROID_ID`；iOS：`identifierForVendor`。
                      example: 8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2
                    device_platform:
                      type: string
                      enum:
                        - android
                        - ios
                        - ipados
                        - tvos
                        - web
                      description: 终端用户设备的平台。
                    device_model:
                      type: string
                      maxLength: 255
                      description: 终端用户设备的型号。
                      example: iPhone17,2
                    os_version:
                      type: string
                      maxLength: 64
                      description: 终端用户设备的操作系统版本。
                      example: 18.0.1
                    app_version:
                      type: string
                      maxLength: 64
                      description: 您的应用版本。
                      example: 1.2.34
                    user_agent:
                      type: string
                      maxLength: 512
                      description: 终端用户浏览器或应用的 User-Agent。
                      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: >-
                    由调用方控制的可选标识符（您的内部用户 id、邮箱、UUID
                    等），在会话中持久化并在发送响应、匹配检查响应、Webhook 和 Business Console
                    中原样返回。可使用它将 Didit 的 `request_id` 与您的用户记录进行关联。
                metadata:
                  type: object
                  nullable: true
                  description: >-
                    可选的自由格式 JSON 对象，持久化保存在会话中，并在发送响应、匹配检查响应、Webhook 以及 Business
                    Console 中回显。
              required:
                - email
            examples:
              Numeric 6-digit code:
                summary: 默认 — 英文 6 位数字验证码
                value:
                  email: alice@example.com
                  options:
                    locale: en
                  vendor_data: user-1234
              Alphanumeric 8-character code:
                summary: 大写字母 + 数字，西班牙模板
                value:
                  email: bob@example.com
                  options:
                    code_size: 8
                    alphanumeric_code: true
                    locale: es
              White-label branding:
                summary: 发送带有您应用白标定制的 OTP 邮件
                value:
                  email: carol@example.com
                  options:
                    locale: en
                    use_white_label_customization: true
                  vendor_data: user-5678
      responses:
        '200':
          description: >-
            已确认发送。请检查 `status`：`Success` 和 `Retry` 表示验证码正在发送中；`Undeliverable`
            表示该地址无法接收邮件，且验证已最终确定为 `Declined`。`request_id` 是持久化的会话 ID（在 `Retry` 时
            ID 相同）。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailVerificationSendResponse'
              examples:
                Success:
                  summary: 已为新验证发送一次性验证码邮件（计费）
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Success
                    reason: null
                    vendor_data: user-1234
                    metadata: null
                Retry:
                  summary: 在 5 分钟时间窗口内的第二次发送：新验证码，相同的 request_id，免费
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Retry
                    reason: null
                    vendor_data: user-1234
                    metadata: null
                Undeliverable:
                  summary: 地址未通过 DNS/MX 验证，验证最终状态为已拒绝，不会产生费用
                  value:
                    request_id: cb1a5011-344d-444d-bdce-218904745d7f
                    status: Undeliverable
                    reason: email_can_not_be_delivered
                    vendor_data: user-1234
                    metadata: null
        '400':
          description: 验证错误 — DRF 的字段错误包装格式：每个违规字段对应一个消息数组，对于选项错误则嵌套在 `options` 下。
          content:
            application/json:
              examples:
                Invalid email:
                  summary: 邮箱地址格式错误
                  value:
                    email:
                      - Enter a valid email address.
                Unsupported locale:
                  summary: '`options.locale` 不在支持的集合内'
                  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` 超出 4–8 范围'
                  value:
                    options:
                      code_size:
                        - Ensure this value is less than or equal to 8.
        '403':
          description: >-
            权限被拒绝。当缺少 `x-api-key` 请求头时返回（`{"detail": ...}`）；错误、已撤销或已过期的密钥返回
            `401`。当组织的余额无法覆盖单次邮箱验证 API 额度时，也会在任何发送之前返回（`{"error": ...}`）。
          content:
            application/json:
              examples:
                Missing or invalid API key:
                  summary: 缺少 `x-api-key` 请求头，或者密钥无效/已被吊销
                  value:
                    detail: You do not have permission to perform this action.
                Not enough credits:
                  summary: 组织余额不足以支付发送价格
                  value:
                    error: You don't have enough credits to perform this request.
        '429':
          description: >-
            超出速率限制。POST/PATCH/DELETE endpoint 每个 API 密钥每分钟共享 300
            次写入请求的额度（交易创建和事件摄入具有单独的 600 次额度）。响应包含
            `X-RateLimit-Limit`、`X-RateLimit-Remaining`、`X-RateLimit-Reset` 和
            `Retry-After` 响应头。
          content:
            application/json:
              examples:
                Write rate limit exceeded:
                  summary: 当前分钟内的写入请求超过 300 次
                  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: >-
            由于与地址无关的原因（无法连接邮件服务商、超时或拒绝发送本身）导致电子邮件无法发送，因此未发送验证码，也不会产生计费或计入发送尝试次数。请重复相同的请求。
          content:
            application/json:
              examples:
                Email delivery unavailable:
                  summary: 自动重试一次后，邮件服务商仍然失败
                  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。`Retry` 发送会返回与原始发送相同的 `request_id`。此 id 会显示在 Business
            Console 中，在已完成的 `POST /v3/email/check/` 中再次返回，并可传递给 `GET
            /v3/session/{sessionId}/decision/`。
        status:
          type: string
          enum:
            - Success
            - Retry
            - Undeliverable
          description: >-
            `Success`：OTP 已通过邮件发送至新的验证（计费）。`Retry`：为先前发送创建的待处理验证重新发送了新的
            OTP（免费）。`Undeliverable`：地址未通过可达性核验或消息无法发送；验证立即以 `Declined`
            终结，且不产生计费。
        reason:
          type: string
          nullable: true
          enum:
            - email_can_not_be_delivered
            - null
          description: >-
            当 `status` 为 `Undeliverable` 时为 `email_can_not_be_delivered`；否则为
            `null`。
        vendor_data:
          type: string
          nullable: true
          description: 存储在会话中的 `vendor_data` 回显（来自首次发送）。
        metadata:
          type: object
          nullable: true
          description: 存储在会话中的 `metadata` 回显（来自首次发送）。
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        您的应用 API 密钥，可在 Business Console 的“开发者 -> API
        密钥”中获取。主密钥拥有完整访问权限。指定名称的密钥可设置作用域：针对每个资源设为无权限、只读或读写，限定于特定工作流或已通过的会话、限定于
        IP 地址列表，以及设置到期日期。401 表示密钥错误、已撤销或已过期；403 表示未发送密钥、密钥无权访问该资源或操作，或请求来自其 IP
        列表之外的地址；在会话路由上返回 404 表示该会话不在该密钥允许的工作流或状态范围内。没有媒体访问权限的密钥获取到的图片、视频和 PDF
        URL 将为 null；没有会话写入权限的密钥获取到的会话链接和 token 将为 null。请参阅
        https://docs.didit.me/console/api-keys。

````

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