SignXP Docs
Enviar um documento
POST /api/v1/documents
Cria o documento, posiciona os campos de assinatura nas coordenadas informadas e convida o primeiro signatário. Responde 202 Accepted — o processamento do PDF é assíncrono.
Corpo da requisição
{
"external_id": "contrato-2026-0001",
"source_system": "meu-erp",
"title": "Contrato de Prestação de Serviços",
"callback_url": "https://meu-sistema.com.br/webhooks/signxp",
"download_policy": "all_signed",
"customer": { "reference": "cli-4471", "name": "Acme Indústria Ltda." },
"evidence": { "document": true, "selfie": true },
"pdf_base64": "JVBERi0xLjcK...",
"signers": [
{
"key": "contratante",
"name": "Maria Souza",
"email": "maria@empresa.com.br",
"tax_id": "529.982.247-25",
"role": "SIGNER",
"signing_order": 1
},
{
"key": "contratada",
"name": "João Lima",
"email": "joao@fornecedor.com.br",
"signing_order": 2
}
],
"fields": [
{ "signer_key": "contratante", "type": "SIGNATURE", "page": 3, "x": 12.5, "y": 78 },
{ "signer_key": "contratada", "type": "SIGNATURE", "page": 3, "x": 55, "y": 78 },
{ "signer_key": "contratante", "type": "INITIALS", "page": 1, "x": 80, "y": 90, "width": 14, "height": 7 }
]
}
Campos
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
title |
string | sim | Nome do documento, exibido ao signatário e no painel. |
pdf_base64 |
string | sim* | PDF em base64. *Alternativamente envie pdf como upload multipart (máx. 20 MB). |
signers |
array | sim | Ao menos um signatário. |
fields |
array | sim* | Ao menos um campo, e todo signatário com papel SIGNER precisa de pelo menos um. *Não se aplica (e é recusado) quando placement é interactive ou signature_page. |
external_id |
string | não | O identificador do documento no seu sistema. Deve ser único por licença. |
source_system |
string | não | Nome do sistema de origem, útil quando você integra vários. |
callback_url |
url | não | Recebe as notificações de mudança de status. |
download_policy |
enum | não | all_signed (padrão), anytime ou disabled. Ignorado quando a sua conta desliga a entrega pelo SignXP — veja verificação. |
delivery |
enum | não | Quem entrega o link ao signatário: email (padrão) ou none. Veja "Entregando o link você mesmo", abaixo. |
customer |
objeto | não | O seu cliente, aquele para quem o documento foi emitido. Veja "Separando o acervo por cliente", abaixo. |
evidence.document |
bool | não | Exigir foto da frente e do verso do documento de identidade. |
evidence.selfie |
bool | não | Exigir selfie segurando o documento. |
evidence.geo |
bool | não | Pedir a geolocalização do signatário no momento da assinatura. |
placement |
enum | não | Onde a assinatura entra no PDF. inline (padrão) traz as coordenadas aqui; interactive cria o documento sem campos e devolve uma tela de posicionamento — veja posicionamento assistido; signature_page dispensa campos e coleta as assinaturas numa Página de Assinaturas anexada ao fim do documento. |
Os três campos de evidence são de três estados: true exige, false dispensa e
omitir deixa valer o que a sua licença já traz configurado. Mande-os apenas
quando este documento precisar de algo diferente do padrão.
Signatários
| Campo | Descrição |
|---|---|
key |
Identificador do signatário dentro deste documento. É o que liga o signatário aos campos. |
name |
Nome do signatário, obrigatório. Vai para o Termo de Evidências. |
email |
Opcional. Quando informado, é para lá que o convite vai. Sem ele, o SignXP não notifica essa pessoa — nem convite, nem conclusão, nem recusa — e a entrega do link fica por sua conta. |
tax_id |
CPF ou CNPJ, opcional. Com ou sem máscara. É o que permite à validação por IA conferir se o documento de identidade fotografado pertence a quem você convidou. Enviar um número inválido recusa o envio com 422; se você não o tem, omita o campo — o próprio signatário informa na hora de assinar. |
role |
SIGNER (padrão), APPROVER, VIEWER, CC ou ASSISTANT. Apenas SIGNER assina. |
signing_order |
Ordem da assinatura. Signatários com o mesmo número assinam em paralelo; o número seguinte só é convidado quando o anterior conclui. Sem signing_order, todos são convidados de uma vez. |
Separando o acervo por cliente
Se o seu software emite documentos para vários clientes seus, mande quem é o cliente de cada envio:
{
"customer": {
"reference": "cli-4471",
"name": "Acme Indústria Ltda."
}
}
| Campo | Descrição |
|---|---|
customer.reference |
O identificador do cliente no seu sistema. É por ele que o acervo é agrupado e filtrado. |
customer.name |
Nome do cliente na data do envio. Viaja junto para o histórico não mudar quando o cadastro mudar. |
O objeto inteiro é opcional — a maioria das integrações não separa carteira. A
reference não é conferida contra cadastro nenhum: quem manda o identificador é
você, e basta usar sempre o mesmo valor para o mesmo cliente.
No portal, os documentos passam a ser filtráveis por cliente, e o licenciado pode manter uma carteira com esses mesmos identificadores.
Entregando o link você mesmo
Por padrão, quem convida o signatário somos nós: assim que o documento fica pronto, sai um e-mail com o link de assinatura. Isso atrapalha quando o canal do seu cliente é outro — WhatsApp, SMS, ou a própria tela do seu sistema. A pessoa recebe um e-mail que não vai abrir e o link "de verdade" chega por outro caminho.
Enviando delivery: "none", nenhum e-mail sai e a entrega passa a ser sua:
{
"title": "Contrato de Prestação de Serviços",
"delivery": "none",
"pdf_base64": "JVBERi0xLjcK...",
"signers": [
{ "key": "cliente", "name": "Marina Alves", "email": "marina@empresa.com.br" }
],
"fields": [
{ "signer_key": "cliente", "type": "SIGNATURE", "page": 1, "x": 15, "y": 78 }
]
}
O link de cada signatário sai na consulta de status, no
campo signing_url. Ele não vem na resposta do envio: o PDF ainda está sendo
processado e os links só existem depois disso. Espere o documento sair de draft
e pegue os links:
GET /api/v1/documents/128
{
"id": 128,
"status": "pending",
"delivery": "none",
"signers": [
{
"key": "cliente",
"email": "marina@empresa.com.br",
"status": "pending",
"signing_url": "https://app.signxp.com.br/assinar/9f2c7a1b..."
}
]
}
Alguns pontos que valem saber:
- O
emaildo signatário é opcional — veja a seção seguinte. Quando ele existe e odeliveryénone, o endereço fica registrado no Termo de Evidências e recebe o aviso de conclusão, mas não o convite. - A ordem de assinatura continua valendo. Com
signing_order, o link do segundo signatário só passa a existir quando o primeiro conclui; consulte o status de novo para pegá-lo. - O modo é gravado no documento e aparece como
deliveryna consulta de status. deliverynão tem relação com o ambiente: uma chavesk_test_nunca envia e-mail, com ou sem ele.
O link de assinatura é a credencial. Quem o tem assina no lugar da pessoa. Entregue-o pelo mesmo canal em que você já identifica o seu cliente, e nunca em um lugar público.
Se em vez de entregar o link você quer que a pessoa assine dentro da sua tela, veja assinatura embutida.
Signatário sem e-mail
Nem todo cliente final tem e-mail. Como quem entrega o link é você, o campo é opcional — basta omiti-lo:
{
"signers": [
{ "key": "cliente", "name": "Marina Alves" },
{ "key": "contratante", "name": "Acme Ltda.", "email": "contratos@acme.com.br" }
]
}
Um documento pode misturar os dois casos, como no exemplo: o contratante recebe o convite por e-mail normalmente, e o cliente recebe o link pelo seu canal.
O que muda para quem está sem e-mail:
- Nenhum aviso nosso chega até ele — nem convite, nem conclusão, nem recusa.
- O
signing_urldele sai na consulta de status, como o dos demais. É o único caminho até essa pessoa, então guarde-o ou entregue-o na hora. - No Termo de Evidências, a linha de identificação vem sem o endereço. Mande
o
tax_idsempre que tiver: com o e-mail ausente, ele passa a ser o identificador forte da pessoa — e é o que permite à validação por IA conferir o documento fotografado.
Opcional não quer dizer "aceita qualquer coisa": um endereço malformado continua devolvendo
422. Falhar no envio é melhor do que descobrir semanas depois que o convite nunca saiu.
Posicionando os campos
Cada item de fields diz onde a assinatura será carimbada no PDF.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
signer_key |
string | sim | Precisa corresponder a uma key da lista de signatários. |
page |
inteiro | sim | Número da página, começando em 1. |
x |
número | sim | Distância da borda esquerda, em % da largura da página (0 a 100). |
y |
número | sim | Distância do topo, em % da altura da página (0 a 100). |
width |
número | não | Largura do campo, em % da largura da página. Padrão: 20. |
height |
número | não | Altura do campo, em % da altura da página. Padrão: 8. |
type |
enum | não | SIGNATURE (padrão) ou INITIALS para rúbrica. |
label |
string | não | Rótulo livre exibido no painel do SignXP. Não aparece no documento. |
O sistema de coordenadas
A origem é o canto superior esquerdo da página, e os valores são percentuais — não milímetros nem pontos. Assim o mesmo campo funciona em A4, Carta ou paisagem, sem conversão.
(0,0) (100,0)
+---------------------------------------+
| |
| x --------> |
| +---------------+ ^ |
| y | assinatura | | height |
| | +---------------+ v |
| v <---- width ----> |
| |
+---------------------------------------+
(0,100) (100,100)
Um campo com x: 12.5, y: 78, width: 20, height: 8 começa a 12,5% da esquerda e a 78% do topo, ocupando 20% da largura e 8% da altura da página.
Use o Posicionador de campos. Você abre o PDF, arrasta o retângulo onde a assinatura deve ficar e copia o bloco
fieldspronto. O arquivo é lido pelo próprio navegador e não é enviado a lugar nenhum.
Quem escolhe o lugar é o usuário do seu sistema, e não o seu código? Então não envie
fields: use o posicionamento assistido e o SignXP devolve uma tela pronta para ele clicar onde cada assinatura vai.
Regras de validação
x + widthey + heightnão podem passar de 100. Um campo que vaza da página é recusado com422no ato do envio.- A
pageprecisa existir no PDF. Como o total de páginas só é conhecido ao abrir o arquivo, essa conferência acontece no processamento: se a página não existir, o documento ficafailede ninguém é convidado, com o motivo no campoerrorda consulta de status. - O PDF precisa ser legível pelo nosso motor de selagem. Arquivos corrompidos ou protegidos por senha também resultam em
failed— é melhor falhar no envio do que entregar ao signatário um contrato que não poderá ser selado no final.
Assinando sem posicionar campos
Nem todo documento tem lugar marcado para assinar — e nem todo integrador quer
calcular coordenadas. Enviando placement: "signature_page", o campo fields
deixa de ser exigido (e passa a ser recusado, para você não achar que mandou
coordenadas que serão ignoradas):
{
"title": "Contrato de Prestação de Serviços",
"placement": "signature_page",
"pdf_base64": "JVBERi0xLjQK...",
"signers": [
{ "key": "cliente", "name": "Marina Alves", "email": "marina@empresa.com.br" }
]
}
As páginas do seu PDF chegam intactas ao signatário. Na cópia certificada, o SignXP anexa ao fim do contrato uma Página de Assinaturas com a assinatura desenhada de cada pessoa, nome, e-mail, data, hora e IP — e só depois dela vem o Termo de Evidências.
O que não muda: o signatário continua desenhando a assinatura e passando
pelas mesmas evidências que a sua licença exige. O documento também não passa
por posicionamento — ele já nasce pronto e os convites saem assim que o preparo
termina, sem placement_url na resposta.
Resposta
{
"id": 128,
"status": "draft",
"status_url": "https://api.signxp.com.br/api/v1/documents/128"
}
Guarde o id: ele identifica o documento nas consultas e nos callbacks.
Idempotência
Um POST que sofre timeout pode ter sido processado. Para não criar o documento duas vezes, envie um cabeçalho Idempotency-Key com um valor único por operação:
Idempotency-Key: contrato-2026-0001-envio-1
- Mesma chave + mesmo conteúdo → devolvemos 200 com o documento original, sem criar outro.
- Mesma chave + conteúdo diferente → 409.
- Sem
Idempotency-Key, umexternal_idrepetido também devolve 409, com oiddo documento já existente.