# Sandbox, produção e lista de bloqueio

<https://unifokal.com/docs/ambientes>

## Lista de bloqueio

Marque um titular e novas verificações dele voltam `blocked` (evento `verification.blocked`) e **não são cobradas**. O bloqueio pode valer para a **conta inteira**, em todos os flows, ou **só para um flow**: a lista da conta vale em todos, e a do flow acrescenta. O valor marcado é guardado cifrado e nunca volta em texto puro.

Além de CPF, CNPJ e documento estrangeiro, a lista aceita o `reference_id`, o identificador do titular no seu sistema, que você envia ao criar a sessão. É a chave que existe antes de haver documento: serve para barrar quem abandonou a verificação no meio ou um titular que você já decidiu não atender. A partir dele, a próxima verificação daquele `reference_id` termina em `blocked`, sem cobrança, e o webhook `verification.blocked` traz `reason` igual a `reference_blocklisted`. Ao titular, a tela informa apenas que a empresa registrou uma restrição. Use sempre o mesmo `reference_id` para o mesmo titular, de preferência com letras, números e os sinais `. _ : @ -`. A comparação **não distingue maiúsculas de minúsculas**: `User_42` e `user_42` são o mesmo titular, então quem você bloqueou numa grafia fica bloqueado em todas. O bloqueio por referência vale só na sua organização e nunca é compartilhado com empresas vinculadas.

No painel, você bloqueia a partir da **linha da verificação**, que é onde acabou de ver o caso, e desbloqueia o titular em **Sessões**. Os interruptores de bloqueio automático são **configuração do flow**, junto do resto da política.

Cada bloqueio dura o prazo do seu tipo de identificador. CPF, CNPJ e `reference_id` valem enquanto você mantiver o bloqueio: CPF e CNPJ não passam a designar outra pessoa, e o `reference_id` é do seu sistema. O documento estrangeiro sai da lista **10 anos** depois do bloqueio, e o prazo recomeça se você bloquear de novo, porque um documento de viagem não segue válido por mais tempo do que isso. Quando um bloqueio passa **24 meses** sem barrar ninguém, o painel mostra ao lado dele o selo **Sem uso há mais de 24 meses**, para você revisar se ele ainda faz sentido. O selo não remove nada: a decisão continua sua.

## Sandbox

O sandbox roda o pipeline completo, grátis e com teto mensal (`livemode:false`). CPFs determinísticos disparam cada resultado para você testar o webhook sem capturar nada:

```
# 1. DESFECHO (documento, face, liveness)
000.000.000-00 → approved
000.000.000-01 → inconclusivo em CADA modulo (score 60, passed null): a verificacao
                 termina em review, com ou sem face e liveness no flow.
000.000.000-02 → denied (reprovado)
000.000.000-04 → review agora, approved depois (dois webhooks, ver abaixo)
000.000.000-05 → review agora, denied depois (dois webhooks, ver abaixo)
qualquer outro  → approved

# 2. CONTEUDO (screening, compliance, risco): o sufixo escolhe O QUE o modulo devolve,
#    e um achado forte leva a verificacao para review. A matriz esta na secao de cada
#    modulo: PEP (66/77/88/99), impedidos de apostar (02/01/33), midia adversa (02/33),
#    coerencia cadastral (02/01/33), ip_risk (33/44/55), email_risk (33/44/55),
#    ip_risk_plus (33/44), email_risk_plus (33/44/55), telefone_risco (33/44/55).
#    Nos cinco de risco o sufixo troca apenas o dado; o desfecho sai da lista 1 acima.

# 3. DOCUMENTO DE VIAGEM (doc_global): num flow global nao ha CPF lido do documento,
#    entao o sufixo viaja no campo opcional `document` do
#    POST /v1/verification-sessions/:id/submit. Os dois ultimos digitos escolhem o
#    cenario, e aqui eles mudam o DESFECHO:
000.000.000-00 → aprova
000.000.000-01 → pede nova foto (mrz_not_found)
000.000.000-02 → vai para review (mrz_tampered)
000.000.000-41 → vai para review (mrz_visual_mismatch)
000.000.000-42 → vai para review (mrz_expiry_unverified)
000.000.000-43 → pede outro arquivo (invalid_media)
000.000.000-45 → aprova com o passaporte vencido (document.expired: true)

# 4. CADASTRO DE CNPJ (cnpj_socios, cnpj_cadastro, cnpj_receita, cnpj_participacoes):
#    o CNPJ de teste terminado em 84 simula a resposta PARCIAL da base.
#    A empresa esta ativa e o modulo aprova, mas os dados nao vem: o item do
#    modulo em check_details sai com data.company null e completeness: partial.

# 5. DOCUMENTO BRASILEIRO (cpf_ocr): o mesmo campo document do submit.
000.000.000-41 → vai para review (mrz_visual_mismatch, o impresso nao bate com a MRZ)
000.000.000-45 → aprova com o documento vencido (document.expired: true)
```

Nas famílias 1 e 2 o CPF de teste vai no campo `document` do `POST /v1/verification-sessions/:id/submit`. O widget submete sem esse campo, então uma sessão de sandbox concluída pelo widget sempre termina aprovada: para ver o `-01`, o `-02`, o `-04` e o `-05`, chame o submit pela API.

Os sufixos `-04` e `-05` testam o webhook de atualização sem esperar um caso real. A verificação termina em review agora e você recebe o primeiro `verification.completed`. Cerca de 60 segundos depois (até 75), ela é decidida de novo e chega um segundo `verification.completed`, com um `id` de evento novo, terminado em `_r<número>`, e o status final: approved no `-04`, denied no `-05`. Se alguém decidir a verificação pelo painel antes disso, vale a decisão da pessoa e o segundo evento não sai. Nada disso é cobrado.

## Sandbox e produção: o que muda

O pipeline é o mesmo e o formato da resposta é o mesmo. O que muda está nesta tabela, e vale a pena ler antes do go-live, não depois: metade destes itens só aparece quando você troca a chave.

| diferença | sandbox | produção |
| --- | --- | --- |
| Criar a chave de produção passa por portões que o sandbox não tem | POST /v1/keys com environment sandbox devolve 201 na primeira tentativa. | environment production exige, em cascata: a conta com o e-mail confirmado, a verificação da conta concluída (403 organization_cnpj_required) e a verificação em duas etapas ativa (403 mfa_enrollment_required, depois 403 mfa_code_required pedindo o código no corpo). |
| Flow e destino de webhook são POR AMBIENTE | O flow_id e o endpoint de webhook que você criou no sandbox existem só no sandbox. | Trocar apenas a chave no dia do go-live devolve 404 flow_not_found. Recrie o flow e o destino do webhook em produção e use o novo flow_id. |
| Produção exige as imagens; o sandbox não | O submit com apenas o documento de teste, sem nenhuma mídia, conclui a verificação e dispara o webhook. | O mesmo corpo devolve action_required, com missing_image por módulo, e nenhum webhook sai enquanto a jornada não terminar: as fotos entram pelo widget. |
| Motivo de recusa: o sandbox alcança um subconjunto do catálogo | Os sufixos cobrem aprovado, selfie_nao_confere, vida_nao_confirmada, restricao_do_cliente e verificacao_nao_confirmada. | O motivo mais comum na vida real é doc_ilegivel (documento que o OCR não conseguiu ler), e ele não tem sufixo no sandbox. Trate o campo reason_code como aberto dentro do catálogo, nunca como a lista dos cinco que você viu. |
| Teto de chamadas por minuto | 240 criações de sessão por minuto. | 60 criações de sessão por minuto. O teto real vem sempre no header X-RateLimit-Limit, e o 429 traz Retry-After: leia os headers em vez de fixar o número. Uma rota pode ter mais de um teto ao mesmo tempo, e o header traz sempre o que restringe primeiro, com o X-RateLimit-Remaining correspondente: o número que você lê é o que vai barrar, e não é preciso descobrir qual teto é. |
| Retenção da mídia | 7 dias. | 180 dias. |
| Cobrança | Nada é cobrado, e o teto mensal de sessões é o único limite de volume. | Criar a sessão não cobra e não reserva nada: a cobrança acontece quando a verificação termina, e o saldo atualizado chega no seu webhook. A criação só confere se o saldo cobre o máximo que a verificação pode custar: o preço do flow mais, quando o flow tem cobrança por sócio ou por empresa da cadeia, essas parcelas no teto. Sem saldo para isso, ela devolve 402 insufficient_credit com o saldo e o valor que falta na mensagem. Um 402 de flow com o módulo Proteção de conta nunca aciona a recarga automática. |

**Não existe rota `sk_` que leia o resultado de uma verificação.** Tentar` GET /v1/verifications/{id}` com a chave secreta devolve `403 credential_type_not_allowed`: aquela rota é do painel. O resultado chega ao seu servidor pelo [webhook](https://unifokal.com/docs/webhooks#webhooks), e `GET /v1/webhook-events` lista o que ainda não foi entregue.
