> ## 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 Webhook Configuration

> Change the application-level webhook, rotate its secret, set data and biometric-template retention, and register Digital ID wallet return hosts.



Update Webhook Configuration API Prompt
        Copy prompt to clipboard



      
      

\<pre>

\`Update my Didit application's webhook configuration through the Management API.

Endpoint:
PATCH https://verification.didit.me/v3/webhook/

Authentication:
Use the x-api-key header with my Didit API key. A scoped API key needs webhooks: write.

Goal:
\- Change application-level settings: the legacy webhook URL and version, the application secret, the data-retention and biometric-template retention policy, or the Digital ID wallet return hosts.

Behavior:
\- Partial update: send only the fields to change. The response is the full configuration, the same shape as GET /v3/webhook/.
\- webhook_url and webhook_version change the application-level (legacy) webhook only. Didit uses it only while the application has no enabled destination, and only for status.updated and data.updated. It does not create a destination, and the next create, update or delete of a destination replaces webhook_url. To receive webhooks, create a destination with POST /v3/webhook/destinations/ instead.
\- rotate_secret_key: true replaces the application-level secret_shared_key immediately. Destination secrets are not changed. Each call generates a new secret, so it is not idempotent.
\- data_retention_months (1 to 120, or null for no automatic deletion): user verification sessions older than this many 30-day months are deleted automatically. Business verification sessions are not affected.
\- face_retention_policy (delete_with_session or retain_until_user_deleted) and face_retention_days (1 to 3650). retain_until_user_deleted needs face_retention_days in the same request or already set.
\- allowed_return_hosts replaces the registered list: up to 20 bare hostnames such as app.example.com (no scheme, port, path or wildcard). Send [] to clear it.
\- Manage destinations with the /v3/webhook/destinations/ endpoints, not here. Never send an endpoints field to this call: it is not part of this contract.

Example call:
curl -X PATCH "https://verification.didit.me/v3/webhook/" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"face_retention_policy": "retain_until_user_deleted", "face_retention_days": 365}'

What to read from the response:
\- The updated fields, and secret_shared_key when you rotated it: store the new value before you discard the response.

Failure modes:
\- 400: field errors, each field mapped to a list of messages, for example { "face_retention_days": ["A finite retention duration is required when face retention is enabled."] }. Nothing is changed.
\- 401: { "detail": "This API key has expired." }
\- 403: { "detail": "You do not have permission to perform this action." } or { "detail": "This API key has no write access to webhooks." }
\- 429: more than 300 write requests per minute with this key; wait for Retry-After.

Side effects:
\- Rotating the secret changes how deliveries to the legacy webhook_url are signed from then on, retries included.
\- A data_retention_months change applies to existing sessions too: every session older than the new window is deleted automatically, and that deletion is irreversible.
\- A face_retention_policy change applies to session deletions from then on; it creates or purges no existing biometric template.

For the full integration shape, see /integration/integration-prompt.`

\</pre>



      
      

Paste into

> [!NOTE]
>
> `rotate_secret_key` rotates only the application-level secret, which signs deliveries to the legacy `webhook_url`. Every [webhook destination](/management-api/webhook/list-destinations.md) signs with its own `secret_shared_key`, which this call does not change.The retention fields are the same policy you set in **Business Console → App Settings → Data**. Read [Data retention](/console/data-retention.md) before you change them, in particular [biometric template retention](/console/data-retention.md#biometric-template-retention). `allowed_return_hosts` is described in [Register your return destination](/standalone-apis/digital-id-wallets.md#register-your-return-destination).To read the current values first, call [Get Webhook Configuration](/management-api/webhook/get-config.md).


## OpenAPI

````yaml PATCH /v3/webhook/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: Identity verification API. Authenticate with x-api-key header.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/webhook/:
    patch:
      tags:
        - Webhook
      summary: Update webhook configuration
      description: >-
        Partially update application-level settings: the legacy webhook URL,
        version and secret, the data and biometric-template retention policy,
        and the Digital ID wallet return hosts. Send only the fields to change;
        the response is the full configuration, the same shape as `GET
        /v3/webhook/`. Destinations are not managed here: create, update and
        delete them with the `/v3/webhook/destinations/` endpoints, and do not
        send an `endpoints` field to this endpoint. A `data_retention_months`
        change also applies to existing sessions, and sessions it deletes cannot
        be restored; read [Data
        retention](https://docs.didit.me/console/data-retention) first. A scoped
        API key needs `webhooks: write`.
      operationId: update_webhook_config
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: >-
                Send only the fields to change. Destinations are not managed
                here.
              properties:
                webhook_url:
                  type: string
                  format: uri
                  nullable: true
                  maxLength: 2000
                  description: >-
                    Legacy application-level webhook URL. Didit uses it only
                    while the application has no enabled destination, and then
                    only for `status.updated` and `data.updated`. It does not
                    create a destination, and the next create, update or delete
                    of a destination replaces it. To receive webhooks, create a
                    destination with `POST /v3/webhook/destinations/` instead.
                webhook_version:
                  type: string
                  enum:
                    - v1
                    - v2
                    - v3
                  description: Payload version of the legacy `webhook_url`.
                rotate_secret_key:
                  type: boolean
                  default: false
                  description: >-
                    `true` replaces the application-level `secret_shared_key`
                    with a new random value at once; the new value is in the
                    response. Destination secrets are not changed. Every call
                    with `true` generates a new secret, so it is not idempotent.
                capture_method:
                  type: string
                  enum:
                    - MOBILE
                    - MOBILE_AND_DESKTOP
                  description: >-
                    Legacy application setting. The verification flow does not
                    read it.
                data_retention_months:
                  type: integer
                  nullable: true
                  minimum: 1
                  maximum: 120
                  description: >-
                    Automatic deletion window in months (a month counts as 30
                    days), or `null` for no automatic deletion. A change applies
                    to existing sessions too: every user verification session
                    older than the new window is deleted automatically, and that
                    deletion is irreversible.
                face_retention_policy:
                  type: string
                  enum:
                    - delete_with_session
                    - retain_until_user_deleted
                  description: >-
                    What happens to a session's face embedding when the session
                    is deleted. `retain_until_user_deleted` needs
                    `face_retention_days` in the same request or already set. A
                    change applies to session deletions from then on; it creates
                    or purges no existing biometric template.
                face_retention_days:
                  type: integer
                  nullable: true
                  minimum: 1
                  maximum: 3650
                  description: >-
                    Retention period, in days, of biometric templates under
                    `retain_until_user_deleted`.
                allowed_return_hosts:
                  type: array
                  maxItems: 20
                  description: >-
                    Replaces the whole list of Digital ID wallet return hosts.
                    Bare hostnames only, such as `shop.example.com`: no scheme,
                    port, path or wildcard. Values are lowercased and duplicates
                    are dropped. Send `[]` to clear the list.
                  items:
                    type: string
                    maxLength: 253
            examples:
              Enable biometric template retention:
                value:
                  face_retention_policy: retain_until_user_deleted
                  face_retention_days: 365
              Rotate the legacy secret:
                value:
                  rotate_secret_key: true
              Set data retention:
                value:
                  data_retention_months: 24
              Register return hosts:
                value:
                  allowed_return_hosts:
                    - shop.example.com
                    - app.example.com
      responses:
        '200':
          description: >-
            The full configuration after the update, the same shape as `GET
            /v3/webhook/`. When you rotated the secret, store the new
            `secret_shared_key` before you discard the response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookConfig'
              examples:
                Retention enabled:
                  value:
                    webhook_url: https://yourapp.com/webhooks/didit
                    webhook_version: v3
                    secret_shared_key: dGhpcy1pcy10aGUtYXBwLWxldmVsLXNlY3JldC0wMDA
                    capture_method: MOBILE
                    data_retention_months: 24
                    face_retention_policy: retain_until_user_deleted
                    face_retention_days: 365
                    available_events:
                      - value: status.updated
                        label: Session status updated
                      - value: data.updated
                        label: Session data updated
                      - value: user.status.updated
                        label: User status updated
                      - value: user.data.updated
                        label: User data updated
                      - value: business.status.updated
                        label: Business status updated
                      - value: business.data.updated
                        label: Business data updated
                      - value: activity.created
                        label: Activity created
                      - value: transaction.created
                        label: Transaction created
                      - value: transaction.status.updated
                        label: Transaction status updated
                      - value: travel_rule.status.updated
                        label: Travel Rule Status Updated
                      - value: workflow.compliance_changed
                        label: Workflow Compliance Changed
                    allowed_return_hosts:
                      - shop.example.com
                    endpoints:
                      - uuid: 11111111-2222-3333-4444-555555555555
                        label: Production session webhooks
                        url: https://yourapp.com/webhooks/didit
                        enabled: true
                        webhook_version: v3
                        secret_shared_key: dGhpcy1pcy1hbi1leGFtcGxlLXNlY3JldC0wMDAwMDA
                        subscribed_events:
                          - status.updated
                          - data.updated
                        created_at: '2026-01-04T08:00:00.000000Z'
                        updated_at: '2026-04-22T14:09:11.523671Z'
        '400':
          description: >-
            Validation failed: each invalid field is mapped to a list of
            messages, and nothing is changed. A body that is not valid JSON
            returns `{"detail": "JSON parse error - ..."}`.
          content:
            application/json:
              schema:
                type: object
                description: Each invalid field mapped to a list of messages.
                additionalProperties:
                  type: array
                  items:
                    type: string
              examples:
                Retention days missing:
                  value:
                    face_retention_days:
                      - >-
                        A finite retention duration is required when face
                        retention is enabled.
                Retention window out of range:
                  value:
                    data_retention_months:
                      - Ensure this value is less than or equal to 120.
                Invalid return host:
                  value:
                    allowed_return_hosts:
                      - >-
                        'https://shop.example.com' is not a hostname. Register
                        the bare host (e.g. shop.example.com): no scheme, port,
                        path or wildcard.
                Invalid choice:
                  value:
                    face_retention_policy:
                      - '"forever" is not a valid choice.'
        '401':
          description: >-
            The API key has expired: it was created with an expiry date that has
            passed. A missing, invalid or revoked key gets `403`, not `401`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    description: Human-readable error message.
              examples:
                Expired key:
                  value:
                    detail: This API key has expired.
        '403':
          description: >-
            The request is not allowed. A missing, invalid or revoked
            `x-api-key` gets `You do not have permission to perform this
            action.` A scoped key without the access this endpoint needs gets a
            message naming the missing access, and a key used from outside its
            IP allowlist gets `This API key can't be used from this IP address.`
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    description: Human-readable error message.
              examples:
                Missing or invalid key:
                  value:
                    detail: You do not have permission to perform this action.
                Scoped key without webhooks write:
                  value:
                    detail: This API key has no write access to webhooks.
                Outside the IP allowlist:
                  value:
                    detail: This API key can't be used from this IP address.
        '429':
          description: >-
            Rate limit exceeded: more than 300 write requests (POST, PATCH, PUT,
            DELETE) in the current one-minute window for this API key. Wait
            `Retry-After` seconds before retrying.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
                minimum: 1
                example: 30
            X-RateLimit-Limit:
              description: Requests allowed in the one-minute window (300).
              schema:
                type: integer
                example: 300
            X-RateLimit-Remaining:
              description: Requests left in the current window.
              schema:
                type: integer
                example: 0
            X-RateLimit-Reset:
              description: Unix time (seconds) when the current window resets.
              schema:
                type: integer
                example: 1792056120
            X-RateLimit-Scope:
              description: Name of the budget that was exceeded.
              schema:
                type: string
                example: generic-write
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    description: Human-readable error message.
              examples:
                Throttled:
                  value:
                    detail: >-
                      Write request rate limit exceeded. You can make up to 300
                      requests per minute.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X PATCH 'https://verification.didit.me/v3/webhook/' \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{"face_retention_policy": "retain_until_user_deleted", "face_retention_days": 365}'
        - lang: python
          label: Python
          source: >-
            import os


            import requests


            resp = requests.patch(
                'https://verification.didit.me/v3/webhook/',
                headers={'x-api-key': os.environ['DIDIT_API_KEY']},
                json={'face_retention_policy': 'retain_until_user_deleted', 'face_retention_days': 365},
                timeout=10,
            )

            resp.raise_for_status()

            config = resp.json()

            print(config['face_retention_policy'],
            config['face_retention_days'])
        - lang: javascript
          label: JavaScript
          source: >-
            const resp = await
            fetch('https://verification.didit.me/v3/webhook/', {
              method: 'PATCH',
              headers: {
                'x-api-key': process.env.DIDIT_API_KEY,
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({ face_retention_policy: 'retain_until_user_deleted', face_retention_days: 365 }),
            });

            if (!resp.ok) throw new Error(await resp.text());

            const config = await resp.json();

            console.log(config.face_retention_policy,
            config.face_retention_days);
components:
  schemas:
    WebhookConfig:
      type: object
      description: >-
        Application-level webhook configuration, retention policy and Digital ID
        wallet return hosts, with every webhook destination.
      required:
        - webhook_url
        - webhook_version
        - secret_shared_key
        - capture_method
        - data_retention_months
        - face_retention_policy
        - face_retention_days
        - available_events
        - allowed_return_hosts
        - endpoints
      properties:
        webhook_url:
          type: string
          format: uri
          nullable: true
          description: >-
            Application-level (legacy) webhook URL. Didit sends to it only while
            the application has no enabled destination, and then only
            `status.updated` and `data.updated`. Every create, update or delete
            of a destination sets it to the URL of the oldest enabled
            destination, or `null` when none is enabled.
        webhook_version:
          type: string
          enum:
            - v1
            - v2
            - v3
          description: >-
            Payload version of the legacy `webhook_url`. Each destination has
            its own `webhook_version`.
        secret_shared_key:
          type: string
          description: >-
            Application-level signing secret (43-character URL-safe token). It
            signs only deliveries to the legacy `webhook_url`; each destination
            signs with its own `secret_shared_key`. API-key callers always
            receive it in full; Console users without `read:webhooks` receive an
            empty string.
        capture_method:
          type: string
          enum:
            - MOBILE
            - MOBILE_AND_DESKTOP
          description: >-
            Legacy application setting. The verification flow does not read it:
            capture options are configured per workflow.
        data_retention_months:
          type: integer
          nullable: true
          minimum: 1
          maximum: 120
          description: >-
            Automatic deletion window. User verification sessions created more
            than this many months ago (a month counts as 30 days) are deleted
            automatically, and that deletion is irreversible. `null` means
            sessions are never deleted automatically. See [Data
            retention](https://docs.didit.me/console/data-retention).
        face_retention_policy:
          type: string
          enum:
            - delete_with_session
            - retain_until_user_deleted
          description: >-
            What happens to a session's face embedding when the session is
            deleted. `delete_with_session` (default) deletes it with the
            session. `retain_until_user_deleted` is the opt-in [biometric
            template
            retention](https://docs.didit.me/console/data-retention#biometric-template-retention):
            an image-free biometric template linked to the User is managed
            separately until its retention period ends, the User is deleted, or
            you purge it.
        face_retention_days:
          type: integer
          nullable: true
          minimum: 1
          maximum: 3650
          description: >-
            Retention period, in days, of biometric templates under
            `retain_until_user_deleted`. Required when that policy is set.
        available_events:
          type: array
          description: >-
            Every event type a destination can subscribe to, with a display
            label.
          items:
            type: object
            required:
              - value
              - label
            properties:
              value:
                $ref: '#/components/schemas/WebhookEvent'
              label:
                type: string
                description: Display label, for example `Session status updated`.
        allowed_return_hosts:
          type: array
          maxItems: 20
          description: >-
            Hostnames (exact match, HTTPS only) a standalone Digital ID wallet
            verification may send the user back to with its `return_url`. Your
            white-label domain is always allowed as well. See [Register your
            return
            destination](https://docs.didit.me/standalone-apis/digital-id-wallets#register-your-return-destination).
          items:
            type: string
            maxLength: 253
        endpoints:
          type: array
          description: >-
            Every webhook destination of the application, oldest first, each
            with its signing secret. Read only here: manage destinations with
            the `/v3/webhook/destinations/` endpoints.
          items:
            $ref: '#/components/schemas/WebhookConfigDestination'
    WebhookEvent:
      type: string
      description: >-
        Supported webhook event name. Use these exact strings in
        `subscribed_events`; unsupported values are rejected.
      enum:
        - status.updated
        - data.updated
        - user.status.updated
        - user.data.updated
        - business.status.updated
        - business.data.updated
        - activity.created
        - transaction.created
        - transaction.status.updated
        - travel_rule.status.updated
        - workflow.compliance_changed
        - auth.signup
        - auth.login
        - auth.login_failed
        - auth.password_reset_requested
        - auth.password_reset_completed
        - auth.mfa_changed
        - auth.new_device
        - auth.account_locked
        - investigator.report.ready
        - investigator.decision.automated
        - investigator.decision.overridden
        - investigator.decision.contested
        - investigator.question.raised
        - investigator.automation.paused
        - investigator.rfi.answered
        - investigator.rfi.overdue
        - investigator.drift.detected
        - investigator.sla.breached
        - investigator.qa.failed
        - investigator.external.report.ready
    WebhookConfigDestination:
      type: object
      description: >-
        A webhook destination as listed in the webhook configuration, without
        delivery metrics. `GET /v3/webhook/destinations/{destination_uuid}/`
        adds its delivery summary.
      required:
        - uuid
        - label
        - url
        - enabled
        - webhook_version
        - secret_shared_key
        - subscribed_events
        - created_at
        - updated_at
      properties:
        uuid:
          type: string
          format: uuid
          description: Destination ID.
        label:
          type: string
          maxLength: 255
          description: Human-readable name.
        url:
          type: string
          format: uri
          maxLength: 2000
          description: HTTPS endpoint Didit posts events to.
        enabled:
          type: boolean
          description: '`false` pauses deliveries to this destination.'
        webhook_version:
          type: string
          enum:
            - v1
            - v2
            - v3
          description: Payload version sent to this destination.
        secret_shared_key:
          type: string
          description: >-
            This destination's signing secret (43-character URL-safe token).
            Verify each webhook with the secret of the destination it was sent
            to. API-key callers always receive it in full; Console users without
            `read:webhooks` receive an empty string.
        subscribed_events:
          type: array
          uniqueItems: true
          description: >-
            Event types delivered to this destination. Empty when the
            destination was created without events, in which case it receives
            nothing.
          items:
            $ref: '#/components/schemas/WebhookEvent'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your application's API key, from Developers -> API keys in the Business
        Console. The primary key has full access. A named key can be scoped:
        none, read or write per resource, limited to some workflows or to
        approved sessions, to a list of IP addresses, and to an expiry date. 401
        means the key is missing, wrong, revoked or expired; 403 means the key
        has no access to this resource or action, or the request came from an
        address outside its IP list; 404 on a session route means the session is
        outside the key's workflows or statuses. A key without media access
        receives image, video and PDF URLs as null, and a key without sessions
        write receives session links and tokens as null. See
        https://docs.didit.me/console/api-keys.

````

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