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

# Guia rápido

> Crie um contato e uma coleta, envie uma fatura e leia os campos da fatura.

Este guia leva a fatura de uma importação do seu sistema até os campos que a leitura extrai. Ele usa `curl` e cinco endpoints, nesta ordem:

1. `GET /packs` mostra o pacote e o tipo de documento da fatura.
2. `POST /contacts` cria o contato.
3. `POST /collections` cria a coleta do contato.
4. `POST /documents` envia a fatura para a coleta.
5. `GET /documents/{id}` mostra o andamento da leitura e, no fim, os campos da fatura.

## Antes de começar

Você precisa de três coisas:

* a chave de API da organização. Veja [Autenticação](/authentication);
* um pacote de operação ativo que pede a fatura comercial. O operador cria o pacote no QX;
* o PDF de uma fatura comercial, com o nome `fatura.pdf`.

Os exemplos usam `qx_sua_chave`. Troque esse texto pela chave da organização.

Cada `POST` do guia leva o cabeçalho `Idempotency-Key`. Crie um valor novo para cada escrita, e guarde o valor junto da escrita no seu sistema. Se a resposta não chegar, repita a chamada com o mesmo valor. A API grava o recurso uma vez só. Veja [Idempotência](/idempotency).

## 1. Ache o pacote e o tipo da fatura

```bash theme={null}
curl "https://app.useqx.com/api/v1/packs?kind=operation&active=true" \
  -H "Authorization: Bearer qx_sua_chave"
```

A resposta traz os pacotes de operação ativos. Cada requisito do pacote traz o tipo de documento que ele pede:

```json theme={null}
{
  "data": [
    {
      "id": "pck_12",
      "name": "Importação marítima",
      "kind": "operation",
      "required_for": "pj",
      "active": true,
      "identification_mode": "any",
      "requirements": [
        {
          "document_type": { "id": "dtp_31", "name": "Fatura Comercial (Commercial Invoice)" },
          "required": true,
          "identifier": true,
          "accepts_many": true,
          "position": 1
        },
        {
          "document_type": { "id": "dtp_32", "name": "Bill of Lading (B/L)" },
          "required": true,
          "identifier": true,
          "accepts_many": false,
          "position": 2
        },
        {
          "document_type": { "id": "dtp_33", "name": "Romaneio de Carga (Packing List)" },
          "required": false,
          "identifier": false,
          "accepts_many": true,
          "position": 3
        }
      ]
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Guarde o `id` do pacote (`pck_12`) e o `id` do tipo da fatura (`dtp_31`).

## 2. Crie o contato

```bash theme={null}
curl https://app.useqx.com/api/v1/contacts \
  -H "Authorization: Bearer qx_sua_chave" \
  -H "Idempotency-Key: d4481be1-a6f6-4bde-bfd9-e15f83757aa1" \
  -H "Content-Type: application/json" \
  -d '{"tax_id": "12.345.678/0001-95", "email": "fiscal@importadora.com.br", "name": "Importadora Exemplo Ltda"}'
```

A resposta `201` traz o contato:

```json theme={null}
{
  "id": "com_12",
  "type": "company",
  "name": "Importadora Exemplo Ltda",
  "trade_name": null,
  "email": "fiscal@importadora.com.br",
  "tax_id": "12345678000195",
  "lookup_status": "pending",
  "discarded": false,
  "origin": "contact",
  "created_at": "2026-09-25T10:30:00.000-03:00"
}
```

* O CNPJ cria uma empresa, e o CPF cria uma pessoa.
* O QX consulta o CNPJ depois da criação. O campo `lookup_status` mostra o andamento da consulta.
* A organização pode já ter um contato com esse CNPJ. Nesse caso, a resposta é `409` com o código `contact_exists`, e o campo `contact` traz o contato. Use o `id` desse contato nos próximos passos.

## 3. Crie a coleta

```bash theme={null}
curl https://app.useqx.com/api/v1/collections \
  -H "Authorization: Bearer qx_sua_chave" \
  -H "Idempotency-Key: c3cbd9dc-1f1b-4541-857f-90bd8f3641ea" \
  -H "Content-Type: application/json" \
  -d '{"pack_id": "pck_12", "contact_id": "com_12"}'
```

A resposta `201` traz a coleta, com um slot vazio para cada requisito do pacote:

```json theme={null}
{
  "id": "col_40",
  "protocol": "DOC-2026-00123",
  "state": "assembling",
  "discarded": false,
  "contact": { "id": "com_12", "type": "company", "name": "Importadora Exemplo Ltda" },
  "recipient": null,
  "packs": [{ "id": "pck_12", "name": "Importação marítima" }],
  "numbers": [],
  "created_at": "2026-09-25T10:31:12.000-03:00",
  "ready_at": null,
  "documents": [
    {
      "id": "doc_310",
      "document_type": { "id": "dtp_31", "name": "Fatura Comercial (Commercial Invoice)" },
      "status": "pending",
      "has_content": false
    },
    {
      "id": "doc_311",
      "document_type": { "id": "dtp_32", "name": "Bill of Lading (B/L)" },
      "status": "pending",
      "has_content": false
    },
    {
      "id": "doc_312",
      "document_type": { "id": "dtp_33", "name": "Romaneio de Carga (Packing List)" },
      "status": "pending",
      "has_content": false
    }
  ]
}
```

* A coleta começa no estado `assembling`, em montagem.
* O QX não manda e-mail ao contato. Para mandar o convite do portal ao contato, envie também `"send_invitation": true`.

## 4. Envie a fatura para a coleta

```bash theme={null}
curl https://app.useqx.com/api/v1/documents \
  -H "Authorization: Bearer qx_sua_chave" \
  -H "Idempotency-Key: eb3754f8-a422-43f5-8d77-b0aa74cef381" \
  -F file=@fatura.pdf \
  -F contact_id=com_12 \
  -F document_type_id=dtp_31 \
  -F collection_id=col_40
```

A resposta `201` traz o documento novo. A leitura já começou, e os campos ainda não têm resposta:

```json theme={null}
{
  "id": "doc_318",
  "document_type": { "id": "dtp_31", "name": "Fatura Comercial (Commercial Invoice)" },
  "status": "uploaded",
  "reading_status": "extracting",
  "contact": { "id": "com_12", "type": "company", "name": "Importadora Exemplo Ltda" },
  "collection_id": "col_40",
  "in_triage": false,
  "discarded": false,
  "discard_reason": null,
  "number": null,
  "arrival_channel": "api",
  "arrived_at": "2026-09-25T10:32:05.000-03:00",
  "files": [{ "name": "fatura.pdf", "content_type": "application/pdf", "size": 182044 }],
  "created_at": "2026-09-25T10:32:05.000-03:00",
  "fields": [
    { "key": "invoice_number", "label": "Número da Fatura", "value": null },
    { "key": "invoice_date", "label": "Data da Fatura", "value": null },
    { "key": "invoice_amount", "label": "Valor da Fatura", "value": null },
    { "key": "currency", "label": "Moeda", "value": null }
  ]
}
```

* O documento novo ocupa o slot vazio da fatura, e o slot `doc_310` sai da coleta. Use o `id` da resposta (`doc_318`) nos próximos passos.
* Quando todo documento obrigatório da coleta chega, a coleta passa a `reviewing`, e o QX avisa os operadores.

## 5. Espere a leitura

Chame `GET /documents/{id}` a cada 10 segundos ou mais. Pare quando o `reading_status` chegar a um destes valores:

| `reading_status` | O que quer dizer                                                  |
| ---------------- | ----------------------------------------------------------------- |
| `complete`       | A leitura terminou, e os campos têm as respostas que ela extraiu. |
| `failed`         | A leitura falhou.                                                 |
| `no_reader`      | O tipo de documento não tem leitura.                              |

Os valores `not_started`, `extracting`, `enriching` e `validating` dizem que a leitura ainda não terminou.

O laço abaixo usa o [jq](https://jqlang.org) para ler o campo:

```bash theme={null}
while true; do
  status=$(curl -s https://app.useqx.com/api/v1/documents/doc_318 \
    -H "Authorization: Bearer qx_sua_chave" | jq -r .reading_status)
  echo "$status"
  case "$status" in
    complete|failed|no_reader) break ;;
  esac
  sleep 10
done
```

## 6. Leia os campos

```bash theme={null}
curl https://app.useqx.com/api/v1/documents/doc_318 \
  -H "Authorization: Bearer qx_sua_chave"
```

A resposta traz todos os campos do tipo, na ordem do catálogo. O exemplo mostra só uma parte deles:

```json theme={null}
{
  "id": "doc_318",
  "document_type": { "id": "dtp_31", "name": "Fatura Comercial (Commercial Invoice)" },
  "status": "uploaded",
  "reading_status": "complete",
  "contact": { "id": "com_12", "type": "company", "name": "Importadora Exemplo Ltda" },
  "collection_id": "col_40",
  "in_triage": false,
  "discarded": false,
  "discard_reason": null,
  "number": "INV-81244/2026",
  "arrival_channel": "api",
  "arrived_at": "2026-09-25T10:32:05.000-03:00",
  "files": [{ "name": "fatura.pdf", "content_type": "application/pdf", "size": 182044 }],
  "created_at": "2026-09-25T10:32:05.000-03:00",
  "fields": [
    { "key": "invoice_number", "label": "Número da Fatura", "value": "INV-81244/2026" },
    { "key": "invoice_date", "label": "Data da Fatura", "value": "2026-09-18" },
    { "key": "invoice_amount", "label": "Valor da Fatura", "value": "48,250.00" },
    { "key": "currency", "label": "Moeda", "value": "USD" }
  ]
}
```

* Cada item de `fields` traz a chave, o rótulo e a resposta do campo.
* O campo sem resposta vem com `value` igual a `null`.
* O campo `number` traz o número impresso que identifica o documento. Na fatura, é o número da fatura.

Para corrigir uma resposta, chame `PATCH /documents/{id}` com `fields`. O valor que o seu sistema grava vence o valor que a leitura extraiu.

## As regras de uso

Siga estas quatro regras em toda integração:

1. Envie os documentos da mesma operação com `collection_id`. Cada envio da API chega sozinho, e o documento que ele cria não tem irmãos na Triagem. Sem coleta, o encaixe liga o documento à operação só pelos números que ele imprime ou cita. O documento sem esses números pode esperar na Triagem por um operador.
2. Envie o documento de cadastro, do pacote `kyc`, com `collection_id`. Sem coleta, a varredura descarta esse documento quando a organização tem um pacote de operação ativo. A resposta mostra `discarded` igual a `true` e `discard_reason` igual a `outside_pack`.
3. Consulte o `reading_status` a cada 10 segundos ou mais. Cada consulta conta no limite de 300 chamadas por minuto da chave, com as outras chamadas. Veja [Autenticação](/authentication).
4. Envie um documento por arquivo. A API não divide o arquivo. O arquivo que junta a fatura, o romaneio e o B/L vira um documento só, do tipo que a chamada informou.
