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

# Create Application

> Create an application inside an organization. The response includes `api_key`; persist it now (recoverable via GET). Requires owner/admin JWT.

export const AgentPromptAccordion = ({prompt, title = "AI Agent Integration Prompt"}) => {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = e => {
    e.stopPropagation();
    if (!prompt) return;
    navigator.clipboard.writeText(prompt.trim()).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };
  const agents = ["Claude Code", "Codex", "Cursor", "Devin", "Windsurf", "GitHub Copilot"];
  return <div className="didit-agent-card">
      {}
      <div className="didit-agent-titlebar">
        <div className="didit-agent-dots" aria-hidden="true">
          <span className="didit-agent-dot didit-agent-dot-red"></span>
          <span className="didit-agent-dot didit-agent-dot-yellow"></span>
          <span className="didit-agent-dot didit-agent-dot-green"></span>
        </div>
        <span className="didit-agent-filename">{title}</span>
        <button type="button" className={`didit-agent-copy ${copied ? "didit-agent-copy-copied" : ""}`} onClick={handleCopy} title="Copy prompt to clipboard" aria-label={copied ? "Copied!" : "Copy prompt to clipboard"}>
          {copied ? <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              <span>Copied</span>
            </> : <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <rect x="5" y="5" width="9" height="9" rx="1.5" stroke="currentColor" strokeWidth="1.5" />
                <path d="M11 5V3.5A1.5 1.5 0 0 0 9.5 2h-6A1.5 1.5 0 0 0 2 3.5v6A1.5 1.5 0 0 0 3.5 11H5" stroke="currentColor" strokeWidth="1.5" />
              </svg>
              <span>Copy</span>
            </>}
        </button>
      </div>

      {}
      <pre className="didit-agent-body"><code>{prompt.trim()}</code></pre>

      {}
      <div className="didit-agent-footer">
        <span className="didit-agent-footer-label">Paste into</span>
        <div className="didit-agent-chips">
          {agents.map(name => <span key={name} className="didit-agent-chip">{name}</span>)}
        </div>
      </div>
    </div>;
};

<AgentPromptAccordion
  title="Create Application Prompt"
  prompt={`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.

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"
}'

Response (201 Created):
{
"uuid": "b2c3d4e5-6789-...",
"name": "Acme Customer App",
"client_id": "S9LIYGSoWNuGMLHsvEt9dQ",
"api_key": "05mHcOWL8GathLZlz8oIDawYj9qFAcoSHtz-75PAkuo",
"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"
}

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.

Failure modes:
- 400 — { "<field>": ["Enter a valid URL."] } for malformed website_url / redirect_uris / terms_url / privacy_url.
- 401 — { "detail": "Invalid access token" } — token missing, malformed, or expired.
- 403 — { "detail": "You do not have permission to perform this action." } — the user is a member of the organization but not an owner or admin.
- 404 — { "detail": "Not found." } — organization not found or you are not a member.

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.`}
/>

Use this endpoint when you need to separate verification traffic, credentials, branding, or reporting inside the same organization.

This is especially useful for **resellers** that create one application per customer. It also works well when your own company has multiple products, brands, regions, staging/production environments, or use cases that should not share the same API key and application-level settings.

<Note>
  All Auth API endpoints use `https://apx.didit.me/auth/v2`. Use the returned `api_key` as `x-api-key` when calling `https://verification.didit.me/v3/...` endpoints such as sessions and workflows.
</Note>


## OpenAPI

````yaml POST /organizations/me/{org_id}/applications/
openapi: 3.0.0
info:
  version: 1.0.0
  title: Didit Auth API
  description: >-
    Programmatic registration and authentication API for developers and AI
    agents. Register in 2 API calls -- no browser needed. The most
    agent-friendly identity verification platform.


    ## Base URL


    All endpoints in this spec are hosted at `https://apx.didit.me/auth/v2`.
    This is a different host than the verification API
    (`https://verification.didit.me/v3`). Keep them straight: this auth host
    issues your **JWT access tokens** and lets you list and manage your
    **organizations** and **applications**. The verification host is where you
    call sessions, workflows, AML, etc., authenticated with the **`api_key`**
    returned by this API.


    ## How the auth flow works


    1. `POST /programmatic/register/` — submit email + password.

    2. Receive a 6-character alphanumeric code by email.

    3. `POST /programmatic/verify-email/` — submit the code. You get back a JWT
    `access_token`, a `refresh_token`, an organization, and a default
    application with `client_id` + `api_key`.

    4. Save the `api_key`. Use it as `x-api-key` for every call to
    `https://verification.didit.me/v3/...`.

    5. From any future machine, `POST /programmatic/login/` exchanges your email
    + password for a fresh JWT, then call `GET /organizations/me/` and the
    application endpoints to recover or rotate credentials.


    The JWT is only needed for the **Account Management** endpoints in this
    spec; verification API traffic uses the long-lived `api_key`, not the JWT.


    ## Conventions


    - All request and response bodies are JSON (`Content-Type:
    application/json`).

    - **Use a real, deliverable email address when testing `POST
    /programmatic/register/`.** The endpoint sends the verification code
    synchronously, so addresses on reserved test domains (`@example.com`,
    `@example.org`, `@*.test`, `@*.example`, `@*.invalid`) are refused by mail
    delivery and the request returns a `500`. Substitute the
    `you@yourdomain.com` placeholder in the samples with an inbox you can
    actually read.

    - Validation errors return HTTP `400` with one of two envelopes: `{"field":
    ["message", ...]}` for field-level problems, or `{"detail": "message"}` for
    business-rule errors. A handful of validators (password strength on
    register, code expiry on verify-email) currently respond with a bare array
    `["message"]` instead of the field-keyed form -- this is a known server-side
    inconsistency, so client code should accept both shapes.

    - Authentication errors come back as `{"detail": "..."}` with HTTP `401`
    (invalid bearer token) or `403` (missing bearer token / insufficient
    privileges).

    - Rate-limit responses include a `wait` field with the cooldown in seconds.
servers:
  - url: https://apx.didit.me/auth/v2
    description: Production auth server
security: []
tags:
  - name: Programmatic Auth
    description: >-
      Email-and-password account lifecycle: register, verify, login. Returns the
      JWT `access_token` you use against the Account Management endpoints, plus
      (on verify) your first application's `client_id` and `api_key`.
  - name: Account Management
    description: >-
      Authenticated endpoints (JWT bearer) that list organizations and create,
      fetch, or update applications. Use these to recover or rotate the
      `api_key` you authenticate verification API calls with.
paths:
  /organizations/me/{org_id}/applications/:
    post:
      tags:
        - Account Management
      summary: Create Application
      description: >-
        Create an application inside an organization. The response includes
        `api_key`; persist it now (recoverable via GET). Requires owner/admin
        JWT.
      operationId: create_organization_application
      parameters:
        - name: org_id
          in: path
          required: true
          description: UUID of the organization. Look it up with `GET /organizations/me/`.
          schema:
            type: string
            format: uuid
            example: a1b2c3d4-5678-90ab-cdef-111111111111
      requestBody:
        required: false
        description: >-
          All fields are optional. Omitting the body creates an application with
          default name `"<organization name> App"` and no public URLs
          configured.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApplicationCreateRequest'
            examples:
              ResellerCustomer:
                summary: Reseller spinning up a customer-scoped application
                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
              Minimal:
                summary: Minimal create -- accept all defaults
                value:
                  name: Sandbox App
              Empty:
                summary: No body at all -- defaults to <org name> App
                value: {}
      responses:
        '201':
          description: >-
            Application created. The response includes the long-lived `api_key`;
            persist it now and use it as the `x-api-key` header on every
            `https://verification.didit.me/v3/...` call.
          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: 05mHcOWL8GathLZlz8oIDawYj9qFAcoSHtz-75PAkuo
                    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'
        '400':
          description: >-
            Validation error in the request body (for example a malformed
            redirect URI).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
              examples:
                InvalidUrl:
                  value:
                    website_url:
                      - Enter a valid URL.
        '401':
          description: Access token missing, malformed, or expired.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                InvalidToken:
                  value:
                    detail: Invalid access token
        '403':
          description: >-
            The authenticated user is a member of the organization but is not an
            owner or admin. Only owners and admins can create applications.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                Forbidden:
                  value:
                    detail: You do not have permission to perform this action.
        '404':
          description: >-
            Organization not found, or the authenticated user is not a member of
            it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              examples:
                NotFound:
                  value:
                    detail: 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"]
              }'
        - lang: python
          label: Python
          source: |-
            import requests

            resp = requests.post(
                f"https://apx.didit.me/auth/v2/organizations/me/{org_id}/applications/",
                headers={"Authorization": f"Bearer {access_token}"},
                json={
                    "name": "Acme Customer App",
                    "website_url": "https://acme.example",
                    "redirect_uris": ["https://acme.example/callback"],
                },
                timeout=10,
            )
            resp.raise_for_status()
            app = resp.json()
            print("Save this:", app["api_key"])
        - lang: javascript
          label: JavaScript
          source: |-
            const resp = await fetch(
              `https://apx.didit.me/auth/v2/organizations/me/${orgId}/applications/`,
              {
                method: "POST",
                headers: {
                  Authorization: `Bearer ${accessToken}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  name: "Acme Customer App",
                  website_url: "https://acme.example",
                  redirect_uris: ["https://acme.example/callback"],
                }),
              },
            );
            if (!resp.ok) throw new Error(`Create app failed: ${resp.status}`);
            const app = await resp.json();
            console.log("Save this:", app.api_key);
components:
  schemas:
    ApplicationCreateRequest:
      type: object
      description: >-
        All fields are optional. Sending an empty body creates an application
        with a default name.
      properties:
        name:
          type: string
          description: Application display name. Defaults to `"<organization name> App"`.
          example: Acme Customer App
        website_url:
          type: string
          description: Website or app URL associated with this application.
          example: https://acme.example
        redirect_uris:
          type: array
          items:
            type: string
          description: >-
            Allowed redirect URIs for OAuth-style and verification redirect
            flows.
          example:
            - https://acme.example/callback
        terms_url:
          type: string
          description: Terms of service URL shown in the verification flow.
          example: https://acme.example/terms
        privacy_url:
          type: string
          description: Privacy policy URL shown in the verification flow.
          example: https://acme.example/privacy
        description:
          type: string
          description: Internal description for the application (not shown to end users).
    Application:
      type: object
      description: >-
        Full application record. `uuid`, `client_id`, and `api_key` never change
        after creation.
      properties:
        uuid:
          type: string
          format: uuid
          description: Application UUID. Use as `{app_id}` in subsequent calls.
          example: b2c3d4e5-6789-01bc-defg-222222222222
        name:
          type: string
          description: Application display name shown in the Didit console.
          example: Acme Production App
        client_id:
          type: string
          description: Public client identifier, safe to embed in OAuth-style flows.
          example: S9LIYGSoWNuGMLHsvEt9dQ
        api_key:
          type: string
          description: >-
            Long-lived secret (also called `client_secret`). Use as the
            `x-api-key` header for every call to
            `https://verification.didit.me/v3/...` (sessions, workflows, AML,
            etc.). Treat as a credential; never expose client-side.
          example: 05mHcOWL8GathLZlz8oIDawYj9qFAcoSHtz-75PAkuo
        website_url:
          type: string
          nullable: true
          description: Website or app URL associated with this application.
          example: https://acme.example
        redirect_uris:
          type: array
          items:
            type: string
          description: >-
            Allowed redirect URIs for OAuth-style and verification redirect
            flows.
          example:
            - https://acme.example/callback
        terms_url:
          type: string
          nullable: true
          description: Terms of service URL shown in the verification flow.
          example: https://acme.example/terms
        privacy_url:
          type: string
          nullable: true
          description: Privacy policy URL shown in the verification flow.
          example: https://acme.example/privacy
        description:
          type: string
          nullable: true
          description: Internal description for the application (not shown to end users).
        created_at:
          type: string
          format: date-time
          example: '2025-06-01T10:00:00Z'
    ValidationError:
      description: >-
        Validation error body. The intended envelope is a `{field: ["message",
        ...]}` map for field-level errors or a `{detail: "..."}` single-key
        envelope for business-rule errors. A handful of validators (password
        strength on register, code validity on verify-email) currently respond
        with a bare array `["message"]` -- known server-side inconsistency. The
        schema below keeps that bare-array branch so client code generated from
        this spec deserializes today's responses, but new client code should
        treat it as the relevant field-keyed form (`{password: [...]}` or
        `{code: [...]}`) and the server contract will converge on that shape.
      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: Authentication / authorization / not-found error envelope.
      properties:
        detail:
          type: string
          example: Invalid access token
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        RS256-signed JWT `access_token` returned by `POST /programmatic/login/`
        or `POST /programmatic/verify-email/`. Send as `Authorization: Bearer
        <access_token>`. Default lifetime is 86400 seconds (24h). This token is
        only valid against the Account Management endpoints on
        `apx.didit.me/auth/v2`. The verification API
        (`verification.didit.me/v3`) uses the long-lived `api_key` as
        `x-api-key` instead.

````