> ## Documentation Index
> Fetch the complete documentation index at: https://gotrebol.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ejecutar la Síntesis de Dictamen bajo demanda

> Encola una corrida de la Síntesis de Dictamen (`findings`) para la verificación, sin esperar a que un nuevo documento la dispare automáticamente.

La corrida pasa por el mismo pipeline con deduplicación que usan las corridas automáticas, así que nunca genera corridas duplicadas.

**La respuesta es asíncrona.** El endpoint responde `202` en cuanto la corrida queda encolada, sin esperar a que termine; la corrida tarda unos segundos y su resultado se lee en el campo `findings` de [Obtener una verificación por su ID](https://docs.gotrebol.com/api-reference/leer-información-de-la-empresa/obtener-una-verificación-por-su-id). Para saber que terminó, guarda el `findings.computed_at` que tenías antes de llamar y consulta la verificación cada 3-5 segundos hasta que ese valor cambie (o hasta que `findings` deje de ser `null`, si nunca había corrido). Un límite de ~2 minutos es holgado; si se agota, vuelve a consultar más tarde en vez de reintentar el `POST`, porque la corrida encolada sigue en curso.

A diferencia de las corridas automáticas, una corrida pedida por este endpoint **no exige que haya cambiado algún documento**: varios hallazgos dependen de la vigencia de los documentos, así que las conclusiones pueden cambiar con el calendario aunque las entradas sean idénticas. Para acotar el costo hay un periodo mínimo entre corridas manuales (300 segundos por defecto), que se reporta como `recently_run`.

El `POST` **no lleva body**; la verificación se identifica por la URL.

Devuelve `409` con un `error_code` cuando la corrida no procede. Qué hacer en cada caso:

| `error_code` | Qué pasó | Qué hacer |
| --- | --- | --- |
| `not_enabled` | La cuenta no tiene habilitada la Síntesis de Dictamen. | No es activable por API: escríbenos para habilitarla. Reintentar no cambia el resultado. |
| `pending_documents` | Hay documentos requeridos sin subir o aún en procesamiento. | Sube los que falten. Para saber cuándo reintentar, consulta la verificación y espera a que los items que lista `pending_items` tengan `item_status: "complete"`; no reintentes el `POST` a ciegas. |
| `already_scheduled` | Ya hay una corrida encolada o en ejecución. | **No reintentes el `POST`**: ya vas a recibir el resultado. Pasa directo a sondear `findings.computed_at`, igual que tras un `202`. |
| `recently_run` | Hubo una corrida hace muy poco y sigue el periodo mínimo entre corridas manuales. | Espera los segundos que indica `retry_after_seconds` y vuelve a pedirla. |

Un segundo `POST` mientras hay una corrida en vuelo responde `409 already_scheduled`, nunca un `202` que duplique la corrida.

Para los códigos de error generales de la API (`401`, `404`, `500`), consulta [Errores](https://docs.gotrebol.com/guia-devs/errores).

### Ejemplo

```bash
curl -X POST "https://api.gotrebol.com/verifications/{verification-id}/findings/run" \
  -H "x-api-key: TU_API_KEY"
```


Sustituye `{verification-id}` por el id que te devolvió `POST /verifications` y
`TU_API_KEY` por tu API key. Si la corrida queda encolada, la respuesta es:


```json
{ "status": "queued" }
```

Y el ciclo completo, pidiendo la corrida y esperando su resultado:

```js
const verificationId = "c8dc41fc-c477-404e-aff7-b9074f86d6d1"; // el id de tu verificación
const headers = { "x-api-key": process.env.TREBOL_API_KEY };
const base = `https://api.gotrebol.com/verifications/${verificationId}`;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

// fetch no rechaza ante un status de error: hay que revisarlo a mano, o un
// 401 durante el sondeo se ve igual que "todavía no termina".
async function getVerification() {
  const res = await fetch(base, { headers });
  if (!res.ok) throw new Error(`Trébol respondió ${res.status}`);
  return res.json();
}

// 1. Guarda el computed_at actual: es la referencia para saber si ya corrió.
const previous = (await getVerification()).findings?.computed_at ?? null;

// 2. Pide la corrida, reintentando cuando el cooldown lo pide.
while (true) {
  const run = await fetch(`${base}/findings/run`, { method: "POST", headers });
  if (run.status === 202) break;
  if (run.status !== 409) throw new Error(`Trébol respondió ${run.status}`);

  const { error_code, retry_after_seconds } = await run.json();
  // Ya hay una corrida en vuelo: su resultado es el que esperas igual.
  if (error_code === "already_scheduled") break;
  // Corrió hace poco. Es el caso normal al revalidar por vigencia.
  if (error_code === "recently_run") {
    await sleep((retry_after_seconds ?? 60) * 1000);
    continue;
  }
  // not_enabled y pending_documents no se resuelven reintentando.
  throw new Error(`corrida rechazada: ${error_code}`);
}

// 3. Sondea hasta que computed_at cambie (~2 min es holgado).
const deadline = Date.now() + 120_000;
while (Date.now() < deadline) {
  await sleep(4000);
  const { findings } = await getVerification();
  if (findings?.computed_at && findings.computed_at !== previous) {
    return findings; // hallazgos frescos
  }
}
// Se agotó la espera. La corrida sigue en curso: no es un fallo, así que
// devuelve los hallazgos que ya tenías y vuelve a consultar más tarde.
return (await getVerification()).findings;
```




## OpenAPI

````yaml /api-reference/openapi.yaml post /verifications/{verification-id}/findings/run
openapi: 3.0.0
info:
  title: Coleccion de API KYB MX
  description: >
    La Colección de API KYB MX proporciona puntos finales para crear y gestionar
    verificaciones de empresas en México. La verificación de empresas implica
    validar la información proporcionada por un cliente comercial, incluyendo
    documentos y fuentes de datos, para asegurar su legitimidad y precisión.


    Cada verificación de empresa puede incluir múltiples ítems, como Actas
    Constitutivas, Constancias de Situación Fiscal, Identificaciones Personales
    y Comprobantes de Domicilio. Trebol maneja automáticamente la clasificación
    de documentos, lo que te permite enviar todos los documentos requeridos como
    URLs descargables (por ejemplo, URLs prefirmadas de AWS o GCP).


    **Autenticación**: 

    La API utiliza una clave API para la autenticación, pasada en el encabezado
    `x-api-key`. Para obtener una clave API, por favor
    [contáctanos](mailto:sales@gotrebol.com).
  version: 1.0.0
servers:
  - url: https://api.gotrebol.com
  - url: http://{{trebol_api_base_url}}
security: []
tags:
  - name: Creacion de Verificacion
    description: Endpoints para crear nuevas verificaciones.
  - name: Leer información de la empresa
    description: >-
      Endpoints v2 para obtener información detallada de empresas y
      verificaciones.
  - name: Leer por Etiqueta
    description: >-
      Endpoints para obtener información detallada sobre empresas mediante
      etiquetas.
  - name: Leer por ID de Verificacion
    description: >-
      Endpoints para obtener información detallada sobre verificaciones mediante
      ID.
  - name: Gestión de IPs Permitidas
    description: >-
      Endpoints para gestionar la lista de IPs permitidas (whitelist) para la
      cuenta del cliente.
  - name: Gestión de API Keys
    description: Endpoints para crear, listar y eliminar API keys de la cuenta del usuario.
  - name: Gestion de item Ids
    description: Endpoints para gestionar items de verificaciones.
  - name: Invalidar un documento
    description: Endpoints para invalidar documentos de verificaciones.
  - name: Labels de Verificacion
    description: Endpoints para gestionar labels de verificaciones.
  - name: Actualizar personas clave de una verificacion
    description: Endpoints para actualizar personas clave de verificaciones.
  - name: Agregar items a una verificacion
    description: Endpoints para agregar items a verificaciones existentes.
  - name: Estado de validacion de documentos
    description: Endpoints para obtener el estado de validación de documentos.
  - name: Gestión de Flujos de Cuenta
    description: Endpoints para gestionar flujos de cuenta.
  - name: Gestión de Webhooks
    description: Endpoints para crear, listar, actualizar y eliminar webhooks de la cuenta.
  - name: Gestión de Política de Retención
    description: Endpoints para gestionar la política de retención de datos de la cuenta.
  - name: Exportación de Verificaciones
    description: >-
      Endpoints para exportar datos de verificaciones a documentos
      personalizados.
  - name: Leer información de la empresa v1
    description: >-
      Endpoints v1 (legacy) para obtener información detallada de empresas y
      verificaciones. Te recomendamos migrar a los endpoints v2.
  - name: Tipos de Ítem Personalizados
    description: >-
      Endpoints para crear y gestionar tipos de ítem personalizados con procesos
      configurables de clasificación, validación y extracción.
  - name: Síntesis de Dictamen
    description: >-
      Endpoints para ejecutar bajo demanda la Síntesis de Dictamen (`findings`)
      de una verificación.
paths:
  /verifications/{verification-id}/findings/run:
    post:
      tags:
        - Síntesis de Dictamen
      summary: Ejecutar la Síntesis de Dictamen bajo demanda
      description: >
        Encola una corrida de la Síntesis de Dictamen (`findings`) para la
        verificación, sin esperar a que un nuevo documento la dispare
        automáticamente.


        La corrida pasa por el mismo pipeline con deduplicación que usan las
        corridas automáticas, así que nunca genera corridas duplicadas.


        **La respuesta es asíncrona.** El endpoint responde `202` en cuanto la
        corrida queda encolada, sin esperar a que termine; la corrida tarda unos
        segundos y su resultado se lee en el campo `findings` de [Obtener una
        verificación por su
        ID](https://docs.gotrebol.com/api-reference/leer-información-de-la-empresa/obtener-una-verificación-por-su-id).
        Para saber que terminó, guarda el `findings.computed_at` que tenías
        antes de llamar y consulta la verificación cada 3-5 segundos hasta que
        ese valor cambie (o hasta que `findings` deje de ser `null`, si nunca
        había corrido). Un límite de ~2 minutos es holgado; si se agota, vuelve
        a consultar más tarde en vez de reintentar el `POST`, porque la corrida
        encolada sigue en curso.


        A diferencia de las corridas automáticas, una corrida pedida por este
        endpoint **no exige que haya cambiado algún documento**: varios
        hallazgos dependen de la vigencia de los documentos, así que las
        conclusiones pueden cambiar con el calendario aunque las entradas sean
        idénticas. Para acotar el costo hay un periodo mínimo entre corridas
        manuales (300 segundos por defecto), que se reporta como `recently_run`.


        El `POST` **no lleva body**; la verificación se identifica por la URL.


        Devuelve `409` con un `error_code` cuando la corrida no procede. Qué
        hacer en cada caso:


        | `error_code` | Qué pasó | Qué hacer |

        | --- | --- | --- |

        | `not_enabled` | La cuenta no tiene habilitada la Síntesis de Dictamen.
        | No es activable por API: escríbenos para habilitarla. Reintentar no
        cambia el resultado. |

        | `pending_documents` | Hay documentos requeridos sin subir o aún en
        procesamiento. | Sube los que falten. Para saber cuándo reintentar,
        consulta la verificación y espera a que los items que lista
        `pending_items` tengan `item_status: "complete"`; no reintentes el
        `POST` a ciegas. |

        | `already_scheduled` | Ya hay una corrida encolada o en ejecución. |
        **No reintentes el `POST`**: ya vas a recibir el resultado. Pasa directo
        a sondear `findings.computed_at`, igual que tras un `202`. |

        | `recently_run` | Hubo una corrida hace muy poco y sigue el periodo
        mínimo entre corridas manuales. | Espera los segundos que indica
        `retry_after_seconds` y vuelve a pedirla. |


        Un segundo `POST` mientras hay una corrida en vuelo responde `409
        already_scheduled`, nunca un `202` que duplique la corrida.


        Para los códigos de error generales de la API (`401`, `404`, `500`),
        consulta [Errores](https://docs.gotrebol.com/guia-devs/errores).


        ### Ejemplo


        ```bash

        curl -X POST
        "https://api.gotrebol.com/verifications/{verification-id}/findings/run"
        \
          -H "x-api-key: TU_API_KEY"
        ```



        Sustituye `{verification-id}` por el id que te devolvió `POST
        /verifications` y

        `TU_API_KEY` por tu API key. Si la corrida queda encolada, la respuesta
        es:



        ```json

        { "status": "queued" }

        ```


        Y el ciclo completo, pidiendo la corrida y esperando su resultado:


        ```js

        const verificationId = "c8dc41fc-c477-404e-aff7-b9074f86d6d1"; // el id
        de tu verificación

        const headers = { "x-api-key": process.env.TREBOL_API_KEY };

        const base = `https://api.gotrebol.com/verifications/${verificationId}`;

        const sleep = (ms) => new Promise((r) => setTimeout(r, ms));


        // fetch no rechaza ante un status de error: hay que revisarlo a mano, o
        un

        // 401 durante el sondeo se ve igual que "todavía no termina".

        async function getVerification() {
          const res = await fetch(base, { headers });
          if (!res.ok) throw new Error(`Trébol respondió ${res.status}`);
          return res.json();
        }


        // 1. Guarda el computed_at actual: es la referencia para saber si ya
        corrió.

        const previous = (await getVerification()).findings?.computed_at ??
        null;


        // 2. Pide la corrida, reintentando cuando el cooldown lo pide.

        while (true) {
          const run = await fetch(`${base}/findings/run`, { method: "POST", headers });
          if (run.status === 202) break;
          if (run.status !== 409) throw new Error(`Trébol respondió ${run.status}`);

          const { error_code, retry_after_seconds } = await run.json();
          // Ya hay una corrida en vuelo: su resultado es el que esperas igual.
          if (error_code === "already_scheduled") break;
          // Corrió hace poco. Es el caso normal al revalidar por vigencia.
          if (error_code === "recently_run") {
            await sleep((retry_after_seconds ?? 60) * 1000);
            continue;
          }
          // not_enabled y pending_documents no se resuelven reintentando.
          throw new Error(`corrida rechazada: ${error_code}`);
        }


        // 3. Sondea hasta que computed_at cambie (~2 min es holgado).

        const deadline = Date.now() + 120_000;

        while (Date.now() < deadline) {
          await sleep(4000);
          const { findings } = await getVerification();
          if (findings?.computed_at && findings.computed_at !== previous) {
            return findings; // hallazgos frescos
          }
        }

        // Se agotó la espera. La corrida sigue en curso: no es un fallo, así
        que

        // devuelve los hallazgos que ya tenías y vuelve a consultar más tarde.

        return (await getVerification()).findings;

        ```
      operationId: ejecutarRevisionDeHallazgos
      parameters:
        - $ref: '#/components/parameters/verificationIdParam'
      responses:
        '202':
          description: Corrida de hallazgos encolada.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - queued
                    description: >-
                      Estado de la solicitud. Siempre `queued` cuando la corrida
                      queda encolada.
              example:
                status: queued
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '409':
          description: >-
            La corrida no procede en el estado actual de la verificación. Revisa
            `error_code` para saber la causa.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FindingsRunConflict'
              examples:
                NotEnabled:
                  summary: not_enabled
                  value:
                    error_code: not_enabled
                    message: The findings analysis is not enabled for this account.
                PendingDocuments:
                  summary: pending_documents
                  value:
                    error_code: pending_documents
                    pending_items:
                      - Acta constitutiva
                      - constancia_situacion_fiscal_mx
                    message: >-
                      Findings cannot run yet: some required documents are still
                      uploading or being processed.
                AlreadyScheduled:
                  summary: already_scheduled
                  value:
                    error_code: already_scheduled
                    message: >-
                      A findings run is already queued or in progress for this
                      verification.
                RecentlyRun:
                  summary: recently_run
                  value:
                    error_code: recently_run
                    retry_after_seconds: 240
                    message: >-
                      Findings were recalculated moments ago. Try again in 240
                      seconds.
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - ApiKeyAuth: []
components:
  parameters:
    verificationIdParam:
      name: verification-id
      in: path
      required: true
      description: El ID único de la verificación
      schema:
        type: string
  responses:
    UnauthorizedError:
      description: No autorizado
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            Unauthorized:
              summary: Falta API key o inválida
              value:
                success: false
                message: Unauthorized
                code: UNAUTHORIZED
                timestamp: '2025-01-01T12:34:56.000Z'
    NotFoundError:
      description: Recurso no encontrado
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            NotFound:
              summary: Recurso inexistente
              value:
                success: false
                message: Entity not found
                code: NOT_FOUND
                timestamp: '2025-01-01T12:34:56.000Z'
    InternalServerError:
      description: Error interno del servidor
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            ServerError:
              summary: Error inesperado
              value:
                success: false
                message: Internal server error
                code: INTERNAL_SERVER_ERROR
                timestamp: '2025-01-01T12:34:56.000Z'
  schemas:
    FindingsRunConflict:
      type: object
      description: >
        Respuesta `409` de `POST /verifications/{verification-id}/findings/run`
        cuando la corrida de hallazgos no procede en el estado actual de la
        verificación.


        Este cuerpo usa `error_code`, no el `code` de `ErrorResponse`, a
        propósito: `code` clasifica el error de forma genérica
        (`VALIDATION_ERROR`, `NOT_FOUND`) y acompaña a `success: false`,
        mientras que `error_code` dice qué condición del negocio impide la
        corrida y se lee para decidir qué hacer a continuación. Ver STYLE_GUIDE,
        "No duplicar significado".
      properties:
        error_code:
          type: string
          enum:
            - not_enabled
            - pending_documents
            - already_scheduled
            - recently_run
            - up_to_date
          description: >
            Causa por la que la corrida no procede. `not_enabled`: la cuenta no
            tiene habilitada la Síntesis de Dictamen. `pending_documents`: hay
            documentos requeridos sin subir o aún en procesamiento.
            `already_scheduled`: ya hay una corrida encolada o en ejecución.
            `recently_run`: hubo una corrida manual hace muy poco y aún corre el
            periodo mínimo entre corridas. `up_to_date`: nada cambió desde la
            última corrida — este endpoint **no** devuelve este código (las
            corridas bajo demanda no exigen que haya cambiado un documento);
            queda en el enum porque el mismo esquema describe las corridas
            automáticas.
        message:
          type: string
          description: Descripción legible de la causa, pensada para mostrarse tal cual.
        pending_items:
          type: array
          description: >
            Solo cuando `error_code` es `pending_documents`: los items de
            documento que bloquean la corrida (nombre configurado del item o, en
            su defecto, su tipo). Vacía cuando todavía no se sube ningún
            documento requerido.
          items:
            type: string
        retry_after_seconds:
          type: integer
          description: >
            Solo cuando `error_code` es `recently_run`: segundos que faltan para
            poder pedir otra corrida. Es el tiempo restante, no la duración
            total del periodo mínimo entre corridas.
          example: 240
      required:
        - error_code
        - message
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: Descripción breve y accionable del error
        code:
          oneOf:
            - type: string
              enum:
                - VALIDATION_ERROR
                - BAD_REQUEST
                - UNAUTHORIZED
                - FORBIDDEN
                - NOT_FOUND
                - CONFLICT
                - DUPLICATE_RESOURCE
                - INTERNAL_SERVER_ERROR
            - type: string
              description: Código de dominio específico (p.ej., items_not_provided)
          example: VALIDATION_ERROR
        timestamp:
          type: string
          format: date-time
          example: '2025-01-01T12:34:56.000Z'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````