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

# Update Application

> Update application metadata (name, URLs, redirect URIs). `api_key` and `client_id` are never rotated. 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="Update Application Prompt"
  prompt={`Partially update one Didit application's metadata (name, public URLs, redirect URIs, description). Credentials (client_id, api_key, uuid) are NEVER changed by this call.

Endpoint:
PATCH https://apx.didit.me/auth/v2/organizations/me/{org_id}/applications/{app_id}/

Authentication:
Authorization: Bearer <access_token>
The access token must belong to an OWNER or ADMIN of the organization.

Path parameters:
- org_id (UUID, required) — Organization that owns the application.
- app_id (UUID, required) — Application UUID to update.

Request body — PATCH semantics. Send ONLY the fields you want to change. Omitted fields are preserved.
- name (string, optional) — Display name.
- website_url (string, URL, optional) — Public homepage.
- redirect_uris (array of strings, optional) — Allowlisted OAuth-style redirect URIs. The array REPLACES the previous value entirely.
- terms_url (string, URL, optional) — Terms-of-service link.
- privacy_url (string, URL, optional) — Privacy policy link.
- description (string, optional) — Internal note (not shown to end users).

What does NOT change:
- uuid, client_id, api_key — credentials stay the same. Existing integrations keep working; no key rotation happens here.

curl example — rename and move to a new domain:
curl -X PATCH "https://apx.didit.me/auth/v2/organizations/me/<ORG_ID>/applications/<APP_ID>/" \\
-H "Authorization: Bearer <ACCESS_TOKEN>" \\
-H "Content-Type: application/json" \\
-d '{
"name": "Acme Production App",
"website_url": "https://app.acme.example"
}'

curl example — add a second redirect URI (full replacement of the array):
curl -X PATCH "https://apx.didit.me/auth/v2/organizations/me/<ORG_ID>/applications/<APP_ID>/" \\
-H "Authorization: Bearer <ACCESS_TOKEN>" \\
-H "Content-Type: application/json" \\
-d '{
"redirect_uris": [
  "https://acme.example/callback",
  "https://staging.acme.example/callback"
]
}'

Response (200 OK):
The full application record after the change (same shape as GET /organizations/me/{org_id}/applications/{app_id}/). uuid, client_id, and api_key are unchanged.

When to call:
- Reseller customer rebrands → rename their application.
- Domain migration → update website_url, terms_url, privacy_url.
- Add or remove a staging redirect URI.
- Refresh terms / privacy URLs shown in the verification flow.

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." } — caller is a member but not an owner or admin.
- 404 — { "detail": "Not found." } — organization or application not found, or caller is not a member.

For end-to-end Didit integration, paste in the full prompt at /integration/integration-prompt.`}
/>

Use this endpoint to keep each application aligned with the customer, brand, environment, or internal use case it represents.

For resellers, this lets you rename or update each customer application without sharing credentials across customers. For direct customers, it helps separate products, regions, or environments while keeping everything under one organization.

<Note>
  This endpoint updates application metadata. The `api_key` stays the same unless you rotate credentials separately.
</Note>


## OpenAPI

````yaml PATCH /organizations/me/{org_id}/applications/{app_id}/
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/{app_id}/:
    patch:
      tags:
        - Account Management
      summary: Update Application
      description: >-
        Update application metadata (name, URLs, redirect URIs). `api_key` and
        `client_id` are never rotated. Requires owner/admin JWT.
      operationId: update_organization_application
      parameters:
        - name: org_id
          in: path
          required: true
          description: UUID of the organization that owns the application.
          schema:
            type: string
            format: uuid
            example: a1b2c3d4-5678-90ab-cdef-111111111111
        - name: app_id
          in: path
          required: true
          description: UUID of the application to update.
          schema:
            type: string
            format: uuid
            example: b2c3d4e5-6789-01bc-defg-222222222222
      requestBody:
        required: true
        description: >-
          Send only the fields you want to change. PATCH semantics: missing
          fields are preserved.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApplicationUpdateRequest'
            examples:
              RenameCustomerApplication:
                summary: Rename and move to a new domain
                value:
                  name: Acme Production App
                  website_url: https://app.acme.example
              UpdateRedirectUris:
                summary: Add a second redirect URI
                value:
                  redirect_uris:
                    - https://acme.example/callback
                    - https://staging.acme.example/callback
              UpdatePolicies:
                summary: Refresh terms and privacy URLs
                value:
                  terms_url: https://acme.example/v2/terms
                  privacy_url: https://acme.example/v2/privacy
      responses:
        '200':
          description: >-
            Application updated. The response is the full application record
            after the change; `uuid`, `client_id`, and `api_key` are unchanged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Application'
              examples:
                Success:
                  value:
                    uuid: b2c3d4e5-6789-01bc-defg-222222222222
                    name: Acme Production App
                    client_id: S9LIYGSoWNuGMLHsvEt9dQ
                    api_key: 05mHcOWL8GathLZlz8oIDawYj9qFAcoSHtz-75PAkuo
                    website_url: https://app.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.
          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 user is a member of the organization but is not an owner or
            admin. Only owners and admins can update 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, application not found in that organization,
            or user is not a member of the organization.
          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 PATCH
            "https://apx.didit.me/auth/v2/organizations/me/$ORG_ID/applications/$APP_ID/"
            \
              -H "Authorization: Bearer $ACCESS_TOKEN" \
              -H "Content-Type: application/json" \
              -d '{
                "name": "Acme Production App",
                "website_url": "https://app.acme.example"
              }'
        - lang: python
          label: Python
          source: |-
            import requests

            resp = requests.patch(
                f"https://apx.didit.me/auth/v2/organizations/me/{org_id}/applications/{app_id}/",
                headers={"Authorization": f"Bearer {access_token}"},
                json={
                    "name": "Acme Production App",
                    "website_url": "https://app.acme.example",
                },
                timeout=10,
            )
            resp.raise_for_status()
            updated = resp.json()
        - lang: javascript
          label: JavaScript
          source: |-
            const resp = await fetch(
              `https://apx.didit.me/auth/v2/organizations/me/${orgId}/applications/${appId}/`,
              {
                method: "PATCH",
                headers: {
                  Authorization: `Bearer ${accessToken}`,
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({
                  name: "Acme Production App",
                  website_url: "https://app.acme.example",
                }),
              },
            );
            if (!resp.ok) throw new Error(`Update app failed: ${resp.status}`);
            const updated = await resp.json();
components:
  schemas:
    ApplicationUpdateRequest:
      type: object
      description: >-
        PATCH body for application metadata. Send only the fields you want to
        change; omitted fields are preserved. `uuid`, `client_id`, and `api_key`
        cannot be updated.
      properties:
        name:
          type: string
          description: Application display name.
          example: Acme Production App
        website_url:
          type: string
          description: Website or app URL associated with this application.
          example: https://app.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.
        privacy_url:
          type: string
          description: Privacy policy URL shown in the verification flow.
        description:
          type: string
          description: Internal description for the application.
    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.

````