Pular para o conteúdo

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.


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.


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.

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 qualquer config nova, e remove() não reseta o singleton. Configure uma vez; para trocar overlay entre capturas, passe overlay em open() ou use setOverlayDefault().


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 vira STREAM_OPEN_FAILED (3001). A bússola é opcional (no iOS o SDK pede um gesto; há botão para pular).


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.

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).


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 {}
{
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
}
{
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_url pode vir null — 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 modo NEVER o componente não entrega um artefato inline — use ALWAYS se 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 usando next_photo — você não re-chama open().


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.

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 do overlay, 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.

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 60016003 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.

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.


← Integração Web