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

# Engines

> Como cada motor decide o que verificar: resolução da engine (engine_id/engine_id), ações, templates do sistema e blocos

Uma **engine** é a configuração de uma análise: ela define quais blocos de verificação rodam e a **ação** aplicada quando um bloco é acionado — bloqueio, alerta ou ignorar. Todo `POST /analyses` e todo `POST /operations` roda com exatamente uma engine, e é ela que determina o resultado — os verdicts no Motor de CPF/CNPJ, os `status` e as `issues` no Motor de Borderô.

## Ações e efeito no resultado

| Ação                   | Efeito no CPF/CNPJ                                                                           | Efeito no Borderô                                                                                  |
| ---------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| **Bloqueio** (`block`) | Bloco acionado sai com status `blocked`; qualquer bloco `blocked` → verdict `reprovado`      | Issue de `category: "blocking"` no nó; pelo rollup worst-of, o nó (e os acima dele) fica `blocked` |
| **Alerta** (`alert`)   | Bloco acionado sai com status `alert`; um ou mais `alert` (sem `blocked`) → verdict `alerta` | Issue de `category: "alert"` no nó; sem nenhum bloqueio, o nó fica `alerted`                       |
| **Ignorar** (`ignore`) | Bloco não é avaliado                                                                         | Regra não é avaliada                                                                               |

Se nenhuma verificação é acionada, o resultado é `aprovado` (CPF/CNPJ) ou `approved` (borderô). Se o motor termina mas uma fonte de dados falhou: no CPF/CNPJ o verdict fica `incompleto`; no borderô, a regra afetada vai para `degraded_rules` e os títulos afetados contam como `alerted` no summary. Veja [Ciclo de vida](/motores/ciclo-de-vida).

Blocos marcados como **ignorar** nos templates são opt-in: vêm desligados por padrão e passam a contar quando você muda a ação para alerta ou bloqueio em uma engine própria.

## Como a engine é resolvida

O campo é **opcional** nos dois motores — `engine_id` no body JSON do Motor de CPF/CNPJ, `engine_id` como parte de texto do multipart no Motor de Borderô:

1. **Explícito** — a engine precisa existir e pertencer ao seu workspace (ou ser um template do sistema).
2. **Omitido** — no Motor de CPF/CNPJ, a API usa a engine padrão do workspace para o `subject_type` e, na falta dela, o template do sistema (PJ ou PF). No Motor de Borderô, `engine_id` omitido **ou com o valor `template-padrao`** usa a engine template de borderô do sistema.

### Erros de resolução

| Situação                                                                            | Resposta                                 |
| ----------------------------------------------------------------------------------- | ---------------------------------------- |
| **CPF/CNPJ:** `engine_id` inexistente ou de outro workspace                         | `404` [`not_found`](/problems/not_found) |
| Engine arquivada                                                                    | `422` [`no_engine`](/problems/no_engine) |
| Engine incompatível com a requisição (ex.: engine PJ para um CPF)                   | `422` [`no_engine`](/problems/no_engine) |
| Engine de borderô não utilizável                                                    | `422` [`no_engine`](/problems/no_engine) |
| Nenhuma engine resolvida (sem engine explícita, sem padrão, sem template aplicável) | `422` [`no_engine`](/problems/no_engine) |

<Note>
  No Motor de CPF/CNPJ, `engine_id` inexistente ou de outro workspace retorna `404 not_found` — a API não revela a existência de engines de outros workspaces.
</Note>

### Exemplo com engine explícita

<Note>
  Os Motores usam a **mesma base** da API 221b (`https://221b-api.sherlocker.com.br/api/v1`), mas autenticam via `Authorization: Bearer slhk_…` — **não** via `?token=`.
</Note>

<Tabs>
  <Tab title="CPF/CNPJ">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://221b-api.sherlocker.com.br/api/v1/analyses" \
        -H "Authorization: Bearer slhk_sua_chave_aqui" \
        -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
        -H "Content-Type: application/json" \
        -d '{
          "document": "12345678000195",
          "engine_id": "0b3c6c7e-9d2a-4f1b-8e5d-2a1b3c4d5e6f"
        }'
      ```

      ```python Python theme={null}
      import requests

      resp = requests.post(
          "https://221b-api.sherlocker.com.br/api/v1/analyses",
          headers={
              "Authorization": "Bearer slhk_sua_chave_aqui",
              "Idempotency-Key": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
          },
          json={
              "document": "12345678000195",
              "engine_id": "0b3c6c7e-9d2a-4f1b-8e5d-2a1b3c4d5e6f",
          },
      )
      print(resp.status_code, resp.json())
      ```

      ```javascript Node.js theme={null}
      const resp = await fetch("https://221b-api.sherlocker.com.br/api/v1/analyses", {
        method: "POST",
        headers: {
          "Authorization": "Bearer slhk_sua_chave_aqui",
          "Idempotency-Key": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          document: "12345678000195",
          engine_id: "0b3c6c7e-9d2a-4f1b-8e5d-2a1b3c4d5e6f",
        }),
      });
      console.log(resp.status, await resp.json());
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Borderô">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST "https://221b-api.sherlocker.com.br/api/v1/operations" \
        -H "Authorization: Bearer slhk_sua_chave_aqui" \
        -F "file=@bordero.rem" \
        -F "cedente_cnpj=12345678000195" \
        -F "engine_id=0b3c6c7e-9d2a-4f1b-8e5d-2a1b3c4d5e6f"
      ```

      ```python Python theme={null}
      import requests

      with open("bordero.rem", "rb") as cnab:
          resp = requests.post(
              "https://221b-api.sherlocker.com.br/api/v1/operations",
              headers={"Authorization": "Bearer slhk_sua_chave_aqui"},
              files={"file": cnab},
              data={
                  "cedente_cnpj": "12345678000195",
                  "engine_id": "0b3c6c7e-9d2a-4f1b-8e5d-2a1b3c4d5e6f",
              },
          )
      print(resp.status_code, resp.json())
      ```

      ```javascript Node.js theme={null}
      import { openAsBlob } from "node:fs";

      const form = new FormData();
      form.append("file", await openAsBlob("bordero.rem"), "bordero.rem");
      form.append("cedente_cnpj", "12345678000195");
      form.append("engine_id", "0b3c6c7e-9d2a-4f1b-8e5d-2a1b3c4d5e6f");

      const resp = await fetch("https://221b-api.sherlocker.com.br/api/v1/operations", {
        method: "POST",
        headers: { Authorization: "Bearer slhk_sua_chave_aqui" },
        body: form,
      });
      console.log(resp.status, await resp.json());
      ```
    </CodeGroup>

    <Warning>
      Se você usa o header opcional `Idempotency-Key`, o `engine_id` faz parte do payload comparado: reenviar o mesmo arquivo com a mesma key e um `engine_id` diferente resulta em `409 idempotency_conflict`. Veja [Idempotência](/motores/idempotencia).
    </Warning>
  </Tab>
</Tabs>

## Onde as engines são geridas

Engines são criadas, editadas, definidas como padrão e arquivadas **no app Sherlocker** (interface web). A API `/v1` não tem endpoints de CRUD de engines — ela só consome uma engine já existente via `engine_id` ou pela resolução automática. Para criar uma política própria (mudar ações, ajustar parâmetros, ativar blocos opt-in), use o app.

<Tip>
  No borderô, a resposta do `GET /operations/{id}` sempre traz o `engine_id` efetivamente usado — inclusive quando você omitiu o campo (ou enviou `template-padrao`) e a operação rodou com o template do sistema. Guarde-o se quiser reproduzir a mesma política em operações futuras.
</Tip>

## O que cada motor verifica

<Tabs>
  <Tab title="CPF/CNPJ">
    Quando o workspace não tem engine padrão e o `engine_id` é omitido, a análise roda com o template global do Sherlocker para o `subject_type`. São políticas conservadoras: irregularidade cadastral, óbito, sanção nacional, trabalho escravo e eventos de falência/recuperação judicial bloqueiam; sinais financeiros (Serasa, dívida ativa) e processos judiciais relevantes geram alerta.

    Os parâmetros listados abaixo são os valores padrão do template. Cada bloco aceita parâmetros configuráveis por engine no app — o catálogo completo está em [Blocos](/motor-analise/blocos).

    ### Sherlocker PJ (template) — 23 blocos

    Usado em análises de CNPJ (`subject_type: "pj"`).

    **Bloqueio**

    | Bloco                     | Parâmetros padrão                            |
    | ------------------------- | -------------------------------------------- |
    | `SITUACAO_CADASTRAL_CNPJ` | —                                            |
    | `FALENCIA_DECRETADA`      | —                                            |
    | `FALENCIA_REQUERIDA`      | `janela_meses: 6`, `janela_alerta_meses: 12` |
    | `RECUPERACAO_JUDICIAL`    | `janela_meses: 6`, `janela_alerta_meses: 12` |
    | `CONSULTA_OBITO`          | —                                            |
    | `LISTA_TRABALHO_ESCRAVO`  | —                                            |
    | `SANCAO_NACIONAL`         | —                                            |

    **Alerta**

    | Bloco                           | Parâmetros padrão                                   |
    | ------------------------------- | --------------------------------------------------- |
    | `IDADE_EMPRESA`                 | `meses_minimos: 12`                                 |
    | `CAPITAL_SOCIAL_MINIMO`         | `capital_minimo: 10000`                             |
    | `CNAE_RISCO`                    | `cnaes_risco`: lista com 13 CNAEs de risco          |
    | `DIVIDA_ATIVA`                  | `valor_minimo: 100000`                              |
    | `PROCESSOS_RELEVANTES`          | `minimo_como_reu: 10`, `termos_classe: []`          |
    | `ACORDOS_LENIENCIA`             | —                                                   |
    | `IBAMA`                         | —                                                   |
    | `SERASA_PROTESTOS`              | `quantidade_minima: 1`, `valor_minimo: 0`           |
    | `SERASA_PEFIN`                  | `quantidade_minima: 1`, `valor_minimo: 0`           |
    | `SERASA_REFIN`                  | `quantidade_minima: 1`, `valor_minimo: 0`           |
    | `SERASA_CHEQUES`                | `quantidade_minima: 1`                              |
    | `SERASA_PONTUALIDADE_PAGAMENTO` | `pontualidade_minima_pct: 85`                       |
    | `SERASA_EVOLUCAO_CONSULTAS`     | `crescimento_minimo_pct: 85`, `media_minima_3m: 14` |

    **Ignorado (opt-in)**

    | Bloco                    | Parâmetros padrão |
    | ------------------------ | ----------------- |
    | `EMPRESA_PUBLICA`        | —                 |
    | `SANCAO_INTERNACIONAL`   | —                 |
    | `DEBARMENT_MULTILATERAL` | —                 |

    ### Sherlocker PF (template) — 18 blocos

    Usado em análises de CPF (`subject_type: "pf"`). Lembre que análises de CPF exigem a feature `analysis_engine_pf` no workspace, além de `analysis_engine`.

    **Bloqueio**

    | Bloco                 | Parâmetros padrão |
    | --------------------- | ----------------- |
    | `CONSULTA_OBITO`      | —                 |
    | `SANCAO_NACIONAL`     | —                 |
    | `SERASA_SITUACAO_CPF` | —                 |

    **Alerta**

    | Bloco                           | Parâmetros padrão                          |
    | ------------------------------- | ------------------------------------------ |
    | `PROCESSOS_RELEVANTES`          | `minimo_como_reu: 10`, `termos_classe: []` |
    | `PEP`                           | —                                          |
    | `BANCO_CENTRAL`                 | —                                          |
    | `IBAMA`                         | —                                          |
    | `SERASA_PROTESTOS`              | `quantidade_minima: 1`, `valor_minimo: 0`  |
    | `SERASA_PEFIN`                  | `quantidade_minima: 1`, `valor_minimo: 0`  |
    | `SERASA_REFIN`                  | `quantidade_minima: 1`, `valor_minimo: 0`  |
    | `SERASA_CHEQUES`                | `quantidade_minima: 1`                     |
    | `SERASA_DIVIDAS_VENCIDAS`       | `quantidade_minima: 1`, `valor_minimo: 0`  |
    | `SERASA_ACOES_JUDICIAIS_PF`     | `quantidade_minima: 1`, `valor_minimo: 0`  |
    | `SERASA_DOCUMENTOS_ROUBADOS_PF` | —                                          |
    | `SERASA_ARQUIVO_FINO_PF`        | —                                          |

    **Ignorado (opt-in)**

    | Bloco                    | Parâmetros padrão      |
    | ------------------------ | ---------------------- |
    | `DIVIDA_ATIVA`           | `valor_minimo: 100000` |
    | `SANCAO_INTERNACIONAL`   | —                      |
    | `DEBARMENT_MULTILATERAL` | —                      |

    <Warning>
      Os blocos `SERASA_*` dependem da integração Serasa habilitada no workspace. Sem ela, esses blocos saem com status `unavailable` e o `verdict` fica `incompleto` — nunca um bloqueio falso. Confira o campo `coverage` da resposta para ver qual fonte ficou indisponível.
    </Warning>
  </Tab>

  <Tab title="Borderô">
    Uma **engine de borderô** reúne dois conjuntos de verificações, organizados por papel:

    * **Regras de título e de NFe** — validações aplicadas a cada título do arquivo: consistência dos dados do CNAB (valores, vencimentos) e cruzamento com o XML de NFe correspondente, quando o ZIP é enviado (veja [Títulos e NFe](/credito/titulos-e-nfe)).
    * **Regras de cedente e de sacado** — a política de risco aplicada a cada entidade única do borderô, com a mesma mecânica de blocos da aba CPF/CNPJ (bloqueio, alerta, ignorar).

    É essa engine que determina as **issues** de cada nó do resultado — e, pelo rollup worst-of, o `status` (`approved` | `blocked` | `alerted`) de títulos, sacados e do cedente. Sem `engine_id` (ou com `engine_id=template-padrao`), a operação roda com a **engine template de borderô do sistema** — a política padrão do Sherlocker para operações de desconto de duplicatas.

    Como cada regra reage — o que vira issue de `category: "alert"`, o que vira `blocking` — depende da configuração da engine. Uma engine de borderô não utilizável retorna `422 no_engine`.
  </Tab>
</Tabs>

## Próximos passos

<CardGroup cols={2}>
  <Card title="Blocos (CPF/CNPJ)" icon="cubes" href="/motor-analise/blocos">
    Catálogo completo de blocos de verificação, com escopo, grupo e descrição
  </Card>

  <Card title="Títulos e NFe (Borderô)" icon="file-invoice" href="/credito/titulos-e-nfe">
    As validações de título e o cruzamento com XMLs de NFe
  </Card>

  <Card title="Ciclo de vida" icon="arrows-rotate" href="/motores/ciclo-de-vida">
    Como a engine determina o resultado de cada motor
  </Card>

  <Card title="Erros" icon="triangle-exclamation" href="/motor-analise/erros">
    Formato RFC 7807, incluindo not\_found e no\_engine
  </Card>
</CardGroup>
