# QI Tech — Risk Solutions › Análise cadastral

Documentação da QI Tech em texto corrido, para colar em um LLM.
Fonte: https://docs.qitech.com.br
13 página(s).

Índice:
- Autenticação (/documentation/caas/onboarding/authentication)
- Status HTTP (/documentation/caas/onboarding/http_status)
- Integrações (/documentation/caas/onboarding/integrations)
- Introdução (/documentation/caas/onboarding/introduction)
- Objeto Legal Person (/documentation/caas/onboarding/legal_person)
- Objeto Natural Person (/documentation/caas/onboarding/natural_person)
- Objetos Compartilhados (/documentation/caas/onboarding/objects)
- Recuperar um Cadastro (/documentation/caas/onboarding/query_registration)
- Integrando os dados do SDK (face, documentos e device) (/documentation/caas/onboarding/sdk_integration)
- Padrões (/documentation/caas/onboarding/standards)
- Dinâmica dos status (/documentation/caas/onboarding/status_dynamics)
- Atualizar um cadastro (/documentation/caas/onboarding/update_registration)
- Webhook (/documentation/caas/onboarding/webhook)

---

# Autenticação

URL: /documentation/caas/onboarding/authentication

> Para autenticar uma chamada, utilize o código seguinte:

```shell
# No shell, você somente precisa adicionar o header adequado em cada requisição
curl "api_endpoint_here"
  -H "Authorization: EXAMPLE-OF-API-KEY"
```

> Substitua a API Key 'EXAMPLE-OF-API-KEY' pela sua chave, que deve ser obtida através do nosso time de suporte.

Utilizamos uma API Key para permitir acesso a nossa API. Ela provavelmente já foi enviada por e-mail para você. Caso você ainda não tenha recebido a sua chave, envie um e-mail para suporte.caas@qitech.com.br .

Nossa API espera receber a API Key em todas as requisições ao nosso servidor em um header como o abaixo:

`Authorization: EXAMPLE-OF-API-KEY`

:::info **Atenção**

Você deve substituir EXAMPLE-OF-API-KEY pela sua chave, que deve ser obtida através do nosso time de suporte.
:::

---

# Status HTTP

URL: /documentation/caas/onboarding/http_status

Todas as APIs da QI Tech utilizam a seguinte padronização nos status HTTP de retorno, de acordo com o RFC 7231 :

Status HTTP | Significado | Descrição
---------- | ------- | ---------------------------------
400 | Bad Request | A requisição enviada possui algum erro de formatação. Na maioria dos casos, retornamos no corpo da mensagem uma explicação de onde está o erro.
401 | Unauthorized | Houve algum problema na autenticação, verifique se a API Key está correta e no header correto, de acordo com a seção Autenticação .
403 | Forbidden | O endpoint acessado é de uso interno e não está disponível para esta API Key.
404 | Not Found | O dado requisitado não foi encontrado usando a chave utilizada. Este status também é retornado quando um endpoint inválido é requisitado.
405 | Method Not Allowed | O método HTTP utilizado não se aplica ao endpoint utilizado.
406 | Not Acceptable | Os dados enviados no corpo da requisição são inválidos. Em geral, isso significa que os dados enviados não são um JSON válido.
409 | Conflict | O id da requisição corresponde a um id já processado anteriormente. Este status é retornado no caso de requisições duplicadas enviadas ao servidor.
500 | Internal Server Error | Tivemos um problema para processar esta requisição, ao encontrarmos esse erro nossos especialistas são automaticamente notificados e iniciam a análise e solução imediatamente.
503 | Service Unavailable | Você se deparou com uma indisponibilidade, planejada ou não, de infraestrutura dos nossos servidores.

---

# Integrações

URL: /documentation/caas/onboarding/integrations

Nossas soluções mobile são compatíveis com as mais diversas tecnologias como Flutter, Ionic Cordova, Capacitor, React Native, Java, Swift entre outras. Caso tenha interesse em alguma dessas integrações, entre em contato com nosso suporte para liberarmos acesso aos nossos repositórios privados.

---

# Introdução

URL: /documentation/caas/onboarding/introduction

Bem vindo à API de Onboarding da QI Tech! Esta API dá acesso aos serviços de Prevenção a Fraudes, à lavagem de dinheiro e de KYC em um Cadastro da sua plataforma! 

Esta API pode ser utilizada para a validação cadastral de clientes para:

* Abertura de Contas Digitais ou Wallets
* Emissão de Cartão
* Validação de Usuários de Aplicativos
* Cadastro para Concessão de Crédito
* Cadastro para Contratação de Seguros
* Validação de Dados Cadastrais

Você pode utilizar a nossa API para acessar os endpoints para avaliar os seguintes tipos de Cadastro:

* **Natural Person** - utilizado para validação cadastral de Pessoas Físicas
* **Legal Person** - utilizado para validação cadastral de Pessoas Jurídicas

Os diferentes tipos de Cadastro acima possuem objetos e endpoints específicos com o intuito de cobrir as particularidades de cada entidade. 

## Como funciona

| Passo | Chamada | O que faz |
| --- | --- | --- |
| 1 | `POST /onboarding/natural_person` ou `/legal_person` | Envia o cadastro; a QI Tech executa a sua árvore de decisão e devolve o resultado em `analysis_status`. |
| 2 | `PUT /onboarding/{tipo}/{id}` | Informa o desfecho na sua plataforma (`client_status`). Retroalimenta os modelos. |
| 3 | `GET /onboarding/{tipo}/{id}` | Consulta o estado atual e o histórico de eventos. |

Resultados assíncronos chegam por [Webhook](/documentation/caas/onboarding/webhook).

:::tip Integre em minutos
São apenas **3 campos obrigatórios** em cada tipo de cadastro. Comece pelo payload mínimo em [Natural Person](/documentation/caas/onboarding/natural_person#payload-minimo) ou [Legal Person](/documentation/caas/onboarding/legal_person#payload-minimo), com exemplos em Python, PHP, Node.js, Java, C# e curl.
:::

:::info Usa os SDKs de biometria, OCR ou Device Scan?
As chaves devolvidas pelos SDKs entram em lugares diferentes em PF e PJ. Veja [Dados do SDK](/documentation/caas/onboarding/sdk_integration).
:::

## Problemas?

Nós não somos uma companhia que se esconde atrás de uma API! Entre em contato com o nosso suporte e nós responderemos o mais rápido possível. Fique à vontade para nos ligar caso deseje uma resposta rápida!

### Adoramos Feedback

Mesmo que você já tenha resolvido o seu problema ou que ele seja muito simples (Até mesmo um typo ou uma organização inadequada que você já notou), envie-nos um e-mail, assim nós tornamos a documentação cada vez mais prática e a próxima pessoa não vai precisar sofrer as dores que você sofreu!

## Ambientes

Possuímos dois ambientes para os nossos clientes. As URLs base das APIs são:

* Produção - `https://api.caas.qitech.app/onboarding/`
* Sandbox - `https://api.sandbox.caas.qitech.app/onboarding/`

:::danger Aviso Importante!
Não devem ser usados dados reais de pessoas físicas e/ou jurídicas nos ambientes de Sandbox da QI Tech.  
:::

No ambiente de Sandbox, as análises enviadas não são cobradas e são respondidas de acordo com a seguinte regra baseada no primeiro dígito do documento - CPF para Pessoas Físicas e CNPJ para Pessoas Jurídicas:

Dígito | Decisão
------ | -------
0 | Em Análise Manual
1 | Em Análise Manual
2 | Em Análise Manual
3 | Em Análise Manual
4 | Contestado Automaticamente
5 | Derivado para Análise Manual - Com reprovação posterior
6 | Derivado para Análise Manual - Com aprovação posterior
7 | Pendente
8 | Reprovado Automaticamente
9 | Aprovado Automaticamente

Nos casos de CPF ou CNPJ com início nos dígitos 1 ou 2, deve-se entrar em contato com nosso suporte para que a tratativa manual seja feita corretamente.

## Somente HTTPS

Por questão de segurança, toda a comunicação com as APIs da QI Tech deve ser realizada utilizando a comunicação HTTPS. Para evitar que, por desatenção ou outro motivo, sejam feitas chamadas HTTP, este servidor somente disponibiliza a porta 443 com comunicação TLS 1.2. Chamadas realizadas utilizando outros protocolos serão automaticamente negadas.

---

# Objeto Legal Person

URL: /documentation/caas/onboarding/legal_person

Objeto Legal Person

Envia o cadastro de uma **pessoa jurídica** para análise de fraude e KYC. A QI Tech executa a sua árvore de decisão contra os dados enviados e devolve em `analysis_status` o resultado que a **sua política** determinou — veja [Dinâmica dos status](/documentation/caas/onboarding/status_dynamics).

:::tip Comece pelo payload mínimo
São apenas **3 campos obrigatórios**. Vá direto para [Payload mínimo](#payload-minimo).
:::

:::danger Onde entram as chaves do SDK
Em Legal Person, `face` e documentos de identidade ficam **dentro de `legal_representatives[]`**, e o `source.session_id` fica na **raiz**. Essa é a principal diferença em relação a Pessoa Física — veja [Integrando os dados do SDK](/documentation/caas/onboarding/sdk_integration).
:::

---

## Payload mínimo

```json title="Payload mínimo — 3 campos obrigatórios"
{
  "id": "87654321",
  "registration_date": "2026-08-07T11:37:15-03:00",
  "document_number": "11.111.111/0001-11"
}
```

Resposta:

```json
{
  "id": "87654321",
  "analysis_status": "automatically_approved",
  "reason": "rule_decision_enum"
}
```

:::info Campos adicionais
Quanto mais dados forem enviados, mais validações são possíveis de se fazer no motor de regras.
:::

---

## Enviar um cadastro

ENDPOINT /onboarding/legal_person
MÉTODO POST

### Query parameters

analyze
boolean
opcional — padrão true
Com true , a sua árvore de decisão é executada. Com false , o cadastro é apenas registrado (sem cobrança) e a resposta retorna not_analysed .

**Python**

```python
import requests

BASE_URL = "https://api.sandbox.caas.qitech.app"
API_KEY = "YOUR_API_KEY"

payload = {
    "id": "87654321",
    "registration_date": "2026-08-07T11:37:15-03:00",
    "document_number": "11.111.111/0001-11"
}

response = requests.post(
    f"{BASE_URL}/onboarding/legal_person",
    params={"analyze": "true"},
    json=payload,
    headers={"Authorization": API_KEY},
    timeout=30,
)

response.raise_for_status()
print(response.json()["analysis_status"])
```

**PHP**

```php
<?php

$baseUrl = 'https://api.sandbox.caas.qitech.app';
$apiKey  = 'YOUR_API_KEY';

$payload = [
    'id'                => '87654321',
    'registration_date' => '2026-08-07T11:37:15-03:00',
    'document_number'   => '11.111.111/0001-11'
];

$ch = curl_init($baseUrl . '/onboarding/legal_person?analyze=true');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Authorization: ' . $apiKey
    ],
    CURLOPT_POSTFIELDS => json_encode($payload)
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 200) {
    throw new RuntimeException("Onboarding retornou HTTP {$status}: {$body}");
}

echo json_decode($body, true)['analysis_status'];
```

**Node.js**

```javascript
const BASE_URL = "https://api.sandbox.caas.qitech.app";
const API_KEY = "YOUR_API_KEY";

const payload = {
  id: "87654321",
  registration_date: "2026-08-07T11:37:15-03:00",
  document_number: "11.111.111/0001-11"
};

async function createLegalPerson() {
  const response = await fetch(
    `${BASE_URL}/onboarding/legal_person?analyze=true`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: API_KEY
      },
      body: JSON.stringify(payload)
    },
  );

  if (!response.ok) {
    throw new Error(`Onboarding retornou HTTP ${response.status}`);
  }

  const result = await response.json();
  console.log(result.analysis_status);
  return result;
}

createLegalPerson();
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class CreateLegalPerson {

    private static final String BASE_URL = "https://api.sandbox.caas.qitech.app";
    private static final String API_KEY = "YOUR_API_KEY";

    public static void main(String[] args) throws Exception {
        String payload = """
            {
              "id": "87654321",
              "registration_date": "2026-08-07T11:37:15-03:00",
              "document_number": "11.111.111/0001-11"
            }
            """;

        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/onboarding/legal_person?analyze=true"))
                .header("Content-Type", "application/json")
                .header("Authorization", API_KEY)
                .timeout(Duration.ofSeconds(30))
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

        HttpResponse<String> response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new IllegalStateException(
                    "Onboarding retornou HTTP " + response.statusCode() + ": " + response.body());
        }

        System.out.println(response.body());
    }
}
```

**C#**

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class CreateLegalPerson
{
    private const string BaseUrl = "https://api.sandbox.caas.qitech.app";
    private const string ApiKey = "YOUR_API_KEY";

    public static async Task Main()
    {
        var payload = new
        {
            id = "87654321",
            registration_date = "2026-08-07T11:37:15-03:00",
            document_number = "11.111.111/0001-11"
        };

        using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
        client.DefaultRequestHeaders.Add("Authorization", ApiKey);

        var content = new StringContent(
            JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");

        var response = await client.PostAsync(
            $"{BaseUrl}/onboarding/legal_person?analyze=true", content);

        var body = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            throw new InvalidOperationException(
                $"Onboarding retornou HTTP {(int)response.StatusCode}: {body}");
        }

        Console.WriteLine(body);
    }
}
```

**curl**

```bash
curl -X POST \
  'https://api.sandbox.caas.qitech.app/onboarding/legal_person?analyze=true' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: YOUR_API_KEY' \
  -d '{
    "id": "87654321",
    "registration_date": "2026-08-07T11:37:15-03:00",
    "document_number": "11.111.111/0001-11"
  }'
```

---

## Campos do objeto

### Obrigatórios

id
string
obrigatório
Identificador da análise. 1 a 50 caracteres. Único por requisição — repetido retorna HTTP 409.

registration_date
datetime
obrigatório
Data e hora do cadastro, com fuso horário. Mesmo formato de Natural Person.

document_number
string
obrigatório
CNPJ com pontuação , no formato XX.XXX.XXX/XXXX-XX . 18 caracteres.

### Dados da empresa

registration_id
string
opcional
Identificador do cadastro no seu sistema. Assume o valor de id quando omitido.

legal_name
string
opcional
Razão social.

trading_name
string
opcional
Nome fantasia.

foundation_date
date
opcional
Data de constituição no formato YYYY-MM-DD .

website
string
opcional
Site da empresa. Até 10.000 caracteres.

activity
string
opcional
Descrição da atividade econômica.

activity_code
string
opcional
CNAE no formato XX.XX-X-XX . Exatamente 10 caracteres.

merchant_category_code
enum
opcional
MCC de 4 dígitos conforme ISO 18245. Aceita apenas códigos da lista oficial.

tier
string
opcional
Porte da empresa. Até 10 caracteres. Ex.: mei , epp , me .

annual_revenues
integer
opcional
Faturamento anual em centavos .

monthly_revenues
integer
opcional
Faturamento mensal em centavos .

### Contato e localização

emails
array
opcional
Lista de objetos Email . Cada item exige email .

phones
array
opcional
Lista de objetos Phone . Cada item exige international_dial_code , area_code e number .

address
object
opcional
Objeto Address . Se enviado, exige postal_code .

documents
object
opcional
Documentos da empresa . Aceita apenas ie , company_statute e proof_of_address — veja o aviso abaixo, Dados do SDK e Objetos compartilhados .

source
object
opcional
Origem da requisição. É aqui na raiz que o session_id do Device Scan deve ser enviado — veja Dados do SDK .

### Quadro societário

legal_representatives
array
opcional
Lista de objetos LegalRepresentative . É dentro deste array que entram face e documentos de identidade (RG, CNH) — veja Dados do SDK .

partners
array
opcional
Lista de objetos Partner com os sócios da empresa.

final_beneficiaries
array
opcional
Lista de objetos FinalBeneficiary com os beneficiários finais.

### Classificação e extras

analysis_type
string
opcional
Tipo de análise, quando sua conta tem mais de um fluxo configurado.

client_category
string
opcional
Categoria do cliente na sua plataforma.

partnership_key
string
opcional
Identificador da parceria associada.

related_account_type
string
opcional
Tipo de conta relacionada.

custom_data
object
opcional
Campos personalizados. Requer schema previamente cadastrado pela QI Tech.

```json title="Payload completo"
{
  "id": "87654321",
  "registration_id": "cad-pj-1234",
  "registration_date": "2026-08-07T11:37:15-03:00",
  "client_category": "Premium Account",
  "legal_name": "Empresa Exemplo LTDA",
  "trading_name": "Barbearia do John",
  "document_number": "11.111.111/0001-11",
  "foundation_date": "1992-09-15",
  "website": "www.exemplo.com.br",
  "activity": "Barber Shops",
  "activity_code": "96.02-5-01",
  "merchant_category_code": "0742",
  "tier": "epp",
  "annual_revenues": 180000000,
  "monthly_revenues": 15000000,
  "emails": [{ "email": "contato@exemplo.com.br" }],
  "address": {
    "street": "Rua do Teste",
    "number": "111",
    "neighborhood": "Centro",
    "city": "São Paulo",
    "uf": "SP",
    "postal_code": "04570-140",
    "country": "BRA"
  },
  "phones": [
    {
      "international_dial_code": "55",
      "area_code": "11",
      "number": "999999999",
      "type": "commercial"
    }
  ],
  "source": {
    "channel": "web",
    "platform": "web",
    "ip": "255.201.26.1",
    "session_id": "54b8e3cf-15de-41e5-9305-0ecf059d6e2a"
  },
  "documents": {
    "company_statute": {
      "ocr_key": "d8fa2fb0-5199-47c3-daae-bd8ef03f4ea9"
    },
    "proof_of_address": {
      "document_analysis_id": "e9ab3ac1-62aa-48d4-ebbf-ce9fa14a5fb0"
    }
  },
  "legal_representatives": [
    {
      "id": "rep-001",
      "name": "Maria Sample",
      "document_number": "222.222.222-22",
      "birthdate": "1985-03-22",
      "mother_name": "Ana Sample",
      "pleaded_pep": false,
      "face": {
        "type": "zaig_sdk",
        "registration_key": "46f38cf4-07b2-4de6-93e9-64b51a68378a"
      },
      "documents": {
        "cnh": {
          "register_number": "05163811694",
          "issuer_state": "SP",
          "ocr_key": "c7ef1eaf-4088-46b2-c9fd-ac7de92e3d98"
        }
      }
    }
  ],
  "partners": [
    {
      "name": "Maria Sample",
      "document_number": "222.222.222-22"
    }
  ],
  "final_beneficiaries": [
    {
      "name": "Maria Sample",
      "document_number": "222.222.222-22"
    }
  ]
}
```

:::warning Campos não previstos são rejeitados
O schema usa `additionalProperties: false`. Qualquer campo fora dos listados retorna **HTTP 400**.
:::

:::danger RG e CNH não vão na raiz
Na raiz de Legal Person, `documents` aceita **apenas** `ie`, `company_statute` e `proof_of_address`. Documentos de identidade pertencem ao representante legal, dentro de `legal_representatives[].documents`. Enviá-los na raiz retorna **HTTP 400**.
:::

---

## Formatos de campo

### `document_number` — CNPJ

Formato `XX.XXX.XXX/XXXX-XX`, com pontuação, 18 caracteres. Apenas dígitos é rejeitado.

### `activity_code` — CNAE

Formato `XX.XX-X-XX`, exatamente 10 caracteres. Ex.: `96.02-5-01`.

### `registration_date`

Mesmo formato de Natural Person: ISO 8601 com fuso horário, offset terminado em `:00`/`:30` ou sufixo `Z`.

### Valores monetários

`annual_revenues` e `monthly_revenues` são inteiros em **centavos**. R$ 150.000,00 → `15000000`.

---

## Representantes, sócios e beneficiários

Os três arrays aceitam os mesmos campos de identificação de uma pessoa física (`name`, `document_number`, `birthdate`, `gender`, `nationality`, `mother_name`, `occupation`, `emails`, `phones`, `address`, `pleaded_pep`).

**Somente `legal_representatives[]` aceita `face` e `documents`** — é ali que entram as chaves de biometria e OCR do representante. Veja [Integrando os dados do SDK](/documentation/caas/onboarding/sdk_integration).

---

## Testando no Sandbox

A decisão é determinística, definida pelo **primeiro dígito do CNPJ**:

| Primeiro dígito | Resultado |
| --- | --- |
| `9` | `automatically_approved` |
| `8` | `automatically_reproved` |
| `7` | `pending` |
| `6` | Análise manual, com aprovação posterior |
| `5` | Análise manual, com reprovação posterior |
| `4` | `automatically_challenged` |
| `0` a `3` | `in_manual_analysis` |

:::danger Aviso importante
Não utilize dados reais de pessoas jurídicas no ambiente de Sandbox.
:::

---

## Erros

| Status | Situação | Como resolver |
| --- | --- | --- |
| 400 | Campo obrigatório ausente, formato inválido ou campo não previsto. | Veja a `description` da resposta. |
| 400 | `rg`/`cnh` na raiz de `documents`. | Mova para `legal_representatives[]`. |
| 400 | `custom_data` sem schema cadastrado. | Solicite o cadastro ao suporte. |
| 401 | Header `Authorization` ausente ou chave desativada. | Verifique a chave. |
| 403 | API Key inválida. | Confirme com o suporte. |
| 409 | `id` já utilizado. | Gere um `id` único. |
| 500 | Erro interno. | Notificação automática à nossa equipe. |

Lista completa em [Status HTTP](/documentation/caas/onboarding/http_status).

---

## Checklist de integração

- [ ] `POST /onboarding/legal_person` com o payload mínimo retornando `200` no Sandbox.
- [ ] CNPJ com pontuação e CNAE no formato `XX.XX-X-XX`.
- [ ] `source.session_id` preenchido **na raiz** (sem isso, o device não aparece na dashboard de PJ).
- [ ] `face` e documentos de identidade dentro de `legal_representatives[]`.
- [ ] Na raiz de `documents`, apenas `ie`, `company_statute`, `proof_of_address`.
- [ ] Valores monetários em centavos.
- [ ] [Webhook](/documentation/caas/onboarding/webhook) configurado para o resultado assíncrono.

---

# Objeto Natural Person

URL: /documentation/caas/onboarding/natural_person

Objeto Natural Person

Envia o cadastro de uma **pessoa física** para análise de fraude e KYC. A QI Tech executa a sua árvore de decisão contra os dados enviados e devolve em `analysis_status` o resultado que a **sua política** determinou — veja [Dinâmica dos status](/documentation/caas/onboarding/status_dynamics).

:::tip Comece pelo payload mínimo
São apenas **3 campos obrigatórios**. Vá direto para [Payload mínimo](#payload-minimo) e depois adicione o que fizer sentido para o seu caso.
:::

:::caution Envie dados finais
Os dados enviados devem ser os definitivos. CPF, nome e data de nascimento não devem mudar depois desta chamada — isso garante consistência da base antifraude e uma avaliação realista de risco.
:::

:::info Usa os SDKs de biometria, OCR ou Device Scan?
As chaves devolvidas pelos SDKs entram nos blocos `face`, `documents` e `source` deste payload. Onde cada uma vai — e o que muda em relação a Pessoa Jurídica — está em **[Dados do SDK (face, documentos e device)](/documentation/caas/onboarding/sdk_integration)**.
:::

---

## Payload mínimo

Este é o menor corpo aceito pelo `POST /onboarding/natural_person`.

```json title="Payload mínimo — 3 campos obrigatórios"
{
  "id": "12345678",
  "registration_date": "2026-08-07T11:37:15-03:00",
  "document_number": "111.111.111-11"
}
```

Resposta:

```json
{
  "id": "12345678",
  "analysis_status": "automatically_approved",
  "reason": "rule_decision_enum"
}
```

:::info Campos adicionais
Quanto mais dados forem enviados, mais validações são possíveis de se fazer no motor de regras.
:::

---

## Enviar um cadastro

ENDPOINT /onboarding/natural_person
MÉTODO POST

### Query parameters

analyze
boolean
opcional — padrão true
Com true , a sua árvore de decisão é executada e a resposta traz o resultado. Com false , o cadastro é apenas registrado (sem cobrança) e passa a compor o histórico usado em análises futuras — a resposta retorna not_analysed .

### Exemplos de requisição

**Python**

```python
import requests

BASE_URL = "https://api.sandbox.caas.qitech.app"
API_KEY = "YOUR_API_KEY"

payload = {
    "id": "12345678",
    "registration_date": "2026-08-07T11:37:15-03:00",
    "document_number": "111.111.111-11"
}

response = requests.post(
    f"{BASE_URL}/onboarding/natural_person",
    params={"analyze": "true"},
    json=payload,
    headers={"Authorization": API_KEY},
    timeout=30,
)

response.raise_for_status()
result = response.json()
print(result["analysis_status"])  # automatically_approved
```

**PHP**

```php
<?php

$baseUrl = 'https://api.sandbox.caas.qitech.app';
$apiKey  = 'YOUR_API_KEY';

$payload = [
    'id'                => '12345678',
    'registration_date' => '2026-08-07T11:37:15-03:00',
    'document_number'   => '111.111.111-11'
];

$ch = curl_init($baseUrl . '/onboarding/natural_person?analyze=true');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Authorization: ' . $apiKey
    ],
    CURLOPT_POSTFIELDS => json_encode($payload)
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 200) {
    throw new RuntimeException("Onboarding retornou HTTP {$status}: {$body}");
}

$result = json_decode($body, true);
echo $result['analysis_status'];
```

**Node.js**

```javascript
const BASE_URL = "https://api.sandbox.caas.qitech.app";
const API_KEY = "YOUR_API_KEY";

const payload = {
  id: "12345678",
  registration_date: "2026-08-07T11:37:15-03:00",
  document_number: "111.111.111-11"
};

async function createRegistration() {
  const response = await fetch(
    `${BASE_URL}/onboarding/natural_person?analyze=true`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: API_KEY
      },
      body: JSON.stringify(payload)
    },
  );

  if (!response.ok) {
    throw new Error(`Onboarding retornou HTTP ${response.status}`);
  }

  const result = await response.json();
  console.log(result.analysis_status);
  return result;
}

createRegistration();
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class CreateNaturalPerson {

    private static final String BASE_URL = "https://api.sandbox.caas.qitech.app";
    private static final String API_KEY = "YOUR_API_KEY";

    public static void main(String[] args) throws Exception {
        String payload = """
            {
              "id": "12345678",
              "registration_date": "2026-08-07T11:37:15-03:00",
              "document_number": "111.111.111-11"
            }
            """;

        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/onboarding/natural_person?analyze=true"))
                .header("Content-Type", "application/json")
                .header("Authorization", API_KEY)
                .timeout(Duration.ofSeconds(30))
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

        HttpResponse<String> response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new IllegalStateException(
                    "Onboarding retornou HTTP " + response.statusCode() + ": " + response.body());
        }

        System.out.println(response.body());
    }
}
```

**C#**

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class CreateNaturalPerson
{
    private const string BaseUrl = "https://api.sandbox.caas.qitech.app";
    private const string ApiKey = "YOUR_API_KEY";

    public static async Task Main()
    {
        var payload = new
        {
            id = "12345678",
            registration_date = "2026-08-07T11:37:15-03:00",
            document_number = "111.111.111-11"
        };

        using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
        client.DefaultRequestHeaders.Add("Authorization", ApiKey);

        var content = new StringContent(
            JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");

        var response = await client.PostAsync(
            $"{BaseUrl}/onboarding/natural_person?analyze=true", content);

        var body = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            throw new InvalidOperationException(
                $"Onboarding retornou HTTP {(int)response.StatusCode}: {body}");
        }

        Console.WriteLine(body);
    }
}
```

**curl**

```bash
curl -X POST \
  'https://api.sandbox.caas.qitech.app/onboarding/natural_person?analyze=true' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: YOUR_API_KEY' \
  -d '{
    "id": "12345678",
    "registration_date": "2026-08-07T11:37:15-03:00",
    "document_number": "111.111.111-11"
  }'
```

### Resposta

id
string
O mesmo id enviado na requisição.

analysis_status
enum
Resultado da execução da sua árvore de decisão. Veja Dinâmica dos status .

reason
string
Motivo da decisão, quando disponível.

```json
{
  "id": "12345678",
  "analysis_status": "automatically_approved",
  "reason": "rule_decision_enum"
}
```

:::info Resposta assíncrona
Quando a análise demora mais que o esperado, a resposta vem como `in_queue` ou `pending` e o resultado final chega por [Webhook](/documentation/caas/onboarding/webhook). Trate esses dois status como "aguardando" — não como recusa.
:::

---

## Campos do objeto

### Obrigatórios

id
string
obrigatório
Identificador da análise no seu sistema. 1 a 50 caracteres. Deve ser único por requisição — um id repetido retorna HTTP 409.

registration_date
datetime
obrigatório
Data e hora do cadastro, com fuso horário . Veja o formato aceito .

document_number
string
obrigatório
CPF com pontuação , no formato XXX.XXX.XXX-XX . Exatamente 14 caracteres.

### Identificação

registration_id
string
opcional
Identificador do cadastro no seu sistema. Use o mesmo valor em análises diferentes do mesmo cadastro para agrupá-las. Quando omitido, assume o valor de id .

name
string
opcional
Nome completo. 1 a 500 caracteres.

birthdate
date
opcional
Data de nascimento no formato YYYY-MM-DD .

gender
enum
opcional
male ou female .

nationality
string
opcional
País em ISO 3166-1 alpha-3, 3 letras maiúsculas. Ex.: BRA .

mother_name
string
opcional
Nome completo da mãe. 1 a 500 caracteres. Sinal relevante para validação em bureaus.

father_name
string
opcional
Nome completo do pai. 1 a 500 caracteres.

### Perfil financeiro

monthly_income
integer
opcional
Renda mensal bruta em centavos . R$ 5.000,00 → 500000 .

declared_assets
integer
opcional
Patrimônio declarado em centavos .

occupation
string
opcional
Profissão. 1 a 100 caracteres.

is_us_person
boolean
opcional
Indica se a pessoa tem obrigações fiscais nos EUA (relevante para FATCA).

pleaded_pep
boolean
opcional
Indica se a pessoa se declarou politicamente exposta (PEP).

### Contato e localização

emails
array
opcional
Lista de objetos Email . Dentro de cada item, apenas email é obrigatório.

phones
array
opcional
Lista de objetos Phone . Se enviado, cada item exige international_dial_code , area_code e number .

address
object
opcional
Objeto Address . Se enviado, apenas postal_code é obrigatório dentro dele.

documents
object
opcional
Documentos de identificação (RG, CNH, passaporte e outros). As chaves de OCR entram aqui — veja Dados do SDK e Objetos compartilhados .

face
object
opcional
Dados de validação facial. A chave devolvida pelo SDK de biometria entra aqui — veja Dados do SDK .

source
object
opcional
Origem da requisição (canal, plataforma, IP, sessão). É aqui que entra o session_id do Device Scan — veja Dados do SDK .

### Classificação e extras

analysis_type
string
opcional
Tipo de análise a aplicar, quando sua conta tem mais de um fluxo configurado. Combine com o suporte antes de usar.

client_category
string
opcional
Categoria do cliente na sua plataforma ou programa de fidelidade. 1 a 100 caracteres.

partnership_key
string
opcional
Identificador da parceria associada ao cadastro. 1 a 500 caracteres.

related_account_type
string
opcional
Tipo de conta relacionada ao cadastro. 1 a 50 caracteres.

vehicle_plate
string
opcional
Placa de veículo associada ao cadastro. 1 a 50 caracteres.

custom_data
object
opcional
Campos personalizados da sua conta. Requer um schema previamente cadastrado pela QI Tech — veja o aviso abaixo.

```json title="Payload completo"
{
  "id": "12345678",
  "registration_id": "cad-98765",
  "registration_date": "2026-08-07T11:37:15-03:00",
  "analysis_type": "default",
  "client_category": "Premium User",
  "name": "John Sample",
  "document_number": "111.111.111-11",
  "birthdate": "1992-09-15",
  "gender": "male",
  "nationality": "BRA",
  "mother_name": "Maria Sample",
  "father_name": "John Sample",
  "monthly_income": 500000,
  "declared_assets": 7500000,
  "occupation": "Teacher",
  "is_us_person": false,
  "pleaded_pep": false,
  "emails": [
    {
      "email": "johnsample@test.com"
    }
  ],
  "documents": {
    "rg": {
      "number": "4.366.477-8",
      "issuer": "II",
      "issuer_state": "PR",
      "issuance_date": "2002-01-12"
    },
    "cnh": {
      "register_number": "05163811694",
      "issuer_state": "PR",
      "first_issuance_date": "2011-03-21",
      "issuance_date": "2016-06-29",
      "expiration_date": "2031-06-25",
      "category": "AB"
    }
  },
  "address": {
    "street": "Rua do Teste",
    "number": "111",
    "neighborhood": "Bairro do Exemplo",
    "city": "Aparecida de Goiânia",
    "uf": "GO",
    "complement": "Térreo",
    "postal_code": "00000-000",
    "country": "BRA"
  },
  "phones": [
    {
      "international_dial_code": "55",
      "area_code": "11",
      "number": "999999999",
      "type": "mobile"
    }
  ],
  "source": {
    "channel": "app",
    "platform": "android",
    "ip": "255.201.26.1",
    "session_id": "54b8e3cf-15de-41e5-9305-0ecf059d6e2a",
    "os_version": "14"
  },
  "face": {
    "type": "zaig_sdk",
    "registration_key": "46f38cf4-07b2-4de6-93e9-64b51a68378a"
  }
}
```

:::warning Campos não previstos são rejeitados
O schema usa `additionalProperties: false`. Qualquer campo fora dos listados acima faz a requisição retornar **HTTP 400**, mesmo que o resto do payload esteja correto.
:::

:::caution `custom_data` exige schema próprio
`custom_data` é validado contra um schema específico da sua empresa, registrado pela QI Tech. Se você enviar esse campo sem ter o schema cadastrado, a resposta é **HTTP 400** com a mensagem *"Custom data not available for you account"*. Fale com o [suporte](mailto:suporte.caas@qitech.com.br) antes de usar.
:::

---

## Formatos de campo

### Formato de `registration_date`

Formato ISO 8601 **com fuso horário obrigatório**. O validador aceita offsets terminados em `:00` ou `:30`, ou o sufixo `Z`:

```text
2026-08-07T11:37:15-03:00          ✅
2026-08-07T11:37:15.123456-03:00   ✅  fração de 1 a 6 dígitos
2026-08-07T14:37:15Z               ✅  UTC
2026-08-07T11:37:15                ❌  sem fuso horário
2026-08-07T11:37:15-03:15          ❌  offset não permitido
```

### `document_number` — CPF

Deve ir **com pontuação**: `XXX.XXX.XXX-XX`, exatamente 14 caracteres. Enviar apenas dígitos (`11111111111`) retorna HTTP 400.

### `postal_code` — CEP

Dentro de `address`, o CEP exige o formato `XXXXX-XXX` (com hífen). `00000000` é rejeitado.

### Valores monetários

`monthly_income` e `declared_assets` são inteiros em **centavos de reais**. Multiplique por 100: R$ 5.000,00 → `500000`.

---

## Enumeradores

### `gender`

| Valor | Significado |
| --- | --- |
| `male` | Masculino |
| `female` | Feminino |

### `phones[].type`

| Valor | Significado |
| --- | --- |
| `mobile` | Celular |
| `residential` | Residencial |
| `commercial` | Comercial |

| `visit` | Confirmado por visita presencial |
| `zaig_sdk` | Confirmado pelo SDK da QI Tech |
| `zaig_ocr` | Confirmado por OCR de comprovante |

### `face.type`

| Valor | Significado |
| --- | --- |
| `zaig_sdk` | Captura via SDK da QI Tech (use `registration_key`) |
| `base_64` | Imagem enviada diretamente no campo `image` |

Para `analysis_status`, `client_status` e `risk_level`, veja [Dinâmica dos status](/documentation/caas/onboarding/status_dynamics).

---

## Testando no Sandbox

No Sandbox a decisão é determinística, definida pelo **primeiro dígito do CPF**:

| Primeiro dígito | Resultado |
| --- | --- |
| `9` | `automatically_approved` |
| `8` | `automatically_reproved` |
| `7` | `pending` |
| `6` | Análise manual, com aprovação posterior |
| `5` | Análise manual, com reprovação posterior |
| `4` | `automatically_challenged` |
| `0` a `3` | `in_manual_analysis` |

:::danger Aviso importante
Não utilize dados reais de pessoas físicas no ambiente de Sandbox.
:::

---

## Erros

| Status | Situação | Como resolver |
| --- | --- | --- |
| 400 | Campo obrigatório ausente, formato inválido, enum fora da lista ou campo não previsto. | Veja a `description` da resposta, que aponta o campo. |
| 400 | `custom_data` sem schema cadastrado. | Solicite o cadastro do schema ao suporte. |
| 401 | Header `Authorization` ausente ou API Key desativada. | Verifique a chave. |
| 403 | API Key inválida. | Confirme a chave com o suporte. |
| 409 | `id` já utilizado. | Gere um `id` único por requisição. |
| 500 | Erro interno. | Nossos especialistas são notificados automaticamente. |

Lista completa em [Status HTTP](/documentation/caas/onboarding/http_status).

---

## Checklist de integração

- [ ] `POST /onboarding/natural_person` com o payload mínimo retornando `200` no Sandbox.
- [ ] `id` único por requisição (teste o `409` reenviando o mesmo `id`).
- [ ] `registration_id` estável para agrupar análises do mesmo cadastro.
- [ ] CPF com pontuação e CEP com hífen.
- [ ] Valores monetários em centavos.
- [ ] `in_queue` e `pending` tratados como "aguardando", não como recusa.
- [ ] [Webhook](/documentation/caas/onboarding/webhook) configurado para receber o resultado assíncrono.

---

# Objetos Compartilhados

URL: /documentation/caas/onboarding/objects

Boa parte dos dados são compartilhados entre várias APIs. Abaixo as definições destes objetos podem ser localizadas de maneira facilitada.

## Objeto *email*

Request Body

```json
{
  "email": "johnsample@test.com"
}
```

O objeto *email* é utilizado para representar os e-mails em toda a API bem como se foi utilizado algum meio de validação dos mesmos. Eles são representados da seguinte maneira:

nome | tipo | restrições | descrição
---- | :----: | :----: | ---------
email | string | 1–100 caracteres | Endereço de e-mail cadastrado. *(obrigatório)*

## Objeto *cnh*

Request Body

```json
{
  "register_number": "05163811694",
  "issuer_state": "PR",
  "first_issuance_date":"2011-03-21",
  "issuance_date":"2016-06-29",
  "expiration_date":"2021-06-25",
  "category": "AB",
  "ocr_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76"
}
```

O objeto *cnh* é utilizado para representar as CNHs em toda a API bem como se foi utilizado algum meio de validação dos mesmos. Eles são representados da seguinte maneira:

nome | tipo | descrição
---- | :----: | ---------
register_number | string | Número do registro da CNH cadastrada.
issuer_state | enum | Enumerador do estado onde a CNH foi emitida
first_issuance_date | date | Data de primeira habilitação.
issuance_date | date | Data de emissão
expiration_date | date | Data de vencimento
category | enum | Categoria da CNH em letras maiúsculas
ocr_key | guid | Id retornado pela API de validação de documento da QI Tech.

## Objeto *rg*

Request Body

```json
{
  "number": "4.366.477-8",
  "issuer": "II",
  "issuer_state": "PR",
  "issuance_date":"2002-01-12",
  "ocr_front_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76",
  "ocr_back_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76"
}
```

O objeto *rg* é utilizado para representar os RGs em toda a API bem como se foi utilizado algum meio de validação dos mesmos. Eles são representados da seguinte maneira:

nome | tipo | descrição
---- | :----: | ---------
number | string | Número do documento cadastrado, incluindo formatação (Pontos, Hífens, Barras e outros).
issuer | string | Órgão emissor do documento (Sigla, e.g.: II, SESP...)
issuer_state | enum | UF emissor do documento.
issuance_date | date | Data de emissão do documento.
ocr_key | guid | Id retornado pela API de validação de documento da QI Tech.

## Objeto *ie*

Request Body

```json
{
  "number": "388.108.598.269",
  "issuer": "JUCESP",
  "issuer_state": "SP",
  "issuance_date":"2002-01-12",
  "ocr_key": "c64627db-1ba4-48b6-979d-06222a25d5e9"
}
```

O objeto *ie* é utilizado para representar as Inscrições Estaduais dentro do objeto de *documents* no endpoint de *legal_person*, bem como se foi utilizado algum meio de validação do mesmo. Ele é representado da seguinte maneira:

nome | tipo | descrição
---- | :----: | ---------
number | string | Número do documento cadastrado, incluindo formatação (Pontos, Hífens, Barras e outros).
issuer | string | Órgão emissor do documento (Sigla, e.g.: JUCESP, JUCEGO...)
issuer_state | enum | UF emissor do documento.
issuance_date | date | Data de emissão do documento.
ocr_key | guid | Id retornado pela API de validação de documento da QI Tech.

## Objeto *company_statute*

Request Body

```json
{
  "ocr_key": "60ed79c4-5aba-4cc7-aebb-5de5f92b7d0d"
}
```

O objeto *company_statute* é utilizado para representar documentos de constituição de empresas, como por exemplo um Contrato Social dentro do objeto de *documents* no endpoint de *legal_person*. Ele é representado da seguinte maneira:

nome | tipo | descrição
---- | :----: | ---------
ocr_key | guid | Id retornado pela API de OCR da QI Tech após envio da imagem ou PDF de um documento de constuição de uma empresa.

## Objeto *letter_attorney*

Request Body

```json
{
  "ocr_key": "13571175-b1d9-4507-82e0-d266516fc5ae"
}
```

O objeto *letter_attorney* é utilizado para representar procurações que instituem poderes a representantes legais dentro do objeto de *documents* no endpoint de *legal_person*. Ele é representado da seguinte maneira:

nome | tipo | descrição
---- | :----: | ---------
ocr_key | guid | Id retornado pela API de OCR da QI Tech após envio da imagem ou PDF de uma procuração.
## Objeto *address*

Request Body

```json
{
  "street": "Rua do Teste",
  "number": "111",
  "neighborhood": "Bairro do Exemplo",
  "city": "Aparecida de Goiânia",
  "uf": "GO",
  "complement": "Térreo",
  "postal_code": "00000-000",
  "country": "BRA",
  "ocr_key": "265b1b74-4b93-41dc-ac78-e1c37467225d"
}
```

O objeto *address* é utilizado para representar endereços em toda a API, endereços no território brasileiro são representados da seguinte maneira:

nome | tipo | restrições | descrição
---- | :----: | :----: | ---------
street | string | 1–100 caracteres | Rua do endereço, incluindo o logradouro, evitando, se possível, abreviações.
number | string | 1–50 caracteres | Número do imóvel, incluindo letras caso possua.
neighborhood | string | 1–100 caracteres | Bairro, sem abreviações. **e.g.: Santa Felicidade**
city | string | 1–100 caracteres | Nome completo da cidade, sem abreviações
uf | enum | sigla UF (2 letras) | A unidade federativa brasileira. Aceita as 27 UFs mais `EX` (exterior), em maiúsculas ou minúsculas. **e.g.: SP, GO, MG, EX**
complement | string | 1–500 caracteres | Quaisquer complementos para localizar o imóvel. **e.g.: Apartamento 101, Conjunto 12**
postal_code | string | Formato `XXXXX-XXX` | CEP brasileiro com hífen, exatamente 9 caracteres. Exemplo: `01310-100` *(obrigatório)*
country | string | 3 letras maiúsculas | Código ISO 3166-1 alfa-3 do país do endereço. Exemplo: `BRA`
ocr_key | guid | UUID (`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) | Id retornado pela API ou SDK de OCR da QI Tech após o envio da imagem do comprovante de residência.

No caso dos endereços cujo país não seja Brasil (`BRA`), o `postal_code` e a unidade federativa poderão ser preenchidos livremente.

## Objeto *phone*

Request Body

```json
{
  "international_dial_code": "1",
  "area_code": "11",
  "number": "999999999",
  "type": "mobile"
}
```

Um objeto *phone* representa um número telefônico, dentro ou fora do Brasil e sua classificação. Para isso, os campos são:

nome | tipo | restrições | descrição
---- | :----: | :----: | ---------
international_dial_code | string | 1–7 caracteres, somente dígitos | Código de discagem internacional, sem zero ou `+`. Exemplo: `55` para Brasil *(obrigatório)*
area_code | string | 1–10 caracteres, somente dígitos | Código de área, sem zero. Exemplo: `11` *(obrigatório)*
number | string | 1–20 caracteres | Número do telefone, sem o hífen *(obrigatório)*
type | enum | `residential`, `commercial` ou `mobile` | Tipo de número telefônico.

## Objeto *source*

Request Body

```json
  {
    "channel": "app",
    "platform": "android",
    "ip":"211.7.142.62",
    "session_id": "733adf2c-a994-4113-aa59-beb646091fea"
  }
```

Um objeto *source* representa o conjunto de informações da plataforma utilizada pelo cliente para seu cadastramento. Para isso, os campos são:

nome | tipo | descrição
---- | :----: | ---------
channel | string | Canal de venda/cadastro do cliente
platform | string | Plataforma utilizada pelo cliente para realizar seu cadastro
ip | string | IP coletado do device que o cliente foi cadastrado
session_id | string | Identificador único da sessão, utilizado para fazer o cruzamento do device scan com o cadastro em questão

## Objeto *face*

Request Body

```json
  {
    "type":"zaig_face_sdk",
    "registration_key":"46f38cf4-07b2-4de6-93e9-64b51a68378a"
  }
```

Um objeto *face* representa uma validação de reconhecimento facial feita através das APIs ou SDKs da QI Tech por você para verificar a autenticidade do cliente prévio ao envio do cadastro. Para isso, os campos são:

nome | tipo | descrição
---- | :----: | ---------
registration_key | guid | Identificador que a API ou SDK da QI Tech retornou para identificar aquele registro.

## Objeto *partner*

Request Body

```json
  {
    "name": "John Partner",
    "document_number": "111.111.111-11",
    "birthdate": "1992-09-15",
    "gender": "male",
    "nationality": "BRA",
    "mother_name": "Maria Partner's Mother",
    "occupation": "Teacher",
    "emails":[
      {
        "email": "johnsample@test.com"
      }
    ],
    "documents": {
      "rg": {
        "number": "4.366.477-8",
        "issuer": "II",
        "issuer_state": "PR",
        "issuance_date":"2002-01-12",
        "ocr_front_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76",
        "ocr_back_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76"
      },
      "cnh": {
        "register_number": "05163811694",
        "issuer_state": "PR",
        "first_issuance_date":"2011-03-21",
        "issuance_date":"2016-06-29",
        "expiration_date":"2021-06-25",
        "category": "AB",
        "ocr_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76"
      }
    },
    "address": {
      "street": "Rua do Teste",
      "number": "111",
      "neighborhood": "Bairro do Exemplo",
      "city": "Aparecida de Goiânia",
      "uf": "GO",
      "complement": "Térreo",
      "postal_code": "00000-000",
      "country": "BRA"
    },
    "phones": [
      {
        "international_dial_code": "1",
        "area_code": "11",
        "number": "999999999",
        "type": "mobile"
      }
    ],
    "source": {
      "channel": "app",
      "platform": "android",
      "ip":"255.321.321.1",
      "session_id": "54b8e3cf-15de-41e5-9305-0ecf059d6e2a"
    },
    "face":
    {
      "type":"zaig_sdk",
      "registration_key":"46f38cf4-07b2-4de6-93e9-64b51a68378a"
    }
  }
```

Um objeto *partner* representa os dados de um sócio da empresa que está sendo cadastrada, bem como informações referentes às validações que o sócio foi submetido durante seu processo de cadastro. Para isso, os campos são:

nome | tipo | descrição
:----: | :----: | ---------
name | string | Nome completo do sócio sendo cadastrado
document_number | string | CPF do sócio sendo cadastrado, com pontos e hífens, de acordo com a padronização *(obrigatório)*
birthdate | date | Data de nascimento do sócio de acordo com a padronização
gender | enum | Gênero do sócio: 'male' ou 'female'
nationality | string | A nacionalidade do sócio, em ISO 3166-1 alfa-3
mother_name | string | Nome completo da mãe do sócio
occupation | string | Profissão do sócio sendo cadastrado
emails | Email | Lista de objetos do tipo Email que descreve o endereço de e-mail do sócio
documents | Document | Objeto do tipo Document de quaisquer documentos enviados no momento do cadastro do sócio
address | Address | Objeto do tipo Address que descreve o endereço da moradia do sócio
phones | Lista de Phone | Lista de objetos do tipo phone que possui a lista de telefones do sócio
source | Source | Objeto do tipo Source que descreve as características da aplicação utilizada para envio do cadastro
face | Face | Objeto do tipo Face que descreve as informações da validação facial 

## Objeto *legal_representative*

Request Body

```json
  {
    "name": "Frederic Attorney",
    "document_number": "111.111.111-11",
    "birthdate": "1987-06-12",
    "gender": "male",
    "nationality": "BRA",
    "mother_name": "Jackie Attorney Mother",
    "occupation": "Accountant",
    "emails":[
      {
        "email": "frederic@attorney.com"
      }
    ],
    "documents": {
      "letter_of_attorney": {
        "ocr_key": "6972894d-d2ef-4b5f-b54f-10f178bf3e5d"
      },
      "cnh": {
        "register_number": "05163811694",
        "issuer_state": "PR",
        "first_issuance_date":"2011-03-21",
        "issuance_date":"2016-06-29",
        "expiration_date":"2021-06-25",
        "category": "AB",
        "ocr_key":"a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76"
      }
    },
    "address": {
      "street": "Avenida de Exemplo",
      "number": "99",
      "neighborhood": "Vila do Exemplo",
      "city": "Jundiaí",
      "uf": "SP",
      "complement": "Ap 82",
      "postal_code": "00000-000",
      "country": "BRA",
      "ocr_key": "265b1b74-4b93-41dc-ac78-e1c37467225d"
    },
    "phones": [
      {
        "international_dial_code": "55",
        "area_code": "11",
        "number": "999998877",
        "type": "mobile"
      }
    ],
    "source": {
      "channel": "app",
      "platform": "ios",
      "ip":"175.92.122.2",
      "session_id": "93c68588-7a41-472f-95b3-835ea6ee1ede"
    },
    "face":
    {
      "type":"zaig_sdk",
      "registration_key":"d2677a8c-d575-44e1-a54d-ec00f9310f34"
    }
  }
```

Um objeto *legal_representative* representa os dados de um representante legal da empresa que está sendo cadastrada, bem como informações referentes às validações que o representante legal foi submetido durante seu processo de cadastro. Para isso, os campos são:

nome | tipo | descrição
:----: | :----: | ---------
name | string | Nome completo do representante legal sendo cadastrado
document_number | string | CPF do representante legal sendo cadastrado, com pontos e hífens, de acordo com a padronização
birthdate | date | Data de nascimento do representante legal de acordo com a padronização
gender | enum | Gênero do representante legal: 'male' ou 'female'
nationality | string | A nacionalidade do representante legal, em ISO 3166-1 alfa-3
mother_name | string | Nome completo da mãe do representante legal
occupation | string | Profissão do representante legal sendo cadastrado
emails | Email | Lista de objetos do tipo Email que descreve o endereço de e-mail do representante legal
documents | Document | Objeto do tipo Document de quaisquer documentos enviados no momento do cadastro do representante legal
address | Address | Objeto do tipo Address que descreve o endereço da moradia do representante legal
phones | Lista de Phone | Lista de objetos do tipo phone que possui a lista de telefones do representante legal
source | Source | Objeto do tipo Source que descreve as características da aplicação utilizada para envio do cadastro
face | Face | Objeto do tipo Face que descreve as informações da validação facial 
## Objeto *final_beneficiary*

Request Body

```json
  {
    "id": "benef-001",
    "name": "Maria Sample",
    "document_number": "222.222.222-22",
    "declared_income": 1200000,
    "address": {
      "street": "Rua do Teste",
      "number": "111",
      "city": "São Paulo",
      "uf": "SP",
      "postal_code": "04570-140",
      "country": "BRA"
    }
  }
```

Um objeto *final_beneficiary* representa um beneficiário final da empresa que está sendo cadastrada. Todos os campos são opcionais. Para isso, os campos são:

nome | tipo | descrição
:----: | :----: | ---------
id | string | Identificador do beneficiário final no seu sistema
name | string | Nome completo do beneficiário final
document_number | string | CPF do beneficiário final, com pontos e hífen, de acordo com a padronização
declared_income | inteiro | Renda declarada do beneficiário final, em centavos
address | Address | Objeto do tipo Address que descreve o endereço do beneficiário final

---

# Recuperar um Cadastro

URL: /documentation/caas/onboarding/query_registration

## Buscar Cadastro específico

A fim de recuperar um Cadastro específico, basta realizar uma requisição GET. O resultado retornado é o json mais atualizado do Cadastro em questão. Caso este identificador não esteja relacionado a nenhum objeto, o HTTP Status 404 é retornado.

* **Natural Person:**

`GET https://api.caas.qitech.app/onboarding/natural_person/12345678`

* **Legal Person:**

`GET https://api.caas.qitech.app/onboarding/legal_person/12345678`

```shell
curl "https://api.caas.qitech.app/onboarding/natural_person/12345678"
  -H "Authorization: EXAMPLE-OF-API-KEY"
```

> O comando acima retorna o JSON que representa um objeto de Natural Person.

```shell
curl "https://api.caas.qitech.app/onboarding/legal_person/12345678"
  -H "Authorization: EXAMPLE-OF-API-KEY"
```

> O comando acima retorna o JSON que representa um objeto de Legal Person.

## Buscar PDF

A fim de recuperar um PDF de um cadastro, basta realizar uma requisição GET. O resultado retornado é o arquivo PDF resultante da análise. Caso seja desejado, basta adicionar uma query string denominada base64 com o valor true para que o arquivo PDF seja retornado em base64.

:::info **Atenção**

A geração de PDF pela plataforma é assíncrona e toma alguns segundos, caso o GET seja realizado antes da geração efetiva do PDF, um erro 404 será retornado com uma descrição que aponta esta situação. Basta retentar após alguns segundos e o PDF será retornado.
:::

* **Natural Person:**

`GET https://api.caas.qitech.app/onboarding/natural_person/12345678/pdf`

`GET https://api.caas.qitech.app/onboarding/natural_person/12345678/pdf?base64=true`

* **Legal Person:**

`GET https://api.caas.qitech.app/onboarding/legal_person/12345678/pdf`

`GET https://api.caas.qitech.app/onboarding/legal_person/12345678/pdf?base64=true`

```shell
curl "https://api.caas.qitech.app/onboarding/natural_person/12345678/pdf"
  -H "Authorization: EXAMPLE-OF-API-KEY"
```

> O comando acima retorna o arquivo PDF gerado pela consulta.

```shell
curl "https://api.caas.qitech.app/onboarding/legal_person/12345678/pdf"
  -H "Authorization: EXAMPLE-OF-API-KEY"
```

> O comando acima retorna o arquivo PDF gerado pela consulta.

---

# Integrando os dados do SDK (face, documentos e device)

URL: /documentation/caas/onboarding/sdk_integration

Integrando os dados do SDK

Os SDKs da QI Tech (biometria facial, OCR de documentos e Device Scan) não enviam dados direto para a análise cadastral. Cada um devolve uma **chave** para o seu backend, e é você que anexa essas chaves ao payload de onboarding.

Esta página trata de onde cada chave entra — que é diferente entre Pessoa Física e Pessoa Jurídica.

| Bloco | O que carrega | Origem da chave |
| --- | --- | --- |
| `face` | Biometria facial | SDK de biometria |
| `documents` | OCR de documentos | SDK/API de OCR |
| `source` | Dados de dispositivo e sessão | SDK de Device Scan |

:::danger A diferença que mais causa retrabalho
Em **Pessoa Física**, os três blocos ficam na **raiz** do payload.

Em **Pessoa Jurídica**, `face` e `documents` de identidade ficam **dentro de `legal_representatives[]`** — mas o `source` continua na **raiz**. Detalhes em [Pessoa Jurídica](#pessoa-juridica-legal-person).
:::

---

## Onde cada bloco entra

| Bloco | Pessoa Física | Pessoa Jurídica |
| --- | --- | --- |
| `source` (`session_id`) | Raiz | **Raiz** — obrigatório para aparecer na dashboard |
| `face` | Raiz | Dentro de `legal_representatives[]` |
| `documents` (RG, CNH, passaporte) | Raiz | Dentro de `legal_representatives[]` |
| `documents` (`ie`, `company_statute`, `proof_of_address`) | — | Raiz |

---

## `source` — Device Scan e `session_id`

O `session_id` é a chave devolvida pelo SDK de Device Scan. É ele que conecta a análise cadastral aos dados de dispositivo, geolocalização e comportamento coletados no app ou no site.

session_id
string
opcional — mas veja o aviso
Identificador da sessão gerado pelo SDK de Device Scan. 1 a 500 caracteres.

channel
string
opcional
Canal de origem do cadastro. Ex.: app , web , backoffice . 1 a 100 caracteres.

platform
string
opcional
Plataforma. Ex.: android , ios , web . 1 a 100 caracteres.

ip
string
opcional
IP de origem. Aceita IPv4 e IPv6 . Um valor mal formatado retorna HTTP 400.

os_version
string
opcional
Versão do sistema operacional. 1 a 100 caracteres.

gps_data
object
opcional
Coordenadas da captura.

**Campos de `gps_data`:**

lat
number
opcional
Latitude, entre -90 e 90 .

lon
number
opcional
Longitude, entre -180 e 180 .

```json title="source — sempre na raiz, PF e PJ"
{
  "source": {
    "channel": "app",
    "platform": "android",
    "ip": "255.201.26.1",
    "session_id": "54b8e3cf-15de-41e5-9305-0ecf059d6e2a",
    "os_version": "14",
    "gps_data": {
      "lat": -23.5613,
      "lon": -46.6565
    }
  }
}
```

:::danger Pessoa Jurídica: `session_id` precisa estar na raiz
Em **Legal Person**, o `source.session_id` deve estar no **objeto `source` da raiz** do payload — não dentro de `legal_representatives[]`.

**Se esse campo não estiver preenchido na raiz, os dados de device não aparecem na dashboard de análise cadastral de PJ.** O schema aceita `source` dentro de `legal_representatives[]`, mas não é de lá que a dashboard de PJ lê a sessão — colocar apenas ali faz o dado ser silenciosamente ignorado na análise.
:::

---

## `face` — biometria facial

type
enum
opcional
Como a biometria foi capturada. Define qual dos campos abaixo você deve preencher.

registration_key
string
opcional
Chave devolvida pelo SDK de biometria. Use com type: "zaig_sdk" . Formato UUID.

image
string
opcional
Imagem em Base64. Use com type: "base_64" quando não houver SDK envolvido.

### Valores de `type`

| Valor | Campo a preencher |
| --- | --- |
| `zaig_sdk` | `registration_key` |
| `base_64` | `image` |

```json title="face via SDK"
{
  "face": {
    "type": "zaig_sdk",
    "registration_key": "46f38cf4-07b2-4de6-93e9-64b51a68378a"
  }
}
```

```json title="face via Base64"
{
  "face": {
    "type": "base_64",
    "image": "iVBORw0KGgoAAAANSUhEUg..."
  }
}
```

---

## `documents` — OCR

As chaves de OCR (`ocr_key`, `ocr_front_key`, `ocr_back_key`) vêm do SDK/API de OCR e entram dentro do documento correspondente.

### Documentos aceitos em Pessoa Física

Na raiz do payload de Natural Person, `documents` aceita:

| Campo | O que é | Chaves aceitas |
| --- | --- | --- |
| `rg` | Registro Geral | `ocr_front_key`, `ocr_back_key`, `ocr_key` |
| `cnh` | Carteira Nacional de Habilitação | `ocr_key`, `ocr_front_key`, `ocr_back_key` |
| `passport` | Passaporte | `ocr_key` *(obrigatório)* |
| `ctps` | Carteira de Trabalho | `ocr_front_key` e `ocr_back_key` *(ambos obrigatórios)* |
| `cin_digital` | Carteira de Identidade Nacional digital | `ocr_key` |
| `national_registry_of_foreigners` | RNE — Registro Nacional de Estrangeiros | `ocr_key`, `ocr_front_key`, `ocr_back_key` |
| `national_migration_registry` | RNM — Registro Nacional Migratório | `ocr_key`, `ocr_front_key`, `ocr_back_key` |
| `class_entity_registry` | Carteira de entidade de classe (OAB, CRM…) | `ocr_key` *(obrigatório)* |
| `military_registry` | Documento militar | `ocr_key` *(obrigatório)* |
| `letter_of_emancipation` | Carta de emancipação | `ocr_key` *(obrigatório)* |
| `company_statute` | Contrato social / estatuto | `ocr_key`, `document_analysis_id` |
| `proof_of_address` | Comprovante de endereço | `document_analysis_id` |
| `others` | Outros documentos | `ocr_front_key` e `ocr_back_key` *(ambos obrigatórios)* |

### Documentos aceitos em Pessoa Jurídica

Na **raiz** do payload de Legal Person, `documents` aceita **apenas** documentos da empresa:

| Campo | O que é | Chaves aceitas |
| --- | --- | --- |
| `ie` | Inscrição estadual | `ocr_key` — exige o campo `number` |
| `company_statute` | Contrato social / estatuto | `ocr_key`, `document_analysis_id` |
| `proof_of_address` | Comprovante de endereço | `document_analysis_id` |

:::danger RG e CNH não existem na raiz de Legal Person
Documentos de identidade (`rg`, `cnh`, `passport`…) **não são aceitos** na raiz do payload de PJ — o schema usa `additionalProperties: false` e a requisição retorna **HTTP 400**.

Eles pertencem ao representante legal, dentro de `legal_representatives[]`.
:::

### Chaves de OCR por documento

As chaves aceitas por documento estão nas tabelas acima. Vale destacar:

- **Frente e verso:** em documentos com dois lados (`rg`, `ctps`, `others`), o padrão é enviar `ocr_front_key` e `ocr_back_key`. Em `ctps` e `others` os dois são **obrigatórios**.
- **Chave única:** quando o OCR devolve uma única chave para o documento inteiro, use `ocr_key`.
- **`document_analysis_id`:** usado em `company_statute` e `proof_of_address`, que passam pela [Análise de Documentos](/documentation/caas/document_analysis/introduction) e não por OCR de identidade.

Em `rg` e `cnh`, o campo `issuer_state` aceita as siglas de UF em maiúsculas ou minúsculas.

```json title="documents com chaves de OCR (PF)"
{
  "documents": {
    "rg": {
      "number": "4.366.477-8",
      "issuer": "SSP",
      "issuer_state": "PR",
      "issuance_date": "2002-01-12",
      "ocr_front_key": "a5cf9c8f-2f66-4490-a7db-8a5bc70c1b76",
      "ocr_back_key": "b6df0d9e-3f77-45a1-b8ec-9b6cd81d2c87"
    },
    "cnh": {
      "register_number": "05163811694",
      "issuer_state": "PR",
      "first_issuance_date": "2011-03-21",
      "issuance_date": "2016-06-29",
      "expiration_date": "2031-06-25",
      "category": "AB",
      "ocr_key": "c7ef1eaf-4088-46b2-c9fd-ac7de92e3d98"
    }
  }
}
```

---

## Pessoa Física (Natural Person)

Os três blocos ficam na raiz:

```json title="POST /onboarding/natural_person"
{
  "id": "12345678",
  "registration_date": "2026-08-07T11:37:15-03:00",
  "document_number": "111.111.111-11",
  "name": "John Sample",

  "source": {
    "channel": "app",
    "platform": "android",
    "ip": "255.201.26.1",
    "session_id": "54b8e3cf-15de-41e5-9305-0ecf059d6e2a"
  },

  "face": {
    "type": "zaig_sdk",
    "registration_key": "46f38cf4-07b2-4de6-93e9-64b51a68378a"
  },

  "documents": {
    "cnh": {
      "register_number": "05163811694",
      "issuer_state": "PR",
      "ocr_key": "c7ef1eaf-4088-46b2-c9fd-ac7de92e3d98"
    }
  }
}
```

---

## Pessoa Jurídica (Legal Person)

`source` na raiz; `face` e documentos de identidade dentro de `legal_representatives[]`:

```json title="POST /onboarding/legal_person"
{
  "id": "87654321",
  "registration_date": "2026-08-07T11:37:15-03:00",
  "document_number": "11.111.111/1111-11",
  "legal_name": "Empresa Exemplo LTDA",

  "source": {
    "channel": "web",
    "platform": "web",
    "ip": "255.201.26.1",
    "session_id": "54b8e3cf-15de-41e5-9305-0ecf059d6e2a"
  },

  "documents": {
    "company_statute": {
      "ocr_key": "d8fa2fb0-5199-47c3-daae-bd8ef03f4ea9"
    },
    "proof_of_address": {
      "document_analysis_id": "e9ab3ac1-62aa-48d4-ebbf-ce9fa14a5fb0"
    }
  },

  "legal_representatives": [
    {
      "id": "rep-001",
      "name": "Maria Sample",
      "document_number": "222.222.222-22",
      "birthdate": "1985-03-22",

      "face": {
        "type": "zaig_sdk",
        "registration_key": "46f38cf4-07b2-4de6-93e9-64b51a68378a"
      },

      "documents": {
        "cnh": {
          "register_number": "05163811694",
          "issuer_state": "SP",
          "ocr_key": "c7ef1eaf-4088-46b2-c9fd-ac7de92e3d98"
        }
      }
    }
  ]
}
```

:::tip Por que a biometria fica no representante
A biometria e o documento de identidade pertencem a uma **pessoa**, não à empresa. Em PJ, quem passa pela validação biométrica é o representante legal — por isso `face` e `documents` de identidade vivem dentro de `legal_representatives[]`.

Já os dados de device pertencem à **sessão** em que o cadastro foi feito, que é única para toda a requisição — por isso `source` fica na raiz.
:::

---

## Erros comuns

| Sintoma | Causa | Correção |
| --- | --- | --- |
| Dados de device não aparecem na dashboard de PJ | `session_id` ausente na raiz, ou enviado apenas dentro de `legal_representatives[]` | Preencha `source.session_id` na **raiz** do payload |
| HTTP 400 ao enviar `rg`/`cnh` em PJ | Documento de identidade na raiz do Legal Person | Mova para `legal_representatives[].documents` |
| HTTP 400 no `passport` | Objeto enviado sem `ocr_key` | `ocr_key` é obrigatório em `passport` |
| HTTP 400 em `source.ip` | IP mal formatado | Envie IPv4 ou IPv6 válido |
| HTTP 400 sem campo aparente | Campo fora do schema (`additionalProperties: false`) | Confira a `description` da resposta |

---

## Checklist

- [ ] `source.session_id` na **raiz**, tanto em PF quanto em PJ.
- [ ] Em PJ, confirmado que os dados de device aparecem na dashboard de análise cadastral.
- [ ] Em PJ, `face` e documentos de identidade dentro de `legal_representatives[]`.
- [ ] Em PJ, apenas `ie`, `company_statute` e `proof_of_address` na raiz de `documents`.
- [ ] `passport`, quando enviado, com `ocr_key`.

---

# Padrões

URL: /documentation/caas/onboarding/standards

Para facilitar a integração e garantir a integridade da informação, foram definidos alguns padrões que são seguidos em toda a API.

## Valores Monetários
> Exemplos:

```
10000
12345
98741
1223
1
0
```

As APIs assumem que todos os valores monetários enviados são em Reais Brasileiros. Os valores devem ser enviados como inteiro em centavos.

## Data e Hora com Fuso Horário
> Alguns exemplos:

```
2019-10-15T22:35:12.232-03:00
2018-05-01T13:32:11.297+00:00
2019-05-01T00:00:00.000+00:00
```

É representada conforme a ISO 8601. Neste caso, o fuso-horário é colocado logo após o horário e deve representar o fuso do local onde aquele dado será valido.

A máscara utilizada para validação é a seguinte:

`YYYY-MM-ddThh:mm:ss.sss±hh:mm`

## Data e Hora sem Fuso Horario
> Alguns exemplos:

```
2019-10-15T22:35:12
2018-05-01T13:32:11
2019-05-01T00:00:00
```

É representada conforme a ISO 8601. Dados que independem de fuso-horário deverão ser enviados sem ele, sempre em UTC, com a letra Z indicando que este dado está em UTC. O seguinte formato, portanto, será validado:

`YYYY-MM-ddThh:mm:ss.sssZ`

## Data
> Alguns exemplos

``` 
2019-10-15
2019-01-01
2017-03-20
```

No caso de campos que recebem somente data, uma data de nascimento, por exemplo, somente a data, sem nenhum horário deve ser enviada com o seguinte formato:

`YYYY-MM-dd`
 

## Documentos
Uma vez que os números de documento são bastante variados e muitos deles possuem caracteres que não se enquadram como numéricos, definem-se todos os números de documento como string. Outro bom motivo para definí-los como string é evitar que os zeros à esquerda desapareçam. Documentos previstos nesta página possuem uma máscara bem definida e estarão sujeitos a validação. O restante dos documentos, como RG, dada sua falta de padronização, não serão validados.

## CPF

> Exemplos de CPFs válidos contra a máscara definida:

```
123.456.789-12
321.987.543-23
111.283.333-00
```

> Exemplos de CPFs inválidos contra a máscara definida:

```
8.577.477-8
08.104.627/0001-23
123.456.789-1
23.456.789-01
```

O CPF é sempre definido como uma string e será validado contra a máscara:

`###.###.###-##`

## CNPJ

> Exemplos de CNPJs válidos contra a máscara definida:

```
08.104.627/0001-02
01.079.210/0114-67
32.402.502/0001-35
```

> Exemplos de CNPJs inválidos contra a máscara definida:

```
8.577.477-8
123.456.789-12
321.987.543-23
32.402.502/0001-3
032.402.502/0001-3
```

O CNPJ é sempre definido como uma string e será validado contra a máscara:

`##.###.###/####-##`

## IP

> Exemplos de IPs válidos contra a máscara definida:

```
201.81.161.86
201.081.161.86
201.81.161.086
201.81.0.1
```

> Exemplos de IPs inválidos:

```
201.81..86
358.81.161.86
201.81.161
```

IPs deverão ser enviados sempre em IPv4, zeros à esquerda poderão ou não ser enviados, respeitando a seguinte máscara:

`###.###.###.###`

---

# Dinâmica dos status

URL: /documentation/caas/onboarding/status_dynamics

Dinâmica dos status

A API de Análise cadastral trabalha com **três** enumeradores de status independentes. Entender a diferença entre eles é o passo que mais evita erro de integração:

| Enumerador | Quem define o valor | Quem devolve | O que representa |
| --- | --- | --- | --- |
| `analysis_status` | **Você**, na sua política | **QI Tech** | O resultado da execução da sua árvore de decisão. |
| `risk_level` | **Você**, na sua política | **QI Tech** | O nível de risco atribuído pela sua árvore de decisão. |
| `client_status` | **Você** | — | A situação do cliente na sua plataforma. |

:::info `analysis_status` e `risk_level` saem da sua própria política
Esses dois campos **não** são um veredito nosso sobre o cadastro. Eles são definidos por você, no motor de regras, através das **caixinhas de decisão** e de **nível de risco** que você posiciona ao longo da sua árvore.

A cada requisição, a QI Tech executa essa árvore contra os dados analisados e devolve o resultado que a **sua** política determinou. Se você quer que um cenário passe a cair em `in_manual_analysis` em vez de `automatically_reproved`, ou que um perfil receba `risk_level: high` em vez de `medium`, a mudança é no motor de regras — não há nada a alterar na integração.
:::

:::tip A regra prática
`analysis_status` é o **resultado da sua política**, executada por nós. `client_status` é a **sua decisão de negócio**, que você registra via [PUT](/documentation/caas/onboarding/update_registration) conforme a jornada do cliente evolui.
:::

### Como a decisão é produzida

1. Você desenha a árvore de decisão no motor de regras, posicionando as caixinhas de **decisão** (`analysis_status`) e de **nível de risco** (`risk_level`) conforme a sua política.
2. Você envia o cadastro para a API.
3. A QI Tech executa a árvore contra os dados do cadastro e os enriquecimentos disponíveis.
4. A resposta traz o `analysis_status` e o `risk_level` que a sua árvore determinou para aquele caso.

Por isso, dois clientes que enviam exatamente o mesmo cadastro podem receber respostas diferentes: cada um tem a sua própria política configurada.

---

## `analysis_status`

Resultado da execução da sua árvore de decisão. Os status abaixo se dividem em três grupos pelo que você deve fazer com cada um.

### Decisões finais

| Status | Significado | Ação |
| --- | --- | --- |
| `automatically_approved` | A sua árvore de decisão terminou em uma caixinha de aprovação automática. | Pode aprovar o cadastro. |
| `automatically_reproved` | A sua árvore de decisão terminou em uma caixinha de reprovação automática. | Recuse o cadastro. |
| `manually_approved` | Aprovado por um analista. | Pode aprovar o cadastro. |
| `manually_reproved` | Reprovado por um analista. | Recuse o cadastro. |
| `approved_by_time` | Aprovado automaticamente após expirar o prazo de análise. | Pode aprovar o cadastro. |
| `reproved_by_time` | Reprovado automaticamente após expirar o prazo de análise. | Recuse o cadastro. |

### Aguardando — o resultado chega por webhook

| Status | Significado | Ação |
| --- | --- | --- |
| `in_queue` | Análise assíncrona em fila. | Aguarde o [Webhook](/documentation/caas/onboarding/webhook). |
| `pending` | As consultas estão demorando mais que o esperado. | Aguarde o Webhook. |
| `in_manual_analysis` | Derivado para análise manual por um analista. | Aguarde o Webhook. |
| `waiting_for_data` | Aguardando dados complementares para processar. | Aguarde o Webhook. |
| `on_hold` | Análise pausada, aguardando retorno do cliente. | Aguarde o Webhook. |

:::danger Não trate "aguardando" como recusa
`in_queue`, `pending`, `in_manual_analysis`, `waiting_for_data` e `on_hold` **não são negativas**. Tratá-los como reprovação é o erro de integração mais comum nesta API — recusa cadastros legítimos que seriam aprovados minutos depois.
:::

### Contestação e casos especiais

| Status | Significado | Ação |
| --- | --- | --- |
| `automatically_challenged` | A sua árvore terminou em uma caixinha de contestação. | O cadastro precisa passar pelo fluxo de contestação. |
| `manually_challenged` | Contestado por um analista. | Idem. |
| `manually_cancelled` | Análise cancelada. | Nenhuma decisão será emitida. |
| `failed` | A análise falhou durante o processamento. | Reenvie com um novo `id` ou acione o suporte. |
| `not_analysed` | Enviado com `analyze=false`. | Nenhuma recomendação será emitida; siga sua própria decisão. |

---

## `client_status`

Situação cadastral do cliente na **sua** plataforma. Você é responsável por manter esse status atualizado via [PUT](/documentation/caas/onboarding/update_registration) — ele alimenta os modelos e melhora análises futuras.

| Status | Significado |
| --- | --- |
| `registered` | Registrado, sem decisão de aprovação ainda. |
| `approved` | Aprovado na sua plataforma. |
| `reproved` | Reprovado na sua plataforma. |
| `fraud_blocked` | Bloqueado por suspeita ou confirmação de fraude. |
| `default_blocked` | Bloqueado por inadimplência. |
| `cancelled` | O cliente cancelou o uso do serviço. |

:::info Grafia do enumerador
O valor correto é `cancelled`, com dois L. Versões antigas desta documentação grafavam `canceled` — esse valor é rejeitado com HTTP 400.
:::

### Quais valores podem ser enviados

O método usado determina os valores aceitos:

| Tipo de cadastro | Valores aceitos no `PUT` |
| --- | --- |
| Natural Person | `approved`, `reproved`, `fraud_blocked`, `default_blocked`, `cancelled` |
| Legal Person | `fraud_blocked`, `default_blocked`, `cancelled` |

:::caution Legal Person aceita menos valores
Em **Legal Person**, o `PUT` **não** aceita `approved` nem `reproved` — apenas os três valores de bloqueio e cancelamento. Enviar `approved` em um cadastro PJ retorna **HTTP 400**.
:::

Detalhes em [Atualizar um cadastro](/documentation/caas/onboarding/update_registration).

---

## `risk_level`

Nível de risco atribuído ao cadastro pela caixinha de nível de risco que a sua árvore percorreu. Presente na resposta do `GET` e nos eventos de análise.

| Valor | Significado |
| --- | --- |
| `low` | Risco baixo. |
| `medium` | Risco médio. |
| `high` | Risco alto. |
| `critical` | Risco crítico. |
| `undefined` | Nenhuma avaliação de risco foi realizada. |

---

## Fluxo típico

1. Você envia o cadastro — `POST /onboarding/natural_person`.
2. A resposta traz um `analysis_status`.
   - Se for uma **decisão final**, siga o que a sua política determinou.
   - Se for **aguardando**, espere o webhook.
3. Ao decidir na sua plataforma, envie o `client_status` via `PUT`.

---

# Atualizar um cadastro

URL: /documentation/caas/onboarding/update_registration

Atualizar um cadastro

Use o método `PUT` para atualizar o **status** de um cadastro — tanto o `client_status` (situação na sua plataforma) quanto o `analysis_status` (decisão manual de análise).

:::tip Retroalimentação importa
Informar o desfecho real via `PUT` é o que mantém a qualidade das recomendações. Sem esse retorno, os modelos não aprendem com os casos da sua carteira.
:::

O endpoint aceita os dois tipos de cadastro:

```text
/onboarding/natural_person/{external_id}
/onboarding/legal_person/{external_id}
```

O `{external_id}` é o `id` que você enviou no `POST`.

---

## PUT — atualizar status

ENDPOINT /onboarding/natural_person/ EXTERNAL_ID
MÉTODO PUT

O corpo aceita **duas formas mutuamente exclusivas**: uma para `client_status`, outra para `analysis_status`.

**client_status**

Atualiza a situação do cliente na sua plataforma.

client_status
enum
obrigatório
Em Natural Person aceita approved , reproved , fraud_blocked , default_blocked ou cancelled . Em Legal Person , apenas fraud_blocked , default_blocked ou cancelled .

event_date
datetime
obrigatório
Data e hora do evento, com fuso horário. Offset terminado em :00 / :30 ou sufixo Z .

```json title="Bloqueio por fraude"
{
  "client_status": "fraud_blocked",
  "event_date": "2026-08-07T13:34:12-03:00"
}
```

```json title="Bloqueio por inadimplência"
{
  "client_status": "default_blocked",
  "event_date": "2026-08-07T13:34:12-03:00"
}
```

```json title="Cancelamento pelo cliente"
{
  "client_status": "cancelled",
  "event_date": "2026-08-07T13:34:12-03:00"
}
```

**analysis_status**

Registra uma decisão manual de análise.

analysis_status
enum
obrigatório
Aceita manually_approved , manually_reproved , manually_challenged , manually_cancelled ou on_hold .

risk_level
enum
opcional
low , medium , high ou critical .

observation
string
opcional
Justificativa da decisão. Até 3.000 caracteres.

user_name
string
opcional
Nome do analista responsável. Até 50 caracteres.

user_email
string
opcional
E-mail do analista responsável.

```json title="Aprovação manual"
{
  "analysis_status": "manually_approved",
  "risk_level": "low",
  "observation": "Documentação conferida e validada.",
  "user_name": "Ana Analista",
  "user_email": "ana@exemplo.com.br"
}
```

### Exemplos de requisição

**Python**

```python
import requests

BASE_URL = "https://api.sandbox.caas.qitech.app"
API_KEY = "YOUR_API_KEY"
EXTERNAL_ID = "12345678"

response = requests.put(
    f"{BASE_URL}/onboarding/natural_person/{EXTERNAL_ID}",
    json={
        "client_status": "approved",
        "event_date": "2026-08-07T13:34:12-03:00",
    },
    headers={"Authorization": API_KEY},
    timeout=30,
)

response.raise_for_status()
```

**PHP**

```php
<?php

$baseUrl    = 'https://api.sandbox.caas.qitech.app';
$apiKey     = 'YOUR_API_KEY';
$externalId = '12345678';

$payload = [
    'client_status' => 'approved',
    'event_date'    => '2026-08-07T13:34:12-03:00',
];

$ch = curl_init("{$baseUrl}/onboarding/natural_person/{$externalId}");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Authorization: ' . $apiKey,
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 200) {
    throw new RuntimeException("Falha ao atualizar: HTTP {$status} — {$body}");
}
```

**Node.js**

```javascript
const BASE_URL = "https://api.sandbox.caas.qitech.app";
const API_KEY = "YOUR_API_KEY";
const EXTERNAL_ID = "12345678";

async function updateStatus() {
  const response = await fetch(
    `${BASE_URL}/onboarding/natural_person/${EXTERNAL_ID}`,
    {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
        Authorization: API_KEY,
      },
      body: JSON.stringify({
        client_status: "approved",
        event_date: "2026-08-07T13:34:12-03:00",
      }),
    },
  );

  if (!response.ok) {
    throw new Error(`Falha ao atualizar: HTTP ${response.status}`);
  }
}

updateStatus();
```

**Java**

```java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class UpdateClientStatus {

    private static final String BASE_URL = "https://api.sandbox.caas.qitech.app";
    private static final String API_KEY = "YOUR_API_KEY";
    private static final String EXTERNAL_ID = "12345678";

    public static void main(String[] args) throws Exception {
        String payload = """
            {
              "client_status": "approved",
              "event_date": "2026-08-07T13:34:12-03:00"
            }
            """;

        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/onboarding/natural_person/" + EXTERNAL_ID))
                .header("Content-Type", "application/json")
                .header("Authorization", API_KEY)
                .timeout(Duration.ofSeconds(30))
                .PUT(HttpRequest.BodyPublishers.ofString(payload))
                .build();

        HttpResponse<String> response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 200) {
            throw new IllegalStateException(
                    "Falha ao atualizar: HTTP " + response.statusCode());
        }
    }
}
```

**C#**

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class UpdateClientStatus
{
    private const string BaseUrl = "https://api.sandbox.caas.qitech.app";
    private const string ApiKey = "YOUR_API_KEY";
    private const string ExternalId = "12345678";

    public static async Task Main()
    {
        var payload = new
        {
            client_status = "approved",
            event_date = "2026-08-07T13:34:12-03:00"
        };

        using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
        client.DefaultRequestHeaders.Add("Authorization", ApiKey);

        var content = new StringContent(
            JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");

        var response = await client.PutAsync(
            $"{BaseUrl}/onboarding/natural_person/{ExternalId}", content);

        if (!response.IsSuccessStatusCode)
        {
            throw new InvalidOperationException(
                $"Falha ao atualizar: HTTP {(int)response.StatusCode}");
        }
    }
}
```

**curl**

```bash
curl -X PUT \
  'https://api.sandbox.caas.qitech.app/onboarding/natural_person/12345678' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: YOUR_API_KEY' \
  -d '{
    "client_status": "approved",
    "event_date": "2026-08-07T13:34:12-03:00"
  }'
```

## Erros

| Status | Situação | Como resolver |
| --- | --- | --- |
| 400 | Enum fora da lista aceita. | Confira os valores aceitos para `client_status` e `analysis_status`. |
| 400 | `client_status` sem `event_date`. | Envie os dois juntos. |
| 400 | Campo não previsto no schema. | O schema usa `additionalProperties: false`. |
| 404 | Cadastro não encontrado para a sua API Key. | Verifique o `external_id` do path. |

Lista completa em [Status HTTP](/documentation/caas/onboarding/http_status).

---

# Webhook

URL: /documentation/caas/onboarding/webhook

Webhook

Atualizações no status de fraude (Para cadastros que sejam derivados para análise manual ou que sejam respondidos como Pendente), são notificados por meio de Webhook. Para tanto, é necessário, por meio da equipe do [suporte](mailto:suporte.caas@qitech.com.br), configurar um endereço do endpoint por onde vamos notificar as atualizações e também um *secret_token* que será utilizado para assinar a requisição.

O cliente pode, apesar de não recomendável, também utilizar a técnica de [polling](https://en.wikipedia.org/wiki/Polling_(computer_science)). Neste caso, basta não configurar o endpoint de webhook e utilizar os endpoints de recuperação de cadastro para proceder com o polling.

## Assinatura do Webhook

## Requisição

```bash
curl --location 'YOUR-ENDPOINT-HERE' \
--header 'Signature: CALCULATED-HASH-HMAC' \
--data '{"natural_person_id": "538509",  "analysis_status": "manually_approved", "event_date": "2024-11-13T17:52:50Z", "reason": "manually_approved"}'
```

A requisição possui o formato acima e notifica a mudança no status de fraude. É importante ressaltar que a requisição utiliza o verbo HTTP POST e o corpo da requisição é enviado como texto codificado em UTF-8.

## Retentativas

A notificação é considerada realizada quando recebe como resposta um HTTP Status 200. Caso as notificações falhem, serão feitas 5 retentativas, com os seguintes intervalos, até que um 200 seja retornado ou as tentativas terminem:

* 30 segundos
* 60 segundos
* 120 segundos
* 240 segundos
* 360 segundos