# Respostas às dúvidas da Vulci sobre a Partner API do Core

Documento de resposta técnica. Base da API em homologação: `http://coreapi-h.monetarie.internal/api/partner/v1` (documentação no portal `docs-h.monetarie.internal`). Cada ponto abaixo foi validado de forma empírica no ambiente de homologação. Onde havia falha nossa, ela foi corrigida e a correção está descrita junto da resposta.

## Resumo

| Dúvida | Situação | O que fazer |
|---|---|---|
| 1. CPF já existente (422 `tax_id has already been taken`) | Comportamento esperado para criar cliente. Faltava endpoint para abrir uma segunda conta no mesmo titular. | Use o novo `POST /customers/:id/accounts` para abrir conta adicional. |
| 2. Erro ao criar chave PIX (`{status: error, type: evp}`) | Falha nossa. Corrigida. | Para EVP, não envie o valor da chave. A API passa a devolver a chave atribuída ou um erro com o motivo. |
| 3. Listar chaves (`Missing ispb parameter`) | Falha nossa. Corrigida. | Use `GET /pix/keys?account_id=<id>` com o token. |
| 4. White-label / segregação | Arquitetura, sem falha. | Segregação lógica por parceiro; isolamento financeiro por entidade/ledger. Ver seção 4. |

## Autenticação (resumo rápido)

OAuth2 `client_credentials`. Troque `client_id` + `client_secret` por um token Bearer e use o token em todas as chamadas.

```
POST /api/partner/v1/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=cli_xxx&client_secret=sk_xxx&scope=pix:read pix:write account:read account:write customer:create
```

Resposta: `{ "access_token": "<jwt>", "token_type": "Bearer", "expires_in": 28800, "scope": "..." }`. O token vale 8 horas. O `scope` concedido é a interseção do que você pediu com as permissões da sua chave. Depois, envie `Authorization: Bearer <jwt>` em cada requisição.

## Dúvida 1. Criação de cliente/conta com CPF já existente

**Um mesmo titular pode ter mais de uma conta?** Sim. No modelo de dados, um titular (um CPF/CNPJ) pode ter várias contas. O que faltava era um endpoint na Partner API para abrir uma conta adicional num cliente que já existe.

**Por que vinha o 422?** O `POST /customers` cria, numa única operação, o cliente e a primeira conta. O `tax_id` (CPF/CNPJ) é único de forma global no Core. Então, ao chamar `POST /customers` com um documento já cadastrado, a resposta é `422` com `{"tax_id": ["has already been taken"]}`. Isso está correto: o `POST /customers` é só para o primeiro cadastro do titular.

**Como abrir uma segunda conta no mesmo titular (novo endpoint):**

```
POST /api/partner/v1/customers/{id}/accounts
Authorization: Bearer {access_token}
Content-Type: application/json

{ "account_type": "payment" }
```

- `id` é o id do cliente (o `data.id` devolvido no `POST /customers`, ou no `GET /customers/:id`).
- Permissão exigida: `account:write`.
- `account_type` é opcional (padrão `payment`). Tipos aceitos: `payment`, `checking`, `savings`, `salary`, `client`.
- O endpoint é "partner-scoped": só funciona para clientes do próprio parceiro. Cliente de outro parceiro (ou id inexistente) retorna `404`.
- Resposta `201`:

```json
{ "data": {
  "id": 10018000, "user_id": 1042, "kind": "...", "account_type": "payment",
  "agency": "0001", "account_number": "123457-8", "status": "active"
} }
```

**Restrições:** não há limite artificial de quantidade de contas por titular. A unicidade global de `tax_id` continua valendo, ou seja, o mesmo CPF não é cadastrado duas vezes como cliente (nem entre parceiros diferentes); para mais contas no mesmo titular, use sempre o endpoint acima.

## Dúvida 2. Erro na criação de chave PIX (EVP)

A resposta que vocês receberam (`{"data": {"status": "error", "type": "evp", "key": "a22371ae-..."}}`) era uma falha nossa. Investigamos a fundo o caminho de registro da chave no DICT do BACEN, achamos e corrigimos uma cadeia de defeitos, todos nossos, e o registro de chave PIX agora funciona de ponta a ponta (validado ao vivo em homologação: uma chave CPF registrada via a API devolveu `{"data":{"status":"ok","type":"cpf","key":"..."}}` e aparece ativa na listagem). As causas corrigidas foram:

1. **Erro mascarado.** Quando o registro falhava, a API devolvia `HTTP 202` com `status: error` e sem o motivo. Corrigido: agora, quando o registro é recusado, a API responde `422` com o motivo no corpo (por exemplo `KEY_LIMIT_EXCEEDED`, `KEY_ALREADY_EXISTS`), em vez de fingir que foi aceito. Foi essa correção que tornou visíveis os defeitos abaixo.
2. **RequestId inválido (a causa principal).** Nós mandávamos o identificador da requisição ao BACEN com um prefixo interno (`dict-...`), e o BACEN exige um UUID puro, então recusava com `Invalid parameters` para qualquer tipo de chave. Corrigido: mandamos um UUID válido.
3. **Chave EVP.** Para a chave aleatória (EVP), quem gera o valor é o BACEN. Nós mandávamos um valor, e o BACEN recusava. Corrigido: para EVP mandamos a chave vazia e adotamos o valor que o BACEN devolve.
4. **Dados da conta e do titular.** Corrigimos o tipo de conta (mapeado para o padrão do BACEN, CACC/SVGS/SLRY/TRAN), o tipo de pessoa (F para CPF, J para CNPJ) e a data de abertura da conta (datetime ISO 8601). Sem esses ajustes o BACEN também recusava.

**Como criar uma chave PIX (forma recomendada):**

```
POST /api/partner/v1/pix/keys
Authorization: Bearer {access_token}
Content-Type: application/json

{ "account_id": 1042, "type": "evp" }
```

- Para `type: "evp"`, **não envie** o campo da chave; o valor é atribuído pelo servidor e devolvido na resposta.
- Para `cpf`/`cnpj`, a chave é derivada do documento do titular.
- Para `phone`/`email`, envie o valor em `key`.
- Permissão: `pix:write`. `account_id` é obrigatório e precisa ser de uma conta do próprio parceiro.
- Sucesso (`202`): `{ "data": { "type": "evp", "key": "<chave atribuída>", "status": "pending" } }`.
- Falha (`422`): `{ "error": { "status": 422, "message": "Falha ao registrar chave PIX: <motivo>", "reason": "<motivo>" } }`.

## Dúvida 3. Listagem de chaves PIX

O `Missing ispb parameter` era uma falha nossa de contrato interno entre o Core e a cabine PIX (o parâmetro de ISPB não era repassado). Corrigido: a listagem volta a funcionar e usa o ISPB da própria instituição automaticamente.

**Chamada correta:**

```
GET /api/partner/v1/pix/keys?account_id={id}
Authorization: Bearer {access_token}
```

- Permissão: `pix:read`. O `account_id` é obrigatório e deve ser de uma conta do próprio parceiro (a documentação anterior não deixava isso claro, ela mostrava a chamada sem o parâmetro).
- Resposta `200`: `{ "data": [ { "id": "...", "type": "EVP", "key": "...", "status": "active", "owner_name": "...", "created_at": "..." } ] }`.

## Dúvida 4. Operação em modelo white-label

A Partner API já foi desenhada para multi-parceiro. A segregação tem duas camadas:

**Segregação lógica por parceiro (sempre ativa).** Cada parceiro tem um `partner_id`. Todo cliente e conta criado por um parceiro fica marcado com esse `partner_id`. As chamadas são "partner-scoped": um parceiro só enxerga e movimenta os clientes, contas, chaves, pagamentos e webhooks que ele mesmo criou. Tentar acessar dado de outro parceiro retorna 403/404. As listagens (`GET /accounts`, extratos, comprovantes) já vêm filtradas pelo parceiro, então conciliação, auditoria e relatórios saem separados por operação naturalmente.

**Isolamento financeiro por entidade/ledger (opcional, recomendado para white-label "de verdade").** O ledger contábil (TigerBeetle) é selecionado por entidade. Se cada white-label for modelado como uma entidade própria, cada um opera no seu próprio ledger, com isolamento financeiro e contábil completo. Se vários parceiros compartilharem a mesma entidade, eles dividem o mesmo ledger e a separação é apenas lógica (pelo `partner_id`). Para o objetivo de vocês (segregação financeira e operacional entre parceiros), a recomendação é: uma entidade por white-label, com o parceiro vinculado a ela. Cada cliente aberto por esse parceiro herda a entidade e cai no ledger correto.

**Identificador / namespace:** o identificador de tenancy da Partner API é o `partner_id` (vinculado a uma entidade). É por ele que as contas, movimentações e relatórios são segregados.

> Observação: existe também um módulo BaaS de multi-tenant mais antigo no Core (`tenants` / `white_label_configs`), mas ele é independente da Partner API. Para a operação white-label sobre os contratos da Partner API, o caminho recomendado é o `partner_id` + entidade descrito acima.

## Endpoints relevantes (Partner API v1)

| Método | Caminho | Escopo | Uso |
|---|---|---|---|
| POST | `/oauth/token` | (anônimo) | Obter token Bearer (8h) |
| POST | `/customers` | `customer:create` | Criar cliente + 1ª conta |
| GET | `/customers/:id` | `customer:read` | Status do cliente |
| POST | `/customers/:id/accounts` | `account:write` | **Abrir conta adicional (novo)** |
| GET | `/accounts` | `account:read` | Listar contas do parceiro |
| GET | `/accounts/:id/balance` | `account:read` | Saldo |
| GET | `/accounts/:id/statement` | `statement:read` | Extrato |
| POST | `/pix/keys` | `pix:write` | Registrar chave DICT |
| GET | `/pix/keys?account_id=` | `pix:read` | Listar chaves da conta |
| DELETE | `/pix/keys/:key?account_id=` | `pix:write` | Remover chave |
| POST | `/pix/payments` | `pix:write` | Enviar PIX |
| GET | `/pix/payments/:id` | `pix:read` | Status do PIX |
| POST | `/pix/charges` | `pix:write` | Cobrança / QR |

## Validação (homologação, 2026-06-30)

Todas as correções foram aplicadas com testes automatizados e deployadas em homologação, e revalidadas ao vivo com um token real de parceiro:

- Dúvida 3: `GET /pix/keys?account_id=...` passou a responder `{"data":[]}` (lista da conta) em vez de `Missing ispb parameter`. Corrigido e no ar.
- Dúvida 1: `POST /customers/{id}/accounts` abriu uma segunda conta para um titular existente (resposta `201`, a conta passou a ter duas). Corrigido e no ar.
- Dúvida 2: RESOLVIDO de ponta a ponta. A API não devolve mais o `status: error` sem motivo, e o registro de chave PIX funciona. Prova ao vivo em homologação: criamos um cliente novo pela API, registramos uma chave CPF para ele (`POST /pix/keys` devolveu `{"data":{"status":"ok","type":"cpf","key":"..."}}`, `HTTP 202`) e a chave aparece `ACTIVE` na listagem. A causa principal era um identificador de requisição malformado que enviávamos ao BACEN (com prefixo interno em vez de um UUID puro), somada ao tratamento incorreto da chave EVP e de alguns campos da conta/titular, tudo corrigido. O `KEY_LIMIT_EXCEEDED` que pode aparecer é a regra normal do BACEN (limite de 5 chaves por CPF), agora reportada de forma clara.
- Dúvida 4: arquitetura confirmada (segregação por parceiro e isolamento por entidade/ledger), sem defeito.
