Web SDK — API do componente
Referência do lado cliente do Web SDK — o Web Component <provvi-camera> que você embeda na sua
página. Aqui estão os exports do módulo, os parâmetros de useProvviCamera() e open(), os eventos
e seus payloads, os STATUSES, o objeto overlay e a tabela de códigos de erro.
Para o passo a passo executável (criar sessão, embedar, tratar o ciclo de captura), siga a jornada em Integração Web. Para os contratos HTTP dos endpoints, veja a API Web.
Tier de garantia — leia. O Web SDK é um cliente de captura para deterrência de fraude (fraud deterrence): a foto é assinada server-side com ICP-Brasil A1 sobre os bytes recebidos. O SDK não fornece proveniência com âncora de hardware device-side (GPS e sensores são telemetria, não prova de origem). Para cadeia de prova legal com âncora de hardware, use o Android SDK ou o iOS SDK.
Instalação
Seção intitulada “Instalação”O SDK é distribuído como ES module único via CDN da Provvi (sdk.provvi.com.br), com
Subresource Integrity (SRI). A URL é versionada por hash de conteúdo — quando o SDK atualiza, a
Provvi publica uma nova URL e um novo hash.
<script type="importmap">{ "imports": { "@provvi/web-sdk": "https://sdk.provvi.com.br/provvi-camera.24ac452a5f8c.es.js" }, "integrity": { "https://sdk.provvi.com.br/provvi-camera.24ac452a5f8c.es.js": "sha384-L6aTUccXz27jJ2/DxXzRmY9yWgcYvYClTN36DJjU0tgg/WsVJ6uXaY4DLCcKeAGo" }}</script><script type="module"> import { useProvviCamera, EVENTS, STATUSES, VERSION } from '@provvi/web-sdk';</script>O bundle é imutável (nome versionado) e servido com integrity SRI. HTTPS é obrigatório — a
câmera não abre em origem insegura. Para o walkthrough completo do embed (CSP, CORS, padrão
dev-desktop com QR), veja Passo 2 — Embedar o componente.
Exports do módulo
Seção intitulada “Exports do módulo”O entry point recomendado para integradores são os quatro primeiros. Os demais são exports avançados, para casos que dispensam a UI do componente.
| Export | Tipo | Uso |
|---|---|---|
useProvviCamera(config) |
function | Cria/retorna o singleton <provvi-camera> e o insere no document.body. |
EVENTS |
object | Nomes dos eventos do DOM (OPENED, CAPTURE, UPLOADING, UPLOADED, ERROR, CLOSED). |
STATUSES |
object | Estados de uma captura (NEW, READY, UPLOADING, UPLOADED, ERROR). |
VERSION |
string | Versão do SDK carregado. |
ProvviError + subclasses, CODES |
class / object | Erros tipados (ver Erros). |
validateLicense, fetchSession, postIngest |
function | Avançado — chamadas de baixo nível usadas internamente pelo componente. |
DEFAULT_SESSIONS_URL, DEFAULT_INGEST_URL, DEFAULT_LICENSE_URL |
string | Avançado — endpoints default usados quando você não passa sessionsUrl / ingestUrl / licenseUrl. |
openStream, closeStream, captureFrames, isCameraSupported, acquireGps, acquireHeading, requestCompassPermission, hashBuffer, bufferToBase64 |
function | Avançado — primitivas de câmera, GPS, bússola e cripto, para integrações que montam a própria UI. |
useProvviCamera(config)
Seção intitulada “useProvviCamera(config)”Cria o Web Component e o anexa ao document.body, retornando o elemento <provvi-camera>.
const camera = useProvviCamera({ licenseKey: 'pvv_live_SuaChaveAqui', // obrigatório (pode ficar no frontend, por design) appVersion: 'meuapp-1.0', // opcional, informativo});| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
licenseKey |
string | Sim | Chave de licença do integrador (pvv_live_* / pvv_sand_* / pvv_stag_*). A admissão é feita por domínio (origin-scoping), então ela pode ficar no frontend. |
licenseUrl |
string | Não | Sobrescreve a URL base de validação de licença (avançado / testes). |
appVersion |
string | Não | Versão do seu app, informativa. |
overlay |
object | Não | Máscara-guia default de enquadramento (ver Objeto overlay). |
Singleton por página.
useProvviCamera()retorna sempre a mesma instância dentro da página. Chamadas repetidas ignoram qualquerconfignova, eremove()não reseta o singleton. Configure uma vez; para trocar overlay entre capturas, passeoverlayemopen()ou usesetOverlayDefault().
camera.open(options)
Seção intitulada “camera.open(options)”Inicia o ciclo de captura: valida a licença, carrega a sessão, pede permissões, abre a câmera, adquire GPS e bússola em background, aguarda o toque no botão e faz o upload para assinatura. Em sessões multi-foto, repete automaticamente para as fotos seguintes.
camera.open({ token, // obrigatório — vem do SEU backend customData: { ref: 'VIN-123' }, // opcional — uso apenas seu; NÃO é ecoado nos eventos});| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
token |
string | Sim | Token de sessão criado pelo seu backend. Ausente → erro TOKEN_REQUIRED (5002). |
licenseKey |
string | Não* | Chave de licença. *Obrigatória se você não a definiu em useProvviCamera(); ausente nos dois → LICENSE_KEY_MISSING (8001). Tem precedência sobre a de useProvviCamera(). |
licenseUrl |
string | Não | Sobrescreve a URL base de validação de licença (avançado / testes). |
overlay |
object | Não | Máscara-guia desta captura — tem precedência sobre a de useProvviCamera() (ver Objeto overlay). |
customData |
any | Não | Dado arbitrário para uso seu. Não é ecoado nos eventos (é filtrado da superfície pública). |
sessionsUrl |
string | Não | Sobrescreve a URL base da API de sessões (avançado / testes). |
ingestUrl |
string | Não | Sobrescreve a URL base de ingest (avançado / testes). |
open()é no-op se uma captura já estiver em andamento. Ele emite o resultado por eventos — não retorna a captura. Câmera é obrigatória: falha ao abrir o stream viraSTREAM_OPEN_FAILED(3001). A bússola é opcional (no iOS o SDK pede um gesto; há botão para pular).
Métodos
Seção intitulada “Métodos”| Método | Retorno | Descrição |
|---|---|---|
open(options) |
Promise<void> |
Inicia o ciclo de captura (acima). |
close() |
void |
Aborta o fluxo em andamento, para o stream, esconde a UI e emite closed. |
remove() |
void |
close() + remove o elemento do DOM. Não reseta o singleton do módulo. |
isUserAgentSupported() |
boolean |
true se o navegador atual está na allowlist (ver Suporte de navegador). Use antes de open() para decidir o fallback. |
setOverlayDefault(overlay) |
void |
Define/atualiza o overlay default da instância (o mesmo que useProvviCamera({ overlay })). open({ overlay }) continua tendo precedência. null limpa o default. |
Suporte de navegador
Seção intitulada “Suporte de navegador”O SDK aplica uma allowlist fail-closed: só Safari mobile e Chrome mobile são aceitos.
Firefox (qualquer plataforma), qualquer navegador desktop, e Chrome/Edge/Opera no iOS (CriOS /
EdgiOS / OPiOS) são bloqueados com BROWSER_NOT_SUPPORTED (2002).
Chame camera.isUserAgentSupported() para detectar antes de abrir e, se o navegador não for
suportado, conduza o usuário pela sua própria UX (por exemplo, oriente a abrir a página no celular).
Eventos (EVENTS)
Seção intitulada “Eventos (EVENTS)”O componente emite CustomEvent padrão do DOM (todos com bubbles: true e composed: true).
Registre listeners antes de chamar open().
camera.addEventListener(EVENTS.UPLOADED, (e) => { const { result } = e.detail.capture; // presente só em UPLOADED, quando há record console.log(result?.session_id, result?.authenticated_jpeg_url);});
camera.addEventListener(EVENTS.ERROR, (e) => { console.error(e.detail.error.code, e.detail.error.message);});| Evento | Constante | Quando | e.detail |
|---|---|---|---|
opened |
EVENTS.OPENED |
Câmera e sensores ativos | {} |
capture |
EVENTS.CAPTURE |
Frame capturado, antes do upload | { capture } |
uploading |
EVENTS.UPLOADING |
Upload iniciado | { capture } |
uploaded |
EVENTS.UPLOADED |
Assinatura concluída | { capture } — com capture.result quando há resultado |
error |
EVENTS.ERROR |
Erro em qualquer etapa | { capture, error } — error é um ProvviError; capture pode ser null |
closed |
EVENTS.CLOSED |
Câmera encerrada | {} |
Objeto capture
Seção intitulada “Objeto capture”{ id: 'uuid-v4', // ID da captura (gerado no cliente) status: 'UPLOADED', // um de STATUSES capturedAt: '2026-07-05T12:05:30Z' // ISO 8601 (null antes de capturar) // result: presente apenas no evento `uploaded`, quando há record — abaixo}capture.result (apenas em uploaded)
Seção intitulada “capture.result (apenas em uploaded)”{ session_id: 'sess_abc123', authenticated_jpeg_url: 'https://…', // JPEG com manifesto + ICP-Brasil EMBUTIDOS. PODE SER null complete: true, // true quando todas as fotos da sessão foram concluídas next_photo: null // { order, label } quando complete=false; null quando complete}
authenticated_jpeg_urlpode virnull— quando a política de armazenamento da sua conta não guarda o JPEG (zero-knowledge,NEVER). O manifesto vai embutido no JPEG autenticado (não há URL de manifesto separada no evento); em modoNEVERo componente não entrega um artefato inline — useALWAYSse precisa que a Provvi retenha o JPEG (ver Passo 5 — Resultados). Quando presente, a URL é temporária: baixe e armazene no seu backend se precisar de acesso permanente. Em multi-foto, o SDK avança sozinho usandonext_photo— você não re-chamaopen().
STATUSES
Seção intitulada “STATUSES”Estados possíveis de uma captura, expostos em capture.status:
| Constante | Valor | Significado |
|---|---|---|
NEW |
'NEW' |
Captura criada, ainda não processada. |
READY |
'READY' |
Frame capturado e com hash calculado. |
UPLOADING |
'UPLOADING' |
Upload em andamento. |
UPLOADED |
'UPLOADED' |
Assinatura concluída. |
ERROR |
'ERROR' |
Falha nesta captura. |
Objeto overlay
Seção intitulada “Objeto overlay”A máscara-guia auxilia o enquadramento (forma + escurecimento externo + texto). Configure-a em
useProvviCamera({ overlay }), em setOverlayDefault(), ou por captura em open({ overlay }) (esta
tem precedência). Sem overlay explícito, o SDK usa a guia do perfil da sessão.
camera.open({ token, overlay: { shape: 'oval', // 'rectangle' | 'oval' | 'square' | 'none' color: '#f59e0b', lineWidth: 2.5, dimOutside: 0.45, // 0..1 — escurecimento fora da guia label: 'Centralize o objeto na moldura', },});| Campo | Tipo | Default | Descrição |
|---|---|---|---|
shape |
string | 'square' |
'rectangle' | 'oval' | 'square' | 'none'. 'none' não desenha guia nem escurecimento. |
inset |
object | preset por shape |
{ top, bottom, left, right } em %/vmin (para rectangle/oval). Insets parciais completam com o default do shape. |
width / height |
string | '72vmin' (square) |
Bounding box centralizado — alternativa ao inset. |
color |
string | accent (--provvi-accent) |
Cor da borda. |
lineWidth |
number | 2.5 |
Espessura da borda, em px. |
dimOutside |
number | 0.45 |
Escurecimento fora da guia (0..1). |
label |
string | guia do perfil | Texto de instrução exibido acima da moldura. |
A máscara é guia VISUAL apenas — nunca recorta a imagem. O frame capturado e assinado é sempre o sensor inteiro. Use
shape: 'none'para não desenhar guia alguma. Além dooverlay, você pode ajustar cores via CSS custom properties (--provvi-accent,--provvi-bg,--provvi-surface,--provvi-success,--provvi-danger) — ver Passo 2.
Todo erro chega no evento error (e.detail.error) como instância de ProvviError, com
code (número), message, cause, details (objeto) e toJSON(). Trate por instanceof ou por
error.code.
Falhas de rede/servidor durante o ingest chegam como INGEST_FAILED (4002), e o HTTP original fica
em error.details.status — mapeie esse status para a ação do usuário. A tabela de ações por status
está em Passo 4 — Erros; os contratos HTTP, em API Web.
Classes de erro
Seção intitulada “Classes de erro”| Classe | Código default | Códigos associados |
|---|---|---|
ProvviError |
1000 | Base de todas; código genérico quando nenhum outro se aplica. |
ProvviBrowserError |
2002 | 2002 (ativo). |
ProvviStreamError |
3001 | 3001 ativo; 3002 reservado. |
ProvviAPIError |
4001 | 4001 e 4002 ativos. |
ProvviCaptureError |
5001 | 5002 ativo; 5001 reservado. |
ProvviGeolocationError |
6001 | 6001–6003 reservados (GPS não bloqueia a captura). |
ProvviUploadError |
7001 | 7001 reservado (falha de upload chega como 4002). |
ProvviLicenseError |
8002 | 8001, 8002, 8003 ativos. |
A constante CODES mapeia os nomes aos números. Ativo = existe um ponto de erro que o dispara
hoje; reservado = definido para uso futuro, sem disparo atual (não construa lógica assumindo que
ele vai chegar).
| Constante | Código | Estado | Significado |
|---|---|---|---|
UNKNOWN |
1000 | Reservado (base) | Erro não classificado. |
BROWSER_NOT_SUPPORTED |
2002 | Ativo | Navegador fora da allowlist. |
STREAM_OPEN_FAILED |
3001 | Ativo | Falha ao abrir a câmera. |
STREAM_CAPTURE_FAILED |
3002 | Reservado | — |
SESSION_FETCH_FAILED |
4001 | Ativo | Falha ao carregar a sessão. |
INGEST_FAILED |
4002 | Ativo | Falha no envio/assinatura (inclui falha de upload). details.status traz o HTTP. |
CAPTURE_FAILED |
5001 | Reservado | — |
TOKEN_REQUIRED |
5002 | Ativo | open() chamado sem token. |
GPS_UNAVAILABLE |
6001 | Reservado | GPS não bloqueia a captura (não é disparado). |
GPS_DENIED |
6002 | Reservado | idem. |
GPS_TIMEOUT |
6003 | Reservado | idem. |
UPLOAD_FAILED |
7001 | Reservado | Falha de upload chega como INGEST_FAILED (4002). |
LICENSE_KEY_MISSING |
8001 | Ativo | licenseKey ausente em useProvviCamera() e open(). |
LICENSE_INVALID |
8002 | Ativo | Licença inválida/recusada na validação. |
LICENSE_NETWORK_ERROR |
8003 | Ativo | Erro de rede ao validar a licença. |
O manifesto
Seção intitulada “O manifesto”A prova de autenticidade — manifesto C2PA + assinatura ICP-Brasil A1 — vai embutida no JPEG
autenticado, auto-verificável em verify.provvi.com.br (ou via
c2patool / CAI). Quando sua conta não armazena o JPEG, o manifest_url (sidecar) entrega a mesma
prova. Detalhes das assertions e da verificação em Passo 5 — Resultados.