SignXP Docs
Canais
Esta página é para quem embute o SignXP dentro do próprio produto e o oferece aos clientes dele — um ERP, um CRM, um SaaS vertical. É diferente da integração comum: lá existe uma conta e uma chave; aqui existem dezenas ou centenas, uma por cliente seu, e nenhuma delas passa por uma tela nossa.
Acesso por contrato. A API de canal não é auto-serviço: o segredo é emitido junto do contrato. Se você chegou aqui pela integração comum, a página que você procura é Autenticação.
O modelo
Cada cliente seu vira uma conta completa no SignXP — com licença, quota, marca, chaves e acervo próprios.
Poderia ser diferente: uma conta só para você, com um identificador de cliente em cada documento. Não é, e a razão é prática. Quota, marca do e-mail, domínio de assinatura, segredo de callback e separação do acervo são todos por conta. Numa conta coletiva, seus clientes disputariam a mesma quota, receberiam e-mails com a marca errada, e um veria o contrato do outro no acervo.
Você continua sendo o dono da relação: provisiona, suspende, reativa e acompanha o consumo de todos por esta API. O que muda é que cada cliente tem o próprio compartimento.
Base e autenticação
POST /api/partner/v1/tenants HTTP/1.1
Host: admin.signxp.com.br
Authorization: Bearer pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
O segredo pk_ identifica o canal e vale para todas as rotas desta página.
Ele não é uma chave de API de assinatura: não envia documento nenhum. As
chaves sk_live_/sk_test_ que assinam documentos são de cada conta, e saem no
provisionamento.
Um segredo de canal desativado responde 403 — o segredo está certo, o contrato
é que acabou.
Provisionar uma conta
POST /api/partner/v1/tenants
{
"external_ref": "tenant-4711",
"name": "Solar Prime Engenharia",
"person_type": "company",
"document": "19.131.243/0001-97",
"legal_name": "Solar Prime Engenharia Ltda",
"zip_code": "01310-100",
"street": "Avenida Paulista",
"street_number": "1578",
"city": "São Paulo",
"state": "SP",
"technical_contact_name": "Marina Alves",
"technical_contact_email": "marina@solarprime.com.br",
"plan": "canal-basico",
"embed_origins": ["https://app.solarprime.com.br"]
}
O external_ref é o id do cliente no seu sistema, e é o que torna a chamada
idempotente: repetir com o mesmo valor devolve a conta que já existe em vez de
criar uma segunda. Mande sempre o mesmo valor — um timeout de rede não pode
virar cadastro duplicado.
O plan é opcional; sem ele vale o plano do seu contrato de canal. Sem nenhum
dos dois a conta nasce sem plano e não assina nada — útil se você quer criar
o cadastro antes de vender o módulo.
O cadastro da empresa é obrigatório aqui (ao contrário do que acontece quando a equipe SignXP licencia pela tela). Por API não existe um "depois" em que alguém volta para completar a ficha, e uma empresa sem CNPJ não tem como ser identificada nem faturada no dia em que ela mesma contratar um plano.
A resposta
{
"reference": "solar-prime-engenharia",
"external_ref": "tenant-4711",
"name": "Solar Prime Engenharia",
"status": "active",
"billing_mode": "partner",
"plan": "canal-basico",
"monthly_document_quota": 25,
"keys": {
"live": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"test": "sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"callback_secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Guarde as chaves. Elas existem em claro uma única vez, nesta resposta.
Repetir a chamada devolve 200 com os mesmos dados e sem o bloco keys — um
retry de rede não pode trocar as credenciais de uma conta que já está integrada e
funcionando. Quem perdeu o valor emite outra em
Chaves.
O reference é o identificador da conta no SignXP. Ele volta nos callbacks e é o
caminho de todas as rotas seguintes — guarde-o ao lado do seu external_ref.
Códigos de resposta
| Código | Significado |
|---|---|
201 |
Conta criada. É a única resposta que traz as chaves. |
200 |
Já existia com esse external_ref. Idempotente, sem chaves. |
409 |
O CNPJ já pertence a outra conta do SignXP. |
422 |
Cadastro incompleto ou inválido. |
503 |
Não foi possível concluir — repita a chamada. |
O 409 merece atenção: ele significa que a empresa já é cliente do SignXP,
por conta própria ou por outro canal. A resposta traz o reference dela e um
same_partner dizendo se é sua. Criar de novo daria à mesma empresa duas
licenças, duas quotas e dois pagadores — então a saída é vincular a conta que já
existe, falando com o cliente.
{
"message": "Esta empresa já tem uma conta no SignXP.",
"reference": "solar-prime-engenharia",
"name": "Solar Prime Engenharia",
"same_partner": false
}
O 503 vem com "retryable": true e significa que nada foi criado — a
resposta é binária de propósito: ou existe uma conta pronta com credenciais na
mão, ou não existe nada e repetir recomeça limpo. Nunca entregamos uma chave
antes de a conta estar operante do outro lado, porque uma chave que responde
401 nos primeiros minutos derruba justamente o "ativar com um clique".
Operar uma conta
Todas as rotas abaixo usam o reference devolvido no provisionamento. Conta de
outro canal responde 404 — você nunca enxerga o que não é seu.
GET /api/partner/v1/tenants
GET /api/partner/v1/tenants/{reference}
PATCH /api/partner/v1/tenants/{reference}
POST /api/partner/v1/tenants/{reference}/suspend
POST /api/partner/v1/tenants/{reference}/resume
GET /api/partner/v1/tenants/{reference}/usage
POST /api/partner/v1/tenants/{reference}/keys
POST /api/partner/v1/tenants/{reference}/portal-link
O PATCH aceita name, technical_contact_name, technical_contact_email,
embed_origins e plan. O cadastro fiscal (documento, razão social, endereço)
fica de fora: é a identidade da empresa, e quem a corrige é ela mesma ou a equipe
SignXP.
Suspender corta a emissão de documentos novos e nada mais. O cliente continua acessando o que já assinou, e a URL de verificação de cada documento continua respondendo. Foi decisão de produto: ninguém deveria perder o acervo por ter parado de contratar.
Consumo e o aviso de franquia
GET /api/partner/v1/tenants/{reference}/usage
{
"period": "2026-08",
"documents_used": 20,
"documents_limit": 25,
"documents_remaining": 5,
"percent_used": 80,
"reference": "solar-prime-engenharia",
"external_ref": "tenant-4711"
}
Use o percent_used para avisar o cliente antes de a franquia acabar. Sem
esse aviso, o primeiro sinal de que o limite estourou é uma recusa da API no meio
de uma venda — e a essa altura você já perdeu a chance de oferecer o upgrade com
calma.
Estourar a quota não gera cobrança extra para o canal: gera o bloqueio, e o caminho de saída é o cliente contratar um plano direto no SignXP, pelo link de acesso ao portal.
A fronteira do canal
Quando um cliente seu contrata um plano diretamente com o SignXP, ele passa a
billing_mode: "direct". Ele continua sendo do seu canal — você segue
atualizando contatos, nome e origens de embed, e segue lendo o consumo. O que
muda é o comercial: plan e suspend passam a responder 409.
É proposital. A partir do momento em que a conta paga o SignXP, o plano e o interruptor deixam de ser do canal — nenhum parceiro deve conseguir rebaixar ou desligar uma conta que paga por fora.
Emitir uma chave nova
POST /api/partner/v1/tenants/{reference}/keys
{ "name": "Rotação", "environment": "live" }
A resposta traz o token em claro. A chave anterior continua válida — quem a
revoga é o painel do SignXP ou o próprio cliente. Derrubá-la aqui cortaria a
integração no instante em que a substituta ainda não foi publicada do seu lado.
Enviando documentos
Daqui para a frente é a API de assinatura normal,
autenticada com a chave sk_live_ da conta do cliente. Não existe um envio
"de canal": quota, validação, idempotência e preparo são exatamente os mesmos.
Uma recomendação que vale para quase todo canal: como o PDF sai de um template
seu, as coordenadas dos campos são estáveis. Use placement: "inline" com
coordenadas fixas por template e o cliente nunca vê uma tela de posicionamento —
o documento sai pronto do seu app. O posicionamento
assistido só se justifica quando o layout varia
documento a documento.
Callback de canal
Os callbacks de todas as suas contas chegam numa URL só,
assinados com um segredo só — o do canal, entregue junto do pk_. É a razão
de o canal existir como conceito: sem isso você guardaria um callback_secret
por cliente só para conferir assinatura.
Cada entrega diz de quem é, no corpo e no cabeçalho:
{
"event": "document.awaiting_review",
"id": 128,
"reference": "solar-prime-engenharia",
"external_id": "proposta-4711-0003",
"status": "awaiting_review"
}
X-SignXP-Reference: solar-prime-engenharia
A URL do canal é o padrão, não uma imposição: se um envio trouxer
callback_url próprio, ele ganha, e a entrega vai assinada com o segredo daquela
conta. Um padrão não sobrepõe uma escolha feita na chamada.
A validação da assinatura é idêntica à da integração comum — só a chave muda. Veja os exemplos em Callbacks.
Acesso ao portal sob demanda
Seu cliente vive dentro do seu produto e não deveria precisar de mais um login. Mas três coisas só existem no portal do SignXP: contratar um plano quando a franquia acaba, liberar um documento retido pela validação por IA, e ver o acervo completo.
Para isso existe o link de uso único:
POST /api/partner/v1/tenants/{reference}/portal-link
{
"email": "marina@solarprime.com.br",
"target": "reviews"
}
{
"url": "https://app.signxp.com.br/acesso/xxxxxxxx",
"expires_at": "2026-08-07T14:35:00-03:00",
"target": "reviews"
}
A conta no portal é criada na primeira vez, sem senha e sem convite por e-mail. O link abre a sessão direto na tela pedida.
target |
Leva para |
|---|---|
plans |
Contratar ou trocar de plano. |
reviews |
Fila de validação manual — documentos esperando conferência. |
documents |
Acervo. |
billing |
Faturas e assinatura. |
dashboard |
Painel (padrão). |
Peça o link no clique do usuário, não no cadastro dele. Ele vale cinco minutos, morre no primeiro uso, e emitir um novo invalida o anterior — a URL é a credencial, e uma credencial guardada em banco ou em log é uma credencial vazada.
Um 409 aqui significa que o e-mail informado já pertence a outra conta do
SignXP. Contas nunca trocam de dono por esta rota, nem para o canal que
provisionou o cliente: use outro endereço.
O ciclo que fecha
A combinação que mais importa na prática:
- Seu cliente envia uma proposta pela API, com a chave dele.
- Todos assinam, mas a validação por IA não fecha o veredito de uma imagem.
- Você recebe
document.awaiting_reviewna URL do canal, com oreference. - Seu app mostra "1 documento aguardando sua conferência" para aquele cliente.
- No clique, você pede um
portal-linkcomtarget: "reviews". - Ele confere, aprova, e o documento conclui — e volta para o seu app.
Sem o passo 3 o documento fica parado sem ninguém saber que a espera é de uma pessoa, não de um signatário.