Passo 4 · Erros e bloqueios
Toda falha de captura chega ao seu código de duas formas: como um erro no evento error do
componente <provvi-camera> (Tabela A) ou, por trás dele, como um erro HTTP de um dos endpoints
da API (Tabela B). Esta página é orientada a ação: para cada caso, o que fazer no seu app ou
o que orientar o usuário.
Alguns bloqueios (frames de câmera ao vivo, recaptura, localização inválida) são gates de dissuasão de fraude (fraud deterrence). Lembre que a garantia do fluxo web é assinatura server-side ICP-Brasil A1 sobre os bytes recebidos — não há âncora de hardware device-side. Esses gates elevam o custo do ataque; não substituem a cadeia de prova com hardware do SDK mobile.
Como tratar (padrão)
Seção intitulada “Como tratar (padrão)”Trate primeiro por classe (instanceof) para o caso amplo, depois por código
(error.code) para o granular. O objeto do erro traz error.code, error.message (o texto do
servidor, quando há), error.details e error.toJSON() (sem stack trace, seguro para telemetria).
import { CODES, ProvviBrowserError, ProvviLicenseError, ProvviStreamError,} from '@provvi/web-sdk';
camera.addEventListener('error', (e) => { const { error } = e.detail; // ProvviError com .code, .message e .details
// 1) Por classe — trata o caso amplo if (error instanceof ProvviBrowserError) { mostrarQrParaCelular(); // 2002 — abra no celular return; } if (error instanceof ProvviLicenseError) { // error.details.reason: INVALID_KEY | REVOKED | EXPIRED | // VOLUME_EXCEEDED | CLIENT_SUSPENDED | ORIGIN_NOT_ALLOWED mostrarErroLicenca(error.details?.reason); return; } if (error instanceof ProvviStreamError) { pedirPermissaoCamera(); // 3001 — permita a câmera return; }
// 2) Por código — trata o granular switch (error.code) { case CODES.TOKEN_REQUIRED: // 5002 — bug de integração console.error('open() foi chamado sem token'); break; case CODES.SESSION_FETCH_FAILED: // 4001 — sessão inválida, ou acesso não validado (403 sem block_reason) if (error.details?.status === 403 && error.message === 'Não foi possível validar o acesso. Recarregue a página pelo link recebido e tente de novo.') { // acesso não validado: oriente a recarregar a página pelo link recebido; se persistir, acione o suporte. // NÃO recrie a sessão em laço — cada nova sessão repete o mesmo 403. mostrar(error.message); break; } recriarSessao(); break; case CODES.INGEST_FAILED: // 4002 — mapeie pelo HTTP tratarIngest(error.details?.status, error.message); break; default: reportarTelemetria(error.toJSON?.() ?? error); }});O código INGEST_FAILED (4002) embrulha os erros HTTP da captura: o status real fica em
error.details.status. Mapeie-o para a ação do usuário (Tabela B, seção POST /web/ingest):
function tratarIngest(status, mensagem) { switch (status) { case 400: // câmera ao vivo, rótulo da foto, coordenadas ou imagem — o texto em `mensagem` distingue mostrar(mensagem); // câmera ao vivo ⇒ refaça a captura apontando para o objeto real (o componente envia os // frames extras sozinho); rótulo ⇒ bug de integração, corrija o `overlay.label`; // coordenadas ⇒ bug de integração (não esperado pelo componente): envie a posição como o // navegador a reporta; imagem ⇒ bug de integração (não esperado pelo componente): envie os // bytes que `captureFrames` produz, sem convertê-los break; case 403: // license, origem, relógio, nonce, sessão inválida ou acesso não validado (sem block_reason) — o texto em `mensagem` distingue mostrar('Não foi possível validar esta captura: ' + mensagem); // origem ⇒ domínio não habilitado para esta licença: fale com a Provvi e NÃO repita a // requisição; sessão carregada de outra origem ⇒ conclua a captura na página em que a // sessão foi aberta, ou crie uma sessão nova e abra-a já nessa página; // relógio ⇒ acertar data e hora; nonce ⇒ recarregar a página; sessão inválida ⇒ nova sessão; // licença ⇒ mesma ação da Tabela A, 8002; acesso não validado (sem block_reason) ⇒ recarregar a // página pelo link recebido e tentar de novo; se persistir, acionar o suporte — não repetir em laço break; case 413: // foto acima do limite por imagem — o limite vem no texto de `mensagem` mostrar('A foto ficou acima do tamanho aceito. Vamos tentar de novo.'); camera.open({ token }); // a sessão admite novas tentativas; o componente não retenta sozinho break; case 404: case 410: // sessão inválida ou expirada — crie outra recriarSessao(); break; case 409: // não foi possível processar — refaça a captura mostrar('Não foi possível processar esta captura. Tente novamente.'); break; case 422: // recaptura ou localização — objeto físico + permitir GPS mostrar('Fotografe o objeto físico e permita o acesso à localização.'); break; case 502: // falha do lado da Provvi — a captura NÃO foi entregue mostrar('Não foi possível concluir a captura. Vamos tentar de novo.'); // Recarregue a sessão (open({ token })) e refaça a captura — o componente tira uma foto // nova. O `block_reason` diz se foi o serviço de assinatura, o armazenamento da prova ou o // registro; a conduta é a mesma. Ver Tabela B. break; case 503: // transitório — repita com backoff mostrar('Serviço temporariamente indisponível. Vamos tentar de novo em instantes.'); // Se a mensagem pedir para recarregar a sessão, repetir o mesmo envio não resolve: // chame open({ token }) de novo e refaça a captura. break; default: mostrar('Não foi possível concluir a captura.'); }}Tabela A — Erros no evento error do componente
Seção intitulada “Tabela A — Erros no evento error do componente”Estes são os erros com throw-site real hoje. Cada um chega em e.detail.error.
code |
Nome | Quando ocorre | O que fazer |
|---|---|---|---|
2002 |
BROWSER_NOT_SUPPORTED |
Navegador fora da allowlist. Só Safari mobile ou Chrome mobile passam; desktop, Firefox e Chrome/Edge/Opera no iOS são bloqueados. | Use camera.isUserAgentSupported() antes de abrir e conduza o usuário no seu fluxo quando não for suportado (ex.: orientá-lo a abrir no celular). |
3001 |
STREAM_OPEN_FAILED |
Falha ao abrir a câmera — permissão negada ou câmera em uso por outro app. A câmera é obrigatória. | Peça ao usuário para permitir a câmera e fechar apps que a estejam usando; ofereça repetir. |
5002 |
TOKEN_REQUIRED |
open() foi chamado sem token. |
Bug de integração — passe o token da sessão criada no backend (Passo 1). |
8001 |
LICENSE_KEY_MISSING |
licenseKey não foi informada em useProvviCamera() nem em open(). |
Bug de integração — informe a license key pvv_* do frontend. |
8002 |
LICENSE_INVALID |
Licença rejeitada na validação. O motivo está em error.details.reason. |
Depende do reason: EXPIRED/VOLUME_EXCEEDED → renovar/ampliar; REVOKED/CLIENT_SUSPENDED → contatar a Provvi; ORIGIN_NOT_ALLOWED → domínio não autorizado (ver Passo 6). |
8003 |
LICENSE_NETWORK_ERROR |
Falha de rede ao validar a licença. | Verifique a conexão do usuário e ofereça repetir. |
4001 |
SESSION_FETCH_FAILED |
Não foi possível carregar a sessão. O status HTTP está em error.details.status: 403 sessão ilegível, origem não habilitada, licença recusada ou acesso não validado (o texto de error.message distingue — o componente não repassa block_reason; no último caso a ação é recarregar a página pelo link recebido e tentar de novo, e, se persistir, acionar o suporte — sem recriar a sessão), 404 não encontrada, 410 expirada ou já usada, 429 carregamentos demais, 503 indisponibilidade transitória. |
403 com block_reason web_origin_not_allowed ou web_origin_allowlist_empty: domínio não habilitado para esta licença — fale com a Provvi e não repita a requisição nem recrie sessões em laço (ver Passo 6). 403 de acesso não validado (mensagem Não foi possível validar o acesso…): oriente o usuário a recarregar a página pelo link recebido e tentar de novo; se persistir, acione o suporte — não recrie a sessão em laço. Demais 403, 404, 410 e 429: crie uma nova sessão no backend e reabra o componente. 503: repita open({ token }) em instantes — não gaste uma sessão nova. Detalhe na Tabela B, seção GET /web/sessions/:token. |
4002 |
INGEST_FAILED |
Falha ao enviar a captura. Duas origens: (a) o upload da imagem para o armazenamento temporário falhou — mensagem "Falha de rede no upload da imagem" (sem details.status; o navegador não obteve resposta legível) ou "Upload da imagem falhou (N)" (details.status = N, o status devolvido pelo armazenamento); (b) o servidor recusou a captura — o status HTTP está em error.details.status. |
(a) chame open({ token }) de novo uma vez: o componente recarrega a sessão e recebe uma URL de upload nova (a URL vale 5 minutos; a sessão admite 20 carregamentos no total, contando o primeiro). Se falhar de novo já na primeira captura a partir do seu domínio, a origem pode não estar habilitada — fale com a Provvi, não repita em laço. (b) mapeie details.status pela Tabela B, seção POST /web/ingest. |
| — | reservados (não ocorrem hoje) | 1000, 3002, 5001, 6001, 6002, 6003, 7001 existem em CODES mas não têm throw-site atual. |
Não trate como comportamento; cubra-os apenas no default de telemetria. |
Tabela B — Erros HTTP na captura
Seção intitulada “Tabela B — Erros HTTP na captura”Os corpos abaixo são os literais retornados pela API. O componente chama GET /web/sessions e
POST /web/ingest internamente e os expõe via os códigos 4001/4002 (acima). A criação de
sessão você mesmo faz no backend (Passo 1).
POST /web/sessions — criação da sessão (backend)
Seção intitulada “POST /web/sessions — criação da sessão (backend)”| HTTP | Corpo | O que fazer |
|---|---|---|
400 |
{ "error": "Payload inválido: ..." }, { "error": "license_key ausente ou malformada", "block_reason": "web_license_key_malformed" } ou { "error": "...", "block_reason": "web_reference_id_invalid" } |
Corpo ilegível, license_key fora do formato (pvv_live_/pvv_stag_/pvv_sand_ + 32–33 caracteres) ou reference_id fora do contrato (ASCII, 1–512 bytes, sem espaço nas pontas). Corrija o payload no seu backend — não é transitório. |
401 |
{ "error": "API key inválida ou ausente" } (variações: "...ou revogada", "...apenas pvv_api_* aceito") |
Confira o header x-api-key: pvv_api_... do seu backend. Nunca envie a x-api-key ao frontend. |
403 |
{ "error": "License inválida para esta API key" } |
A license_key do corpo não pertence a esta x-api-key. Use a license emitida para a mesma conta. |
403 |
{ "error": "License e API key pertencem a ambientes diferentes", "block_reason": "web_license_environment_mismatch" } |
A license é sua, mas de outro ambiente (sandbox × produção) que a x-api-key. Use a license e a api key do mesmo ambiente. |
429 |
{ "error": "Limite de criação de sessões atingido..." } |
Reduza a taxa de criação de sessões e aplique backoff. Cada sessão é única — não recrie desnecessariamente. |
500 |
{ "error": "Erro na validação de API Key" } ou { "error": "Erro na validação da license" } |
Dado inconsistente do lado da Provvi ao validar a x-api-key ou a license. Não é transitório: não repita em laço — fale com a Provvi. |
503 |
{ "error": "Serviço temporariamente indisponível, tente novamente", "block_reason": "web_upstream_unavailable" } |
Transitório (um serviço interno da Provvi indisponível; fail-closed). Repita a criação com backoff exponencial. Não trate como falha permanente. |
GET /web/sessions/:token — chamado pelo componente (chega como 4001)
Seção intitulada “GET /web/sessions/:token — chamado pelo componente (chega como 4001)”| HTTP | Corpo | O que fazer |
|---|---|---|
403 |
{ "error": "Sessão inválida — recrie a sessão.", "block_reason": "web_session_corrupt" } |
A sessão não pôde ser lida pelo servidor e não se recupera. Crie uma sessão nova no backend. |
403 |
{ "error": "Origem não autorizada para esta licença — fale com a Provvi para habilitar este domínio.", "block_reason": "web_origin_not_allowed" } ou "web_origin_allowlist_empty" |
O domínio de onde a página foi servida não está habilitado para esta licença (web_origin_allowlist_empty = a licença ainda não tem domínio algum registrado). Não repita a requisição e não recrie sessões em laço: registre o domínio com a Provvi antes de publicar (Passo 6). A sessão continua válida: habilitado o domínio, a mesma sessão pode ser carregada de novo. |
403 |
{ "error": "Sessão inválida — recrie a sessão.", "block_reason": "web_license_missing" } |
A sessão não carrega licença utilizável. Crie uma sessão nova no backend, com a license_key no corpo do create. |
403 |
{ "error": "License inválida — verifique a licença.", "block_reason": "web_license_invalid" } |
A licença amarrada à sessão não é reconhecida. Confirme a license_key usada no create; se ela é a correta, fale com a Provvi — não repita em laço. |
403 |
{ "error": "Não foi possível validar o acesso. Recarregue a página pelo link recebido e tente de novo." } — sem block_reason |
O servidor não validou o acesso: o pedido não se apresentou como um navegador suportado. Pelo <provvi-camera> não é esperado (ele barra o navegador antes, com 2002). Oriente o usuário a recarregar a página pelo link recebido e tentar de novo; se persistir, acione o suporte. Não repita em laço nem recrie a sessão. |
404 |
{ "error": "Sessão não encontrada" } |
Token inválido ou nunca emitido. Crie uma nova sessão no backend. |
410 |
{ "error": "Sessão expirada ou já utilizada" } |
Sessões são single-use e têm validade limitada. Gere uma sessão nova. |
429 |
{ "error": "Limite de tentativas atingido para esta sessão" } |
A página foi recarregada vezes demais. Oriente o usuário a recomeçar com uma sessão nova. |
503 |
{ "error": "Serviço temporariamente indisponível, tente novamente", "block_reason": "web_upstream_unavailable" } ou "web_presign_unavailable" |
Transitório (inclui a emissão da URL de upload). Ofereça repetir em instantes: open({ token }) de novo. |
POST /web/ingest — chamado pelo componente (chega como 4002, details.status)
Seção intitulada “POST /web/ingest — chamado pelo componente (chega como 4002, details.status)”| HTTP | Corpo | O que fazer |
|---|---|---|
400 |
{ "error": "Imagem estática detectada — a câmera deve estar ao vivo durante a captura.", "block_reason": "web_liveness_static" } |
Os frames extras do envio eram iguais entre si — tela parada, vídeo congelado ou imagem injetada. Oriente o usuário a apontar para o objeto real e capturar pela câmera; o componente coleta e envia os frames extras sozinho. |
400 |
{ "error": "Frames de liveness insuficientes — a câmera deve estar ao vivo durante a captura.", "block_reason": "web_liveness_insufficient" } |
O envio trouxe menos de dois frames extras. Pelo <provvi-camera> não ocorre (ele envia dois). Se você monta a própria UI com as primitivas exportadas, envie extra_frame_hashes conforme a Referência da API Web. |
400 |
{ "error": "extra_frame_hashes fora da forma (SHA-256 hex).", "block_reason": "web_liveness_malformed" } |
Algum hash extra não é um SHA-256 em hexadecimal (64 caracteres). Ocorre quando a aplicação monta os frames extras por conta própria; o componente oficial envia dois frames válidos. Não é ação do usuário. |
400 |
{ "error": "extra_frame_hashes acima do teto.", "block_reason": "web_liveness_too_many" } |
Foram enviados mais hashes extras do que o aceito (limite na Referência da API Web). Ocorre quando a aplicação monta os frames extras por conta própria; o componente oficial envia dois frames válidos. |
400 |
{ "error": "label inválido — até 64 bytes, sem caracteres de controle/formato nem <>&\"'`.", "block_reason": "web_label_invalid" } |
O rótulo da foto (overlay.label, assinado como photo_label) está acima de 64 bytes ou usa caracteres não aceitos. Bug de integração: corrija o texto do rótulo — refazer a captura não resolve. |
400 |
{ "error": "Localização inválida." } |
As coordenadas enviadas não são válidas. Com o <provvi-camera> isso não é esperado. Se você monta a própria UI com as primitivas exportadas, envie gps_lat, gps_lon e gps_accuracy como o navegador os reporta, sem transformá-los. Bug de integração: corrija o payload — refazer a captura não resolve. |
400 |
{ "error": "Imagem ausente ou inválida" } |
A imagem enviada não pôde ser aceita (ausente, ilegível ou fora do que o SDK produz). Com o <provvi-camera> isso não é esperado. Se você monta a própria UI com as primitivas exportadas, envie os bytes que captureFrames produz, sem convertê-los nem reprocessá-los. Bug de integração: corrija o payload — refazer a captura não resolve. Se repetir em todas as capturas de um aparelho, fale com a Provvi — não repita em laço. |
400 |
{ "error": "photo_order não corresponde à foto pendente desta sessão.", "block_reason": "web_photo_order_mismatch" } |
O envio não corresponde à foto que a sessão espera. Pelo componente <provvi-camera> isto não ocorre: a sessão web é de uma foto e o componente envia a ordem que ela informa. Se aparecer, o envio não veio do componente — crie uma sessão nova e reabra o componente. |
403 |
{ "error": "..." } — licença revalidada (revogada/suspensa/expirada) |
A licença deixou de ser válida durante a sessão. Trate como licença inválida (ver Tabela A, 8002). |
403 |
{ "error": "Origem não autorizada para esta licença — fale com a Provvi para habilitar este domínio.", "block_reason": "web_origin_not_allowed" } ou "web_origin_allowlist_empty" |
O domínio de onde a página foi servida não está habilitado para esta licença (web_origin_allowlist_empty = a licença ainda não tem domínio algum registrado). Não repita a requisição e não recrie sessões em laço: registre o domínio com a Provvi (Passo 6). A sessão continua válida: habilitado o domínio, a mesma sessão pode ser carregada de novo. |
403 |
{ "error": "Sessão carregada de outra origem — recarregue a sessão.", "block_reason": "web_origin_session_mismatch" } |
A sessão foi carregada em um domínio e a captura enviada de outro. O vínculo é definido no carregamento e não muda: conclua a captura na mesma página em que a sessão foi aberta, ou crie uma sessão nova no backend e abra-a já na página de onde o usuário vai capturar. Repetir o envio da mesma sessão de outra origem devolve o mesmo erro. |
403 |
{ "error": "Relógio do dispositivo fora de sincronia..." } |
Oriente o usuário a verificar a data e a hora do dispositivo e capturar de novo. |
403 |
{ "error": "..." } — nonce ausente/inválido (block_reason: web_nonce_missing, web_nonce_malformed ou web_nonce_replay) |
Oriente o usuário a recarregar a página para renovar a sessão. web_nonce_malformed (valor fora da forma) ocorre quando a aplicação monta a requisição por conta própria; o componente oficial envia o valor recebido ao carregar a sessão. |
403 |
{ "error": "Sessão inválida — recrie a sessão.", "block_reason": "web_session_corrupt" } |
A sessão não pôde ser lida pelo servidor e não se recupera. Crie uma sessão nova no backend e reabra o componente. Se o erro se repetir em todas as capturas, não recrie em laço: fale com a Provvi. |
403 |
{ "error": "Não foi possível validar o acesso. Recarregue a página pelo link recebido e tente de novo." } — sem block_reason |
O servidor não validou o acesso: o envio não se apresentou como um navegador suportado. Pelo <provvi-camera> não é esperado (ele barra o navegador antes, com 2002). Oriente o usuário a recarregar a página pelo link recebido e tentar de novo; se persistir, acione o suporte. Não repita em laço nem recrie a sessão. |
404 |
{ "error": "Sessão não encontrada" } |
Sessão inexistente. Crie uma nova. |
404 |
{ "error": "Imagem não encontrada — refaça o upload" } |
O servidor não achou a imagem enviada (a sessão continua válida). Chame open({ token }) de novo para repetir o upload. |
409 |
{ "error": "Sessão já utilizada" } |
Reuso de sessão já concluída. Gere uma nova. |
409 |
{ "error": "Esta captura não pôde ser processada.", "block_reason": "web_duplicate" } |
Corpo opaco por design (a sub-causa não é revelada). Oriente o usuário a repetir a captura; se persistir, use uma sessão nova. |
410 |
{ "error": "Sessão expirada" } |
Sessão fora de validade. Gere uma nova. |
413 |
{ "error": "Imagem acima do tamanho máximo aceito (... bytes).", "block_reason": "web_asset_too_large", "bytes": ..., "max_asset_bytes": ... } |
A foto excede o limite por imagem. O limite vem no texto da própria mensagem, que o componente entrega em error.message junto de details.status = 413; os campos bytes e max_asset_bytes do corpo não são repassados pelo componente. O <provvi-camera> captura o frame inteiro do stream de vídeo, sem recorte nem redimensionamento, e não expõe opção de resolução (quem monta a própria UI com as primitivas exportadas escolhe o stream). Chame open({ token }) de novo para o usuário repetir a captura; se o erro se repetir num dispositivo, fale com a Provvi. |
422 |
{ "error": "Imagem rejeitada — possível recaptura", "recapture_risk": ... } |
Foto de tela/foto-de-foto detectada. Oriente o usuário a fotografar o objeto físico, sem telas no enquadramento. |
422 |
{ "error": "Não foi possível validar a localização da captura." } |
A localização da captura não pôde ser validada. Oriente o usuário a permitir o acesso à localização e refazer a captura. O nível da verificação de localização é configurado por conta (Passo 6 · Configuração). |
502 |
{ "error": "Serviço de assinatura indisponível — refaça a captura.", "block_reason": "web_signer_unavailable" }, { "error": "A assinatura foi recusada — refaça a captura.", "block_reason": "web_signer_rejected" } ou { "error": "Resposta do serviço de assinatura inválida — refaça a captura.", "block_reason": "web_signer_response_invalid" } |
Falha do lado da Provvi ao assinar: nada foi entregue e a captura não conta como assinada. Com web_signer_rejected nada foi assinado. Com web_signer_unavailable e web_signer_response_invalid a assinatura pode ter ocorrido do lado da Provvi sem chegar ao seu app, e o mesmo frame pode ser recusado como duplicata (409, web_duplicate) por alguns minutos — a nova captura deve ser um frame novo, não o reenvio. Chame open({ token }) de novo para recarregar a sessão e o usuário refaz a captura. Se web_signer_rejected se repetir em todas as capturas de um domínio, não repita em laço: fale com a Provvi. |
502 |
{ "error": "Serviço de armazenamento da prova indisponível — refaça a captura.", "block_reason": "web_prova_store_unavailable" }, { "error": "Falha ao gerar o acesso à prova — refaça a captura.", "block_reason": "web_ingest_presign_failed" }, { "error": "Serviço temporariamente indisponível — refaça a captura.", "block_reason": "web_ingest_presign_config_failed" } ou { "error": "Serviço de registro indisponível — refaça a captura.", "block_reason": "web_hash_store_unavailable" } |
Um serviço interno da Provvi (armazenamento da prova, acesso a ela ou registro anti-replay) indisponível — nada entregue. Recarregue a sessão (open({ token })) e refaça a captura, com backoff. |
502 |
{ "error": "Falha ao ler a imagem enviada — recarregue a sessão e refaça o upload.", "block_reason": "web_raw_read_failed" } |
O upload chegou, mas a leitura da imagem falhou do lado da Provvi. Repetir o mesmo envio não resolve: chame open({ token }) para recarregar a sessão e refaça a captura. |
502 |
{ "error": "Imagem assinada acima do tamanho entregável — reduza a resolução da captura.", "block_reason": "web_signed_payload_too_large" } |
A resposta com o JPEG assinado passaria do tamanho entregável — nada persistido. Não é esperado com o limite atual por imagem (o 413 acima chega antes). Se ocorrer: o <provvi-camera> não expõe opção de resolução — quem monta a própria UI escolhe o stream —, então refaça e fale com a Provvi. |
502 |
{ "error": "Serviço temporariamente indisponível — recarregue a sessão e refaça a captura.", "block_reason": "web_ledger_client_id_unauthoritative" } |
A licença amarrada à sessão não trouxe o dado que registra a captura (configuração do lado da Provvi) — nada assinado. Recarregue a sessão e refaça; se persistir, fale com a Provvi. Não é ação do usuário. |
502 |
{ "error": "Serviço temporariamente indisponível — recarregue a sessão e refaça a captura.", "block_reason": "web_ledger_write_failed" } |
A captura foi assinada e não entregue: o registro probatório não pôde ser gravado. A mesma imagem não é aceita de novo (volta como 409). Chame open({ token }): o componente tira uma foto nova. Ofereça ao usuário refazer a captura; não há como recuperar a anterior. |
502 |
{ "error": "Erro interno ao montar a resposta.", "block_reason": "web_response_serialization_failed" } |
Erro interno da Provvi ao montar a resposta — não é transitório do seu lado. Repita uma vez com open({ token }); se persistir, fale com a Provvi. |
503 |
{ "error": "Serviço temporariamente indisponível — tente novamente.", "block_reason": "web_nonce_store_unavailable" } |
Transitório, do lado da Provvi (fail-closed: a captura não foi assinada). Repita com backoff exponencial. |
503 |
{ "error": "Serviço temporariamente indisponível — recarregue a sessão e tente novamente.", "block_reason": "web_raw_store_unavailable" } |
Transitório, do lado da Provvi (fail-closed). Aqui repetir o mesmo envio não resolve: chame open({ token }) para recarregar a sessão e refaça a captura, com backoff. |
Os contratos HTTP completos (payloads, campos e envelopes) estão na Referência da API Web; a API do componente e os códigos, na Referência do Web SDK.