> ## 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 para actualizar estado de sesión: aprobar y rechazar

> Con la API de Didit, PATCH /v3/session/{id}/update-status/ aprueba, rechaza o pasa sesiones a revisión. KYC y KYB. Pago por uso, sin mínimos.



Prompt para actualizar el estado de una sesión
        Copiar el prompt al portapapeles



      
      

\<pre>

\`Manually approve, decline, or re-open a Didit verification session.

Endpoint:
PATCH https://verification.didit.me/v3/session/{session_id}/update-status/

Authentication:
Use the x-api-key header with your Didit API key (or a user-auth token). Privilege: write:sessions.

Path parameter:
\- session_id (UUID) — KYC or KYB; Didit resolves it against both session types.

Request body:
\- new_status (string, required) — One of "Approved", "Declined", "Resubmitted". Any other value is rejected.
\- comment (string, optional) — Free-text note saved on the audit trail (visible in the Console review log).
\- nodes_to_resubmit (array, required when new_status="Resubmitted") — Which feature steps the user must redo. Each entry: { "node_id": "feature_poa_1", "feature": "POA" }. KYB-only nodes "KYB_REGISTRY" and "KYB_KEY_PEOPLE" cannot be resubmitted directly (the parent recomputes from child KYCs).
\- send_email (boolean, optional, default false): if true, email the person. "Approved" and "Declined" send their decision email; "Resubmitted" sends a fresh hosted link with the reasons.
\- email_address (string, required when send_email=true).
\- email_language (string, optional, default "en") — ISO 639-1.
\- email_preview_token (string, optional): the preview_token from Preview Decision Email ("Approved", "Declined") or Preview Resubmission Email ("Resubmitted"). Only valid with send_email=true; without it the request returns 400 { "email_preview_token": ["A preview receipt is only valid when the email is sent."] }. The update then sends exactly the previewed email, or returns 409 before changing anything if the email or the session changed since the preview.

Optional preview step (all three statuses):
1\. Preview the email. Neither call changes the session or sends anything.
\- Approved or Declined: POST https://verification.didit.me/v3/session/{session_id}/decision-email-preview/ with { "new_status": "Approved", "email_language": "en" } (see /sessions-api/preview-decision-email).
\- Resubmitted: POST https://verification.didit.me/v3/session/{session_id}/resubmission-preview/ with { "nodes_to_resubmit": [...], "email_language": "en" } (see /sessions-api/preview-resubmission). email_address is optional there; without it the email goes to the person's own address.
2\. Check subject, html, recipient, will_be_sent and not_sent_reason in the response.
3\. Confirm here with the same new_status (and the same nodes_to_resubmit for Resubmitted), send_email=true, email_address=<recipient>, email_language=<the language you previewed>, email_preview_token=<preview_token>.
The receipt expires after 15 minutes.

Allowed transitions:
Current status must be one of: Approved, Declined, In Review, Kyc Expired, Abandoned, Resubmitted. Otherwise the API returns 400 { "detail": "Only sessions with status Approved, Declined, In Review, Kyc Expired, Abandoned, Resubmitted can be updated. Current status: ..." }.
Setting "Approved" or "Declined" on a session that already has that status is a no-op: 200, nothing changes, and no webhook or email goes out. Setting "Resubmitted" on a session that is already Resubmitted returns 400 ["The new status is the same as the current status."].

curl example — approve after manual review:
curl -X PATCH https://verification.didit.me/v3/session/<SESSION_ID>/update-status/ \
-H "x-api-key: <API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"new_status": "Approved",
"comment": "Cleared after compliance review."
}'

curl example: approve and send the email you previewed:
curl -X PATCH https://verification.didit.me/v3/session/<SESSION_ID>/update-status/ \
-H "x-api-key: <API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"new_status": "Approved",
"send_email": true,
"email_address": "<recipient from the preview>",
"email_language": "en",
"email_preview_token": "<preview_token from the preview>"
}'

curl example — request resubmission of the proof-of-address step:
curl -X PATCH https://verification.didit.me/v3/session/<SESSION_ID>/update-status/ \
-H "x-api-key: <API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"new_status": "Resubmitted",
"nodes_to_resubmit": [{ "node_id": "feature_poa_1", "feature": "POA" }],
"comment": "Please upload a clearer proof of address",
"send_email": true,
"email_address": "user@example.com"
}'

Response: { "session_id": "<uuid>" } only. Fetch the refreshed session with GET /v3/session/{session_id}/decision/.

Side effects:
\- Fires a status.updated webhook (plus user.status.updated or business.status.updated alias).
\- Writes an entry to the Console review trail with the actor and your comment.
\- "Approved" or "Declined" with send_email=true emails the decision to email_address. Preview Decision Email tells you beforehand whether it will be sent (for example, not to the contact_details address of a session created without contact_details.send_notification_emails=true).
\- "Resubmitted" sends the user back to the steps in nodes_to_resubmit, resets the session expiration window, and (if send_email=true) emails the user a fresh link. What those steps returned before stays readable: the decision endpoint returns it with include=resubmissions (see Retrieve Session).

Failure modes:
\- 400: invalid new_status (only "Approved", "Declined" and "Resubmitted" are accepted), current status not allowed, nothing to resubmit, send_email=true without email_address, or email_preview_token without send_email=true. Field errors look like { "<field>": ["..."] }.
\- 401: the scoped API key has expired.
\- 403: { "detail": "..." } when credentials are missing or invalid, the caller lacks write:sessions (a scoped API key needs decisions write), or the session belongs to another application.
\- 404: { "detail": "Not found." } when no session with this session_id exists.
\- 409: { "detail": "This email preview changed or expired. Preview the message again before confirming." } when email_preview_token no longer matches the email or the session, or is older than 15 minutes. Nothing changed and no email was sent: preview again.
\- 429 - { "detail": "..." } when a resubmit that only targets backend-only features (AML, DATABASE_VALIDATION, IP_ANALYSIS) repeats within 30 seconds of the previous resubmit. Those features re-run automatically with no user interaction, so an immediate repeat cannot change the outcome; honor the Retry-After header instead of retrying in a loop (e.g. from a webhook handler).

Idempotency:
Repeating "Approved" or "Declined" returns 200 and changes nothing. Repeating "Resubmitted" returns 400.

Next step:
After updating, call GET /v3/session/{session_id}/decision/ to fetch the refreshed payload — see /sessions-api/retrieve-session.

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

\</pre>



      
      

Pegar en

## Compatibilidad con KYC y KYBEste endpoint funciona exactamente igual para las sesiones de **Verificación de usuario (KYC)** y de **Verificación de empresas (KYB)**. Didit busca el `session_id` en ambos tipos de sesión, y la validación de las transiciones de estado es la misma para los dos (se aplica el mismo enum de estados a ambos).La respuesta solo incluye el `session_id`.
Consulta `session_kind` en [Obtener sesión](https://docs.didit.me/es/sessions-api/retrieve-session.md) cuando tu lógica posterior necesite actuar según el tipo.## Transiciones permitidasPuedes cambiar una sesión a `Approved`, `Declined` o `Resubmitted`.
Cualquier otro `new_status`, incluido `In Review`, devuelve `400`.
El estado actual de la sesión debe ser `Approved`, `Declined`, `In Review`, `Kyc Expired`, `Abandoned` o `Resubmitted`; de lo contrario, la API devuelve `400`.Asignar `Approved` o `Declined` a una sesión que ya tiene ese estado no tiene efecto: la API devuelve `200` y no cambia nada, no dispara ningún webhook ni envía ningún correo electrónico.
Asignar `Resubmitted` a una sesión que ya está en `Resubmitted` devuelve `400` (`The new status is the same as the current status.`).Un reenvío cuyos `nodes_to_resubmit` contienen solo funciones que se ejecutan únicamente en el backend (`AML`, `DATABASE_VALIDATION`, `IP_ANALYSIS`) se ejecuta automáticamente y devuelve la sesión a un estado con una decisión tomada sin interacción del usuario.
Repetir un reenvío de este tipo en menos de 30 segundos devuelve `429 Too Many Requests` con un encabezado `Retry-After`, ya que una repetición inmediata no puede producir un resultado distinto.
No reenvíes automáticamente la sesión desde un controlador de webhook cada vez que recibas un estado `In Review`: primero revisa el hallazgo o cambia los datos subyacentes.## Previsualiza primero el correo electrónicoCon `send_email: true`, `Approved` y `Declined` envían a la persona el correo electrónico con su decisión, y `Resubmitted` le envía un enlace nuevo con los motivos.
Puedes ver ese correo electrónico antes de cambiar nada:1) Llama a [Previsualizar correo de decisión](https://docs.didit.me/es/sessions-api/preview-decision-email.md) para `Approved` o `Declined`, o a [Previsualizar correo de reenvío](https://docs.didit.me/es/sessions-api/preview-resubmission.md) para `Resubmitted`.
2) Comprueba el `subject` y el `html` renderizados, el `recipient` y `will_be_sent` / `not_sent_reason`.
3) Llama a este endpoint con el mismo `new_status` (y, en el caso de un reenvío, los mismos `nodes_to_resubmit`), `send_email: true`, `email_address` con el valor de `recipient`, el `email_language` que previsualizaste y `email_preview_token` con el valor de `preview_token`.Ninguna de las dos previsualizaciones modifica la sesión ni envía nada.
Después, la actualización envía exactamente el correo electrónico que previsualizaste.
El comprobante expira a los 15 minutos.
Si el destinatario, el idioma, el estado de la sesión, el remitente o el correo electrónico cambiaron desde la previsualización, la actualización devuelve `409` antes de que se modifique nada; vuelve a previsualizar y confirma con el nuevo comprobante.
Enviar `email_preview_token` sin `send_email: true` devuelve `400`.
El paso de previsualización es opcional: las integraciones existentes pueden seguir llamando a este endpoint sin él.## Ejemplos> [tab] Aprobar una sesión de Verificación de usuario (KYC)
>
> ```bash theme={null}
> curl -X PATCH https://verification.didit.me/v3/session/4c5c7f3a-.../update-status/ \
>   -H "x-api-key: YOUR_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "new_status": "Approved",
>     "comment": "Cleared after manual review by compliance team"
>   }'
> ```> [tab] Rechazar una sesión de Verificación de empresas (KYB)
>
> ```bash theme={null}
> curl -X PATCH https://verification.didit.me/v3/session/bs-01HJX1.../update-status/ \
>   -H "x-api-key: YOUR_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "new_status": "Declined",
>     "comment": "Sanctioned subsidiary detected in ownership chain"
>   }'
> ```> [tab] Solicitar un reenvío
>
> ```bash theme={null}
> curl -X PATCH https://verification.didit.me/v3/session/.../update-status/ \
>   -H "x-api-key: YOUR_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "new_status": "Resubmitted",
>     "nodes_to_resubmit": [
>       { "node_id": "feature_poa_1", "feature": "POA" }
>     ],
>     "comment": "Please upload a clearer proof of address",
>     "send_email": true,
>     "email_address": "user@example.com"
>   }'
> ```> [tab] Aprobar y enviar el correo previsualizado
>
> ```bash theme={null}
> curl -X PATCH https://verification.didit.me/v3/session/.../update-status/ \
>   -H "x-api-key: YOUR_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "new_status": "Approved",
>     "send_email": true,
>     "email_address": "user@example.com",
>     "email_language": "en",
>     "email_preview_token": "PREVIEW_TOKEN_FROM_THE_PREVIEW"
>   }'
> ```## PermisoRequiere el privilegio `write:sessions`. El mismo privilegio cubre ambos tipos.## Relacionado- [Estados de verificación](https://docs.didit.me/es/integration/verification-statuses.md): referencia de la máquina de estados.
- [Obtener sesión](https://docs.didit.me/es/sessions-api/retrieve-session.md): consulta la decisión después de actualizarla.
- [Visión general de las sesiones](https://docs.didit.me/es/sessions-api/overview.md): cómo distinguir el tipo de sesión.
- [Previsualizar correo de decisión](https://docs.didit.me/es/sessions-api/preview-decision-email.md): consulta el correo de aprobación o rechazo antes de enviarlo.
- [Previsualizar correo de reenvío](https://docs.didit.me/es/sessions-api/preview-resubmission.md): consulta el correo de reenvío antes de enviarlo.


## OpenAPI

````yaml es/openapi-25.json PATCH /v3/session/{sessionId}/update-status/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API de verificación de identidad. Autentícate con el encabezado x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/session/{sessionId}/update-status/:
    patch:
      tags:
        - Sessions
      summary: Aprobar, rechazar o solicitar un reenvío para una sesión de verificación
      description: >-
        Anula manualmente la decisión final de una sesión de verificación KYC o
        KYB. Establece `new_status` en `Approved` o `Declined` para registrar
        una decisión manual, o en `Resubmitted` para borrar pasos de
        verificación concretos y permitir que el usuario los repita desde la
        misma URL de verificación. El endpoint acepta ID de sesión tanto de
        usuarios (KYC) como de empresas (KYB).


        Llámalo cuando la sesión haya llegado a un estado revisable: el estado
        actual debe ser `Approved`, `Declined`, `In Review`, `Kyc Expired`,
        `Abandoned` o `Resubmitted`. Las sesiones que siguen en `Not Started`,
        `In Progress` o `Awaiting User`, o que terminaron como `Expired`,
        devuelven `400`. Tu clave de API necesita el permiso `write:sessions`
        (una clave de API con alcance limitado necesita acceso de escritura a
        las decisiones). La comprobación del estado admisible se ejecuta antes
        de validar el cuerpo, por lo que una sesión no admisible devuelve el
        error `Wrong Current Status` aunque el payload también sea inválido.


        Para `Resubmitted`, pasa `nodes_to_resubmit` para elegir qué pasos del
        flujo debe repetir el usuario, u omítelo para seleccionar
        automáticamente los intentos de funciones existentes que estén en un
        estado reenviable (`Declined`, `In Review`, `Not Finished`, `Expired`).
        Las funciones que nunca se intentaron no se seleccionan automáticamente:
        inclúyelas de forma explícita en `nodes_to_resubmit`, o la solicitud
        devolverá `400` cuando ningún intento registrado necesite reenvío. Los
        resultados anteriores de los pasos seleccionados pasan al historial del
        reenvío (que devuelve Obtener decisión con `include=resubmissions`), los
        pasos se reordenan según el grafo del flujo, el periodo de expiración de
        la sesión se reinicia y la URL de verificación original vuelve a poder
        usarse. Los pasos que solo se ejecutan en el backend (`AML`,
        `DATABASE_VALIDATION`, `IP_ANALYSIS`) al principio de la lista se
        ejecutan de inmediato sin interacción del usuario; si todos los pasos
        reenviados son solo de backend, la sesión se vuelve a finalizar dentro
        de la misma solicitud. `KYB_REGISTRY` y `KYB_KEY_PEOPLE` no se pueden
        reenviar directamente: reenvía en su lugar las sesiones KYC hijas
        correspondientes y la sesión de empresa principal se recalcula
        automáticamente.


        Cada llamada que cambia el estado dispara el
        [webhook](/es/integration/webhooks) `status.updated` una vez que el
        cambio se confirma, y añade una entrada de actividad (con la atribución
        del actor y tu `comment`) a los `reviews` de la sesión, visible en
        [Obtener decisión](#get-/v3/session/-sessionId-/decision/) y en la
        cronología de actividad de la consola. Los datos agregados del perfil de
        usuario vinculados al `vendor_data` de la sesión también se actualizan.
        Rechazar desactiva la monitorización AML continua de la sesión; volver a
        aprobar la reactiva (desde `Resubmitted`, `Declined` o `Kyc Expired`)
        cuando el flujo tiene la monitorización activada. Aprobar o rechazar una
        sesión KYC hija que pertenece a una comprobación de personas clave de
        KYB recalcula el estado de la sesión de empresa principal. Establece
        `send_email: true` (con `email_address`) para notificar al usuario: un
        aviso de estado para `Approved`/`Declined`, o un correo de reenvío con
        el enlace de verificación y los motivos de cada paso para `Resubmitted`.
        Para revisar el correo antes, obtén una vista previa con [Vista previa
        del correo de decisión](/es/sessions-api/preview-decision-email)
        (`Approved`, `Declined`) o [Vista previa del correo de
        reenvío](/es/sessions-api/preview-resubmission) (`Resubmitted`) y pasa
        su `preview_token` como `email_preview_token`: la actualización envía
        entonces exactamente el correo previsualizado, o devuelve `409` antes de
        cambiar nada si el correo o la sesión cambiaron desde la vista previa o
        si el comprobante tiene más de 15 minutos.


        Repetir `Approved` o `Declined` en una sesión que ya tiene ese estado no
        cambia nada y devuelve `200`: sin webhook, sin entrada de actividad y
        sin correo. Repetir `Resubmitted` devuelve `400` (`The new status is the
        same as the current status.`). Las credenciales ausentes o inválidas y
        la falta de permisos devuelven `403`; una clave de API con alcance
        limitado que ha expirado devuelve `401`.
      operationId: patch_v3_session_update_status
      parameters:
        - in: path
          name: sessionId
          required: true
          description: >-
            UUID de la sesión de verificación que se va a actualizar. Acepta ID
            de sesión tanto de usuario (KYC) como de empresa (KYB): el servicio
            resuelve el ID en ambos tipos de sesión.
          schema:
            type: string
            format: uuid
            example: 11111111-2222-3333-4444-555555555555
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - new_status
              properties:
                new_status:
                  type: string
                  description: >-
                    Estado de destino. `Approved` y `Declined` registran una
                    decisión manual definitiva (cada una también puede revertir
                    la otra). `Resubmitted` borra los pasos seleccionados y
                    devuelve la sesión al usuario. Cualquier otro valor devuelve
                    `400`.
                  enum:
                    - Approved
                    - Declined
                    - Resubmitted
                  example: Approved
                comment:
                  type: string
                  description: >-
                    Motivo del cambio en texto libre, que se guarda en el
                    historial de revisiones de la sesión y se devuelve en el
                    array `reviews` de [Obtener
                    decisión](#get-/v3/session/-sessionId-/decision/). Por
                    ejemplo, `Duplicated user`.
                  example: All checks passed manual review
                nodes_to_resubmit:
                  type: array
                  description: >-
                    Pasos del flujo que el usuario debe repetir. Solo se tienen
                    en cuenta cuando `new_status` es `Resubmitted`. Con
                    `Approved`/`Declined` las entradas se siguen validando
                    contra el esquema (un valor de `feature` no válido devuelve
                    `400`), pero las entradas válidas se ignoran a efectos de su
                    significado. Si se omite, el servidor selecciona
                    automáticamente los intentos existentes de OCR, Liveness,
                    Face Match, POA, Phone, Email, AML, Database Validation y
                    Questionnaire cuyo estado es `Declined`, `In Review`, `Not
                    Finished` o `Expired` (los intentos de NFC, análisis de IP,
                    estimación de edad, búsqueda facial y documentos KYB nunca
                    se seleccionan automáticamente; los intentos faciales que no
                    son de coincidencia facial se seleccionan como `LIVENESS`).
                    Las funciones que el usuario nunca intentó (sin ningún
                    intento registrado) NO se seleccionan, por lo que una sesión
                    sin intentos devuelve `400` ("No features found that need
                    resubmission") aunque no se haya aprobado nada; en ese caso,
                    envía `nodes_to_resubmit` de forma explícita. Los pasos se
                    ejecutan en el orden del grafo del flujo, sin importar el
                    orden en que los envíes. `KYB_REGISTRY`, `KYB_KEY_PEOPLE` y
                    el alias `KYB` se rechazan con `400`: esas comprobaciones
                    principales se recalculan a partir de sus sesiones KYC
                    hijas.
                  items:
                    type: object
                    required:
                      - node_id
                      - feature
                    properties:
                      node_id:
                        type: string
                        description: >-
                          Identificador del nodo tal como aparece en la
                          definición del flujo de la sesión (por ejemplo,
                          `feature_ocr`, `feature_liveness`).
                        example: feature_ocr
                      feature:
                        type: string
                        description: >-
                          Tipo de función del nodo. El servidor normaliza los
                          alias `ID_VERIFICATION`, `POA`, `PHONE` y `EMAIL` a
                          `OCR`, `PROOF_OF_ADDRESS`, `PHONE_VERIFICATION` y
                          `EMAIL_VERIFICATION`. `KYB_REGISTRY`, `KYB_KEY_PEOPLE`
                          y `KYB` superan la validación del esquema, pero
                          siempre se rechazan con el `400` de regla de negocio
                          que se muestra en los ejemplos.
                        enum:
                          - OCR
                          - OCR_BACK
                          - NFC
                          - AML
                          - FACE
                          - LIVENESS
                          - FACE_MATCH
                          - IP_ANALYSIS
                          - AGE_ESTIMATION
                          - PROOF_OF_ADDRESS
                          - PHONE_VERIFICATION
                          - EMAIL_VERIFICATION
                          - FACE_SEARCH
                          - DATABASE_VALIDATION
                          - QUESTIONNAIRE
                          - DOCUMENT_AI
                          - KYB_DOCUMENTS
                          - ID_VERIFICATION
                          - POA
                          - PHONE
                          - EMAIL
                          - KYB_REGISTRY
                          - KYB_KEY_PEOPLE
                          - KYB
                          - GEOLOCATION
                        example: OCR
                send_email:
                  type: boolean
                  description: >-
                    Indica si se envía un correo electrónico al usuario sobre el
                    cambio. Requiere `email_address`. Con `Approved`/`Declined`
                    el usuario recibe un aviso de estado; con `Resubmitted` el
                    correo incluye el enlace de verificación y los motivos de
                    reenvío de cada paso.
                  default: false
                  example: false
                email_address:
                  type: string
                  format: email
                  description: >-
                    Destinatario del correo electrónico de notificación.
                    **Obligatorio cuando `send_email` es `true`**: si lo omites,
                    se devuelve `400`.
                  example: user@example.com
                email_language:
                  type: string
                  description: >-
                    Idioma del correo electrónico de notificación. El esquema
                    acepta cualquier cadena; los códigos no admitidos pasan a
                    inglés (`en`) sin avisar.
                  default: en
                  example: en
                email_preview_token:
                  type: string
                  writeOnly: true
                  minLength: 1
                  maxLength: 512
                  description: >-
                    Comprobante opcional de [Vista previa del correo de
                    decisión](/es/sessions-api/preview-decision-email) (para
                    `Approved` y `Declined`) o de [Vista previa del correo de
                    reenvío](/es/sessions-api/preview-resubmission) (para
                    `Resubmitted`): su `preview_token`. Solo es válido con
                    `send_email: true`; sin este, la solicitud devuelve `400`.
                    El destinatario, el idioma, el estado de la sesión, el
                    remitente y el correo (y, en un reenvío, los pasos
                    seleccionados) deben seguir coincidiendo con la vista
                    previa, y el comprobante caduca a los 15 minutos. De lo
                    contrario, la solicitud devuelve `409` antes de que cambie
                    la sesión o se envíe ningún correo. Las integraciones
                    existentes pueden omitir este campo.
            examples:
              Approve Session:
                summary: Aprobar una sesión tras la revisión manual
                value:
                  new_status: Approved
                  comment: All checks passed manual review
              Decline Session:
                summary: Rechazar una sesión
                value:
                  new_status: Declined
                  comment: Suspected fraud
              Resubmit Specific Steps:
                summary: >-
                  Solicitar reenvío de los pasos elegidos, con correo
                  electrónico
                value:
                  new_status: Resubmitted
                  nodes_to_resubmit:
                    - node_id: feature_ocr
                      feature: OCR
                    - node_id: feature_liveness
                      feature: LIVENESS
                  send_email: true
                  email_address: user@example.com
                  email_language: en
              Resubmit Auto-select:
                summary: >-
                  Solicitar reenvío (selección automática de los pasos no
                  aprobados)
                value:
                  new_status: Resubmitted
              Approve With Previewed Email:
                summary: >-
                  Aprobar y enviar el correo electrónico devuelto por Preview
                  Decision Email
                value:
                  new_status: Approved
                  send_email: true
                  email_address: person@example.com
                  email_language: en
                  email_preview_token: >-
                    eyJkaWdlc3QiOiI0ZjJhIn0:1uExAm:Pl3x4mpleS1gnatureValue000000000000000
      responses:
        '200':
          description: >-
            Estado actualizado. La respuesta solo contiene el `session_id`;
            obtén la sesión actualizada con [Obtener
            decisión](#get-/v3/session/-sessionId-/decision/). El webhook
            `status.updated` se dispara una vez que se confirma el cambio.
            Repetir `Approved` o `Declined` devuelve el mismo cuerpo y no cambia
            nada.
          content:
            application/json:
              schema:
                type: object
                properties:
                  session_id:
                    type: string
                    format: uuid
                    description: UUID de la sesión actualizada.
              examples:
                Updated:
                  summary: Se devuelve por igual para Approved, Declined y Resubmitted
                  value:
                    session_id: 3472fb7c-8f7c-4d1a-9cf4-cf3d74ce1a60
        '400':
          description: >-
            Error de validación. Los errores de campo llegan como `{"<field>":
            ["<message>"]}` (algunos rechazos por reglas de negocio usan en su
            lugar un valor de cadena: `{"nodes_to_resubmit": "<message>"}`), los
            errores entre estados como `{"detail": "<message>"}`, y el error de
            mismo estado como un array JSON sin envolver.
          content:
            application/json:
              examples:
                Wrong Current Status:
                  summary: La sesión no está en un estado que permita actualizarla
                  value:
                    detail: >-
                      Only sessions with status Approved, Declined, In Review,
                      Kyc Expired, Abandoned, Resubmitted can be updated.
                      Current status: In Progress
                Invalid Status Value:
                  summary: >-
                    new_status es un estado de sesión real, pero no es Approved,
                    Declined ni Resubmitted
                  value:
                    new_status:
                      - >-
                        You can only update the status to 'Approved',
                        'Declined', or 'Resubmitted'.
                Missing new_status:
                  summary: Campo obligatorio omitido
                  value:
                    new_status:
                      - This field is required.
                Same Status:
                  summary: >-
                    Se solicitó Resubmitted en una sesión que ya está en
                    Resubmitted
                  value:
                    - The new status is the same as the current status.
                Email Address Required:
                  summary: send_email es true sin email_address
                  value:
                    email_address:
                      - Email address is required when send_email is true.
                Non-resubmittable Feature:
                  summary: El reenvío apunta a una comprobación principal de KYB
                  value:
                    nodes_to_resubmit: >-
                      The following features cannot be resubmitted directly:
                      KYB_REGISTRY. Resubmit the relevant child KYC sessions
                      instead; the parent will recompute automatically.
                Nothing To Resubmit:
                  summary: La selección automática no encontró funciones no aprobadas
                  value:
                    nodes_to_resubmit: >-
                      No features found that need resubmission. All features are
                      already approved.
                Invalid Feature Choice:
                  summary: Función desconocida en nodes_to_resubmit
                  value:
                    nodes_to_resubmit:
                      - feature:
                          - >-
                            "BOGUS" is not a valid choice. Valid choices are:
                            OCR, OCR_BACK, NFC, AML, FACE, LIVENESS, FACE_MATCH,
                            IP_ANALYSIS, AGE_ESTIMATION, PROOF_OF_ADDRESS,
                            PHONE_VERIFICATION, EMAIL_VERIFICATION, FACE_SEARCH,
                            DATABASE_VALIDATION, QUESTIONNAIRE, KYB_REGISTRY,
                            KYB_DOCUMENTS, KYB_KEY_PEOPLE, ID_VERIFICATION, POA,
                            PHONE, EMAIL, KYB
                Invalid Status Value (not a status at all):
                  summary: new_status no es un valor válido de StatusChoices
                  value:
                    new_status:
                      - '"Bogus" is not a valid choice.'
                Preview Receipt Without Email:
                  summary: 'Se envió email_preview_token sin send_email: true'
                  value:
                    email_preview_token:
                      - A preview receipt is only valid when the email is sent.
        '401':
          description: La clave de API con alcance limitado ha expirado.
          content:
            application/json:
              examples:
                Expired API Key:
                  summary: >-
                    Clave de API con alcance limitado con la fecha de caducidad
                    vencida
                  value:
                    detail: This API key has expired.
        '403':
          description: >-
            Faltan las credenciales o los permisos son insuficientes, o el
            `session_id` pertenece a otra aplicación.
          content:
            application/json:
              examples:
                Invalid Credentials:
                  summary: x-api-key ausente o no válido
                  value:
                    detail: >-
                      Authentication credentials were not provided or are
                      invalid.
                Missing Privilege:
                  summary: La clave de API no tiene el permiso write:sessions
                  value:
                    detail: You do not have permission to perform this action.
        '404':
          description: >-
            No existe ninguna sesión KYC o KYB con este `session_id` (las
            sesiones eliminadas también devuelven `404`).
          content:
            application/json:
              examples:
                Not Found:
                  summary: session_id desconocido
                  value:
                    detail: Not found.
        '409':
          description: >-
            La vista previa del correo electrónico cambió o expiró. Genera una
            nueva vista previa antes de confirmar; no se producen cambios en la
            sesión ni se realiza la entrega del correo electrónico.
          content:
            application/json:
              examples:
                Preview Changed:
                  summary: El comprobante ya no coincide o tiene más de 15 minutos
                  value:
                    detail: >-
                      This email preview changed or expired. Preview the message
                      again before confirming.
        '429':
          description: >-
            Se repitió un reenvío dirigido solo a funciones exclusivas del
            backend (AML, DATABASE_VALIDATION, IP_ANALYSIS) dentro del periodo
            de espera de 30 segundos; una repetición inmediata no puede cambiar
            el resultado. Espera y reintenta pasado el intervalo indicado en
            `Retry-After`.
          content:
            application/json:
              examples:
                Backend-only resubmit throttled:
                  value:
                    detail: >-
                      This session was already resubmitted for backend-only
                      features within the last 30 seconds; repeating it cannot
                      change the outcome. Wait before resubmitting again.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X PATCH \
              https://verification.didit.me/v3/session/11111111-2222-3333-4444-555555555555/update-status/ \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "new_status": "Approved",
                "comment": "All checks passed manual review"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.sessions.update_status(
                "11111111-2222-3333-4444-555555555555",
                new_status="Approved",
                comment="All checks passed manual review",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: >-
            import Didit from "@didit-protocol/sdk-node";


            // Reads DIDIT_API_KEY.

            const didit = new Didit();


            const result = await
            didit.sessions.updateStatus("11111111-2222-3333-4444-555555555555",
            {
              new_status: "Approved",
              comment: "All checks passed manual review",
            });

            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Sessions.UpdateStatus(ctx, \"11111111-2222-3333-4444-555555555555\", didit.SessionsUpdateStatusParams{\n\tNewStatus: \"Approved\",\n\tComment:   didit.String(\"All checks passed manual review\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: >-
            import me.didit.Didit;

            import me.didit.types.SessionsUpdateStatusParams;


            // Reads DIDIT_API_KEY.

            Didit client = new Didit();


            var result =
            client.sessions().updateStatus("11111111-2222-3333-4444-555555555555",
            SessionsUpdateStatusParams.builder()
                    .newStatus(SessionsUpdateStatusParams.NewStatus.of("Approved"))
                    .comment("All checks passed manual review")
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: >-
            <?php


            require 'vendor/autoload.php';


            use Didit\DiditClient;


            // Reads DIDIT_API_KEY.

            $didit = new DiditClient();


            $result =
            $didit->sessions->updateStatus('11111111-2222-3333-4444-555555555555',
            [
                'new_status' => 'Approved',
                'comment' => 'All checks passed manual review',
            ]);

            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Reads DIDIT_API_KEY.
            didit = Didit::Client.new

            result = didit.sessions.update_status(
              "11111111-2222-3333-4444-555555555555",
              new_status: "Approved",
              comment: "All checks passed manual review"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Text.Json;

            using Didit;


            // Reads DIDIT_API_KEY.

            using var client = new DiditClient();


            var result = await
            client.Sessions.UpdateStatusAsync("11111111-2222-3333-4444-555555555555",
            new SessionsUpdateStatusParams

            {
                NewStatus = "Approved",
                Comment = "All checks passed manual review",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        La clave de API de tu aplicación, que encontrarás en Developers -> API
        keys en la Business Console. La clave principal tiene acceso completo.
        Una clave con nombre puede tener un alcance limitado: ninguno, lectura o
        escritura por recurso, limitada a algunos flujos o a sesiones aprobadas,
        a una lista de direcciones IP y a una fecha de caducidad. 401 significa
        que la clave es incorrecta, se revocó o expiró; 403 significa que no se
        envió ninguna clave, que la clave no tiene acceso a este recurso o
        acción, o que la solicitud provino de una dirección fuera de su lista de
        IP; 404 en una ruta de sesión significa que la sesión está fuera de los
        flujos o estados de la clave. Una clave sin acceso a contenido
        multimedia recibe las URL de imágenes, videos y PDF como null, y una
        clave sin permiso de escritura en sesiones recibe los enlaces y tokens
        de sesión como null. Consulta https://docs.didit.me/console/api-keys.

````

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