> ## 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：程序化创建 Didit 应用

> Didit 的 POST /organizations/me/{org_id}/applications/ 接口可为每个客户、品牌、环境或业务单元创建一个应用，并返回 client_id 和 api_key。



创建应用提示词
        将提示词复制到剪贴板



      
      

\<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>



      
      

粘贴到

当你需要在同一组织内分离验证流量、凭证、品牌设置或报表时，请使用此 endpoint。这对于为每位客户创建一个应用的**经销商**尤其有用。当你的公司拥有多个产品、品牌、地区、预发布/生产环境，或某些使用场景不应共享同一 API 密钥和应用级设置时，此 endpoint 同样适用。> [!NOTE]
>
> 所有 Auth API endpoint 均使用 `https://apx.didit.me/auth/v2`。调用 `https://verification.didit.me/v3/...` endpoint（例如会话和工作流）时，请将返回的 `api_key` 作为 `x-api-key` 使用。## 数据位置每个应用都会将其验证数据存储并处理在一个位置，即其数据位置；该位置在创建应用时通过 `data_location` 选择。
目前唯一可用的位置是 `eu`，即欧盟（爱尔兰）。若省略该字段，则默认使用此位置。
澳大利亚（悉尼，`au`）和墨西哥（`mx`）即将推出。若请求中指定这些位置，将返回 400 `This data location is not available yet.`，且不会创建应用。
读取应用时都会返回其 `data_location`，且应用创建后无法更改该位置。
详见 [数据位置](https://docs.didit.me/zh/console/applications.md#数据所在地)。


## OpenAPI

````yaml zh/openapi-auth.json POST /organizations/me/{org_id}/applications/
openapi: 3.0.0
info:
  version: 1.0.0
  title: Didit Auth API
  description: >-
    面向开发者和 AI 代理的程序化注册与认证 API。仅需 2 次 API 调用即可完成注册，无需浏览器。对代理最友好的身份证件验证平台。


    ## Base URL


    本规范中的所有 endpoint 均托管在 `https://apx.didit.me/auth/v2`。该主机与验证
    API（`https://verification.didit.me/v3`）不同。请务必区分它们：此认证主机负责签发您的 **JWT 访问
    token**，并允许您列出和管理您的**组织**与**应用**。验证主机则是您调用会话、工作流、AML 等服务的地方，使用此 API 返回的
    **`api_key`** 进行身份验证。


    ## 认证流程运作方式


    1. `POST /programmatic/register/`：提交邮箱 + 密码。

    2. 通过电子邮件接收 6 位字母数字验证码。

    3. `POST /programmatic/verify-email/`：提交验证码。您将获得 JWT
    `access_token`、`refresh_token`、一个组织以及带有 `client_id` + `api_key` 的默认应用。

    4. 保存 `api_key`。在对 `https://verification.didit.me/v3/...` 的每次调用中将其作为
    `x-api-key` 使用。

    5. 在将来的任何机器上，`POST /programmatic/login/` 都可以用您的邮箱 + 密码换取全新的 JWT，然后调用 `GET
    /organizations/me/` 和应用 endpoint 来恢复或轮换凭据。


    JWT 仅在用于本规范中的**账户管理** endpoint 时需要；验证 API 的流量使用的是长期有效的 `api_key`，而非 JWT。


    ## 约定


    - 所有请求体和响应体均为 JSON（`Content-Type: application/json`）。

    - **在测试 `POST /programmatic/register/` 时，请使用真实、可投递的电子邮件地址。** 该 endpoint
    会同步发送验证码，因此保留测试域名（`@example.com`、`@example.org`、`@*.test`、`@*.example`、`@*.invalid`）的地址将被邮件发送系统拒绝，且请求将返回
    `500`。请将示例中的占位符 `you@yourdomain.com` 替换为您实际可以查收的收件箱。

    - 验证错误返回 HTTP `400`，具有以下两种外层结构之一：针对字段级问题的 `{"field": ["message",
    ...]}`，或针对业务规则错误的 `{"detail":
    "message"}`。少数验证器（注册时的密码强度、验证邮箱时的验证码过期）目前会响应纯数组 `["message"]`
    而不是以字段为键的形式，这是已知的服务端不一致性，因此客户端代码应同时支持这两种结构。

    - 身份验证错误将作为 `{"detail": "..."}` 返回，状态码为 HTTP `401`（无效的 bearer token）或
    `403`（缺少 bearer token / 权限不足）。

    - 速率限制响应包含一个以秒为单位的冷却时间字段 `wait`。
servers:
  - url: https://apx.didit.me/auth/v2
    description: 生产环境认证服务器
security: []
tags:
  - name: Programmatic Auth
    description: >-
      邮箱和密码账户生命周期：注册、验证、登录。返回用于访问账户管理 endpoint 的 JWT
      `access_token`，并在验证通过时一并返回您首个应用的 `client_id` 和 `api_key`。
  - name: Account Management
    description: >-
      用于列出组织以及创建、获取或更新应用的经认证 endpoint（JWT bearer）。使用这些 endpoint 可以恢复或轮换用于验证 API
      调用身份的 `api_key`。
paths:
  /organizations/me/{org_id}/applications/:
    post:
      tags:
        - Account Management
      summary: 创建应用
      description: >-
        在组织内创建应用，数据驻留位置由您选择（`data_location`，默认为欧盟；创建后不可更改）。响应中包含
        `api_key`；请立即持久化保存该密钥（可通过 GET 重新获取）。需要所有者/管理员 JWT。
      operationId: create_organization_application
      parameters:
        - name: org_id
          in: path
          required: true
          description: 组织的 UUID。使用 `GET /organizations/me/` 查询。
          schema:
            type: string
            format: uuid
            example: a1b2c3d4-5678-90ab-cdef-111111111111
      requestBody:
        required: false
        description: 所有字段均为可选。省略请求体将创建一个默认名称为 `"<organization name> App"` 且未配置公开 URL 的应用。
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApplicationCreateRequest'
            examples:
              ResellerCustomer:
                summary: 分销商创建客户专属应用
                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: 极简创建 -- 接受所有默认值
                value:
                  name: Sandbox App
              Empty:
                summary: 完全没有请求正文：默认使用 <org name> App
                value: {}
      responses:
        '201':
          description: >-
            应用已创建。响应包含长期有效的 `api_key`；请立即将其持久化保存，并在每次调用
            `https://verification.didit.me/v3/...` 时将其用作 `x-api-key` 请求头。
          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: >-
            请求体中存在验证错误：例如重定向 URI 格式错误、`data_location`
            尚未开放（`au`、`mx`）或不存在。未创建任何内容。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
              examples:
                InvalidUrl:
                  value:
                    website_url:
                      - Enter a valid URL.
                DataLocationNotAvailable:
                  summary: 即将推出的数据位置
                  value:
                    data_location:
                      - This data location is not available yet.
                UnknownDataLocation:
                  summary: 不存在的数据位置
                  value:
                    data_location:
                      - '"us" is not a valid choice.'
        '401':
          description: 访问 token 格式错误、无效或已过期。请使用 `POST /programmatic/login/` 获取新 token。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                InvalidToken:
                  value:
                    detail: Invalid access token
                ExpiredToken:
                  value:
                    detail: Expired access token
        '403':
          description: >-
            您无法在此组织中创建应用。非所有者或管理员的组织成员将收到 `Only organization owners and admins
            can manage applications.`。对组织的访问权限被暂停的所有者或管理员将收到 `Your access to
            this organization is suspended.`。不带 `Authorization` 请求头的请求将收到 `You
            do not have permission to perform this action.`。在您恢复账户后的 72
            小时内，请求将被拒绝，返回 `code` 为 `recovery_hold` 以及冻结结束时间 `until`。
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/AuthError'
                  - $ref: '#/components/schemas/RecoveryHoldError'
              examples:
                NotOwnerOrAdmin:
                  summary: 非所有者或管理员的成员
                  value:
                    detail: >-
                      Only organization owners and admins can manage
                      applications.
                Suspended:
                  summary: 成员资格已暂停
                  value:
                    detail: Your access to this organization is suspended.
                MissingToken:
                  summary: 无 Authorization 请求头
                  value:
                    detail: You do not have permission to perform this action.
                RecoveryHold:
                  summary: 账户恢复时间距今不到 72 小时
                  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: 组织不存在，或者您不是该组织的成员。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                OrganizationNotFound:
                  summary: 未找到组织，或者您不是该组织的成员
                  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: 所有字段均为可选。发送空请求体将在欧盟地区创建一个包含默认名称的应用。
      properties:
        name:
          type: string
          description: 应用显示名称。默认为 `"<organization name> App"`。
          example: Acme Customer App
        website_url:
          type: string
          description: 与此应用关联的网站或应用 URL。
          example: https://acme.example
        redirect_uris:
          type: array
          items:
            type: string
          description: OAuth 风格及验证重定向流程允许的重定向 URI。
          example:
            - https://acme.example/callback
        terms_url:
          type: string
          description: 在验证流程中显示的服务条款 URL。
          example: https://acme.example/terms
        privacy_url:
          type: string
          description: 在验证流程中显示的隐私政策 URL。
          example: https://acme.example/privacy
        description:
          type: string
          description: 应用的内部描述（不对终端用户显示）。
        data_location:
          $ref: '#/components/schemas/ApplicationDataLocation'
    Application:
      type: object
      description: >-
        完整应用记录。`uuid`、`client_id` 和 `api_key` 在创建后永不更改。`data_location`
        同样不会更改，除非在随您的组织创建的生产环境应用被投入使用之前修改一次（参见更新请求）。
      properties:
        uuid:
          type: string
          format: uuid
          description: 应用 UUID。在后续调用中用作 `{app_id}`。
          example: b2c3d4e5-6789-01bc-defg-222222222222
        name:
          type: string
          description: 在 Didit 控制台中显示的应用显示名称。
          example: Acme Production App
        client_id:
          type: string
          description: 公开客户端标识符，可安全嵌入 OAuth 风格的流程中。
          example: S9LIYGSoWNuGMLHsvEt9dQ
        api_key:
          type: string
          description: >-
            长期有效的密钥（也称为 `client_secret`）。在对
            `https://verification.didit.me/v3/...` 的每次调用（会话、工作流、AML 等）中作为
            `x-api-key` 请求头使用。请妥善作为凭据保管，切勿在客户端暴露。新密钥以 `sk_live_`（生产环境应用）或
            `sk_test_`（沙盒应用）开头，后接 43 个 URL 安全字符（字母、数字、`-` 和
            `_`）。在此格式之前创建的密钥没有前缀，仍可继续使用。在恢复账户后的 72
            小时内，此处的列表、检索和更新接口将返回空字符串而不是密钥。
          example: sk_live_example_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        website_url:
          type: string
          nullable: true
          description: 与此应用关联的网站或应用 URL。
          example: https://acme.example
        redirect_uris:
          type: array
          items:
            type: string
          description: OAuth 风格及验证重定向流程允许的重定向 URI。
          example:
            - https://acme.example/callback
        terms_url:
          type: string
          nullable: true
          description: 在验证流程中显示的服务条款 URL。
          example: https://acme.example/terms
        privacy_url:
          type: string
          nullable: true
          description: 在验证流程中显示的隐私政策 URL。
          example: https://acme.example/privacy
        description:
          type: string
          nullable: true
          description: 应用的内部描述（不对终端用户显示）。
        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: >-
            该应用的产品。始终包含全部三项，顺序如下：`identity`、`transactions`、`authentication`。新创建的应用会默认启用
            `identity` 及其所有模块，并禁用 `transactions` 和
            `authentication`。只读：创建或更新请求体中的 `products` 键将被忽略。
          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: >-
        验证错误主体。预期的包装格式为针对字段级错误的 `{field: ["message", ...]}` 映射，或针对业务规则错误的
        `{detail: "..."}` 单键包装格式。少数验证器（注册时的密码强度、邮箱验证时的验证码有效性）当前会返回单纯的数组
        `["message"]`（已知的服务端不一致情况）。以下架构保留了该单纯数组分支，以便根据本规范生成的客户端代码可以反序列化当前的响应，但新的客户端代码应将其视为以相关字段为键的形式（`{password:
        [...]}` 或 `{code: [...]}`），服务端契约也将逐步统一为该结构。
      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: 认证 / 授权 / 未找到错误响应封装。
      properties:
        detail:
          type: string
          example: Invalid access token
    RecoveryHoldError:
      type: object
      description: 在账户恢复（重置丢失的登录方式）后 72 小时内返回。在 `until` 之前，创建组织、应用或密钥的操作将被拒绝；读取操作仍可正常工作。
      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: 暂停结束的时间（ISO 8601）。请在此时间之后重试请求。
          example: '2026-11-04T10:15:00+00:00'
    ApplicationDataLocation:
      type: string
      enum:
        - eu
        - au
        - mx
      description: >-
        应用验证数据的存储和处理位置，在创建应用时选择。`eu` 为欧盟（爱尔兰），即默认值。`au`（澳大利亚，悉尼）和
        `mx`（墨西哥）即将推出：指定这些位置的请求将返回 400 `This data location is not available
        yet.`。组织的沙盒应用始终位于欧盟。
      example: eu
    ApplicationProduct:
      type: object
      description: 应用的一个产品及其状态。只读：应用相关 endpoint 会返回该字段，并在请求体中忽略它。
      properties:
        product:
          type: string
          enum:
            - identity
            - transactions
            - authentication
          description: '`identity`（身份证件验证）、`transactions`（交易监控）或 `authentication`（身份验证）。'
          example: identity
        status:
          type: string
          enum:
            - enabled
            - early_access
            - disabled
          description: 该产品是否已为该应用开启。`early_access` 仅适用于 `authentication`，由 Didit 为您开启。
          example: enabled
        modules:
          type: object
          additionalProperties:
            type: boolean
          description: >-
            产品的模块开关，每个为 `true` 或 `false`。`identity` 包含
            `user_verification`、`business_verification` 和
            `case_management`。`transactions` 包含 `travel_rule` 和
            `case_management`。`authentication` 无任何开关（`{}`）。`case_management`
            是同时显示在 `identity` 和 `transactions` 下的单一设置，因此在两者上具有相同的值。
          example:
            user_verification: true
            business_verification: true
            case_management: true
      required:
        - product
        - status
        - modules
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        由 `POST /programmatic/login/` 或 `POST /programmatic/verify-email/` 返回的
        RS256 签名 JWT `access_token`。作为 `Authorization: Bearer <access_token>`
        发送。默认有效期为 86400 秒（24 小时）。该 token 仅对 `apx.didit.me/auth/v2` 上的账户管理
        endpoint 有效。验证 API（`verification.didit.me/v3`）改用长效的 `api_key` 作为
        `x-api-key`。

````

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