SignXP Docs
Assinatura dentro do seu sistema
Por padrão, o signatário recebe um link e assina numa página nossa. Quando o seu software já é a tela em que o cliente final está, mandá-lo para fora é uma quebra no meio do fluxo — e cada saída é uma chance de a pessoa não voltar.
Há três formas de resolver isso, da mais barata para a mais trabalhosa:
| Quem faz a tela | O que você escreve | Evidência | |
|---|---|---|---|
| Domínio próprio | nós | nada | nossa responsabilidade |
| Assinador embutido | nós, dentro da sua tela | um <script> |
nossa responsabilidade |
| Fluxo próprio | você | a interface inteira | depende do seu fluxo |
O assinador embutido é o caminho recomendado: o cliente não sai do seu sistema, a marca em volta é a sua, e o fluxo de assinatura continua sendo nosso — correções e etapas novas chegam sozinhas, sem você republicar nada.
Assinador embutido
Carregue o widget e abra a signing_url do signatário numa janela modal:
<script src="https://app.signxp.com.br/embed/signer.js"></script>
<script>
SignXP.openSigner({
url: signingUrl,
onSigned: function () {
// Assinou. Atualize a sua tela.
},
onRejected: function () {
// Recusou. O documento foi encerrado.
},
onCancel: function () {
// Fechou sem decidir. O link continua valendo.
}
});
</script>
Para embutir sem modal, dentro de um elemento seu:
SignXP.mountSigner({
url: signingUrl,
container: '#area-de-assinatura',
onSigned: function () { /* ... */ }
});
| Método | Parâmetros |
|---|---|
SignXP.openSigner |
url (obrigatório), showDocument, onSigned, onRejected, onCancel. Devolve { close() }. |
SignXP.mountSigner |
url e container (obrigatórios), showDocument, onSigned, onRejected. Devolve { destroy() }. |
O endereço
https://app.signxp.com.br/embed/signer.jsé fixo e versionado por nós — não copie o arquivo para o seu servidor, ou deixará de receber correções. Ele convive com opositioner.js: os dois penduram métodos no mesmo objetoSignXP.
Quando você já mostra o documento
Por padrão o assinador abre numa etapa de revisão, com o PDF dentro dele. Se a sua tela já exibe o documento — num visualizador ao lado, numa aba própria, num painel do seu sistema —, essa etapa vira uma segunda cópia do mesmo PDF e empurra a assinatura para baixo. Desligue-a:
SignXP.mountSigner({
url: signingUrl,
container: '#area-de-assinatura',
showDocument: false,
onSigned: function () { /* ... */ }
});
O que muda:
- a etapa de revisão sai do fluxo, e o assinador abre direto na etapa seguinte (consentimento, localização, fotos — o que a sua licença coletar);
- o PDF não é baixado pelo iframe, então a tela carrega mais leve;
- na hora de assinar continua havendo um link discreto para abrir o documento. Ele fica: quem assina precisa poder conferir o que assina, e o seu visualizador pode estar fora do campo de visão naquele momento.
Só vale embutido. Se o signatário abrir a
signing_urldireto no navegador, a etapa de revisão volta — fora do seu sistema não existe outra tela mostrando o documento, e assinar sem ele à vista não é opção.
De onde sai a signing_url
Da consulta de status, no campo signing_url de cada
signatário.
Se a assinatura vai acontecer na sua tela, o nosso convite por e-mail só atrapalha — a pessoa recebe um link que leva para fora do seu sistema. Duas formas de calá-lo, as duas descritas em enviar um documento:
delivery: "none"no envio, que suprime o convite de todos os signatários daquele documento;- omitir o
emaildo signatário, quando ele simplesmente não tem um.
Autorize a sua origem
Por padrão a página pode ser embutida em qualquer site: o segredo é o token da URL. Para restringir — recomendado —, cadastre as origens autorizadas da sua licença em Configurações, no portal. O navegador passa a recusar o iframe em qualquer outro lugar.
Uma origem por linha, com esquema:
https://sistema.meu-erp.com.br
https://app.meu-erp.com.br
Isso não exige apontar domínio nenhum para nós: autorizar uma origem e ter um domínio de white-label são coisas separadas.
Câmera e geolocalização
Quando a sua licença coleta foto do documento, selfie ou localização, o navegador
precisa que a página de fora delegue essas permissões ao iframe. O widget já
faz isso (allow="camera; geolocation"). O que você precisa garantir é que a sua
própria página seja servida em HTTPS — sem isso o navegador bloqueia a câmera
antes de chegar em nós.
Quando o cliente está no computador
Se a licença coleta imagens e a pessoa abriu no desktop, o fluxo mostra um QR
Code para ela continuar no celular, e a tela embutida fica aguardando. O
onSigned dispara quando ela conclui pelo telefone — você não precisa tratar o
handoff.
Fluxo próprio, sobre a API de sessão
Se você quer desenhar a experiência inteira, a mesma API que a nossa página
consome está aberta para você. A autenticação é o próprio signing_token da
URL — não use a sua chave de API aqui: essas chamadas saem do navegador do
signatário.
GET /api/signing/{token} estado inicial da sessão
GET /api/signing/{token}/status o que já foi coletado (usado no handoff)
GET /api/signing/{token}/document redireciona para o PDF
POST /api/signing/{token}/consent registra o aceite do termo
POST /api/signing/{token}/tax-id CPF/CNPJ autodeclarado
POST /api/signing/{token}/geo latitude, longitude, accuracy, denied
POST /api/signing/{token}/photo kind + image (multipart)
POST /api/signing/{token}/validate-image pede o veredito da IA para uma imagem
POST /api/signing/{token}/signature image + type (drawn|typed)
POST /api/signing/{token}/initials image + type (drawn|typed)
POST /api/signing/{token}/progress salva a etapa, para retomar depois
POST /api/signing/{token}/complete conclui a assinatura
POST /api/signing/{token}/reject recusa, com motivo opcional
O GET inicial devolve tudo o que a tela precisa decidir:
{
"document": { "title": "Contrato", "is_test": false, "verification_url": "...", "download_enabled": true },
"signer": { "name": "Maria Souza", "email": "maria@empresa.com.br", "tax_id": "529.982.247-25", "status": "pending" },
"brand": { "name": "Acme", "color": "#00a3ff", "logo": "..." },
"state": "open",
"collect": { "document": true, "selfie": true, "geo": true, "initials": false, "tax_id": false },
"consent": { "required": true, "version": "1", "text": "Declaro, para os devidos fins..." },
"progress": { "current_step": "geo", "photos": {}, "has_signature": false, "has_initials": false }
}
O que merece atenção:
collectmanda. Ele já combina o que o documento pediu com o que a licença contratou. Coletar menos do que ele diz enfraquece a prova; coletar mais não adianta, porque o motor só guarda o que conhece.statediferente deopensignifica que não é a vez desta pessoa, que ela já assinou, ou que o documento acabou. Pare o fluxo e mostre o motivo.- O texto do consentimento é o do
consent.text, com a versão que vem junto. Escrever o seu próprio texto invalida o casamento entre o que a pessoa leu e o que o Termo de Evidências afirma que ela leu. progress.current_stepé o que permite retomar de onde parou. Salvá-lo é opcional; não salvar faz a pessoa recomeçar a cada recarga.- A ordem é sua, o
completeé o fim. Só chame quando tiver coletado o que ocollectpediu — depois dele o documento segue para selagem.
Para o navegador poder falar com o motor a partir do seu domínio, cadastre a sua origem em Configurações → origens autorizadas, como no widget. Sem isso o navegador barra as chamadas por CORS.
A evidência passa a depender do seu fluxo. O motor continua validando tudo do lado dele e é a única fonte da prova, mas quem garante que a pessoa passou por cada etapa é a sua tela. É o preço de desenhar a experiência inteira — e a razão de o widget existir.