API e webhooks
Autenticação por token, criação de documentos, consulta de status e eventos por webhook.
- Token com escopo
- POST /api/v1/documents
- Signatários e níveis pela API
- Webhooks assinados por evento
Visão geral da integração
O MySign pode ser operado por outro sistema sem ninguém abrir a tela: um ERP, um sistema de ordens de serviço ou um portal do cliente cria o documento, acompanha a situação e recebe avisos quando algo acontece. A integração tem duas direções:
- Entrada: o sistema parceiro cria o documento, com arquivos e signatários, numa única chamada à API, e pode já enviá-lo para assinatura.
- Saída: o MySign avisa o parceiro, por webhook, a cada acontecimento relevante do documento (enviado, aberto, assinado, concluído, recusado e outros).
Quem chama a API é uma aplicação parceira, cadastrada pelo administrador do MySign. Cada aplicação tem uma chave de API própria, enviada no cabeçalho X-Api-Key de toda requisição. A chave não representa um usuário: o escopo dela é a aplicação. A aplicação opera na empresa a que pertence e, nas consultas, só enxerga os documentos que ela mesma criou. Documento criado por outra aplicação, ou por uma pessoa na tela, não existe para ela.
A API do parceiro vive sob o prefixo api/v3/mysign/integration/, na mesma versão da API interna do PowerP. A administração das aplicações, das inscrições de webhook e das entregas fica em outra superfície, usada pela tela do MySign com a sessão normal do usuário, e nunca com a chave do parceiro.
Três garantias atravessam toda a integração:
- Criação idempotente: repetir a mesma chamada de criação devolve o documento já criado, em vez de criar outro.
- Aviso só por inscrição: nada é enviado ao parceiro sem que a aplicação tenha escolhido para onde e sobre quais eventos.
- Toda entrega registrada: cada aviso, entregue ou não, fica visível para o administrador, com o conteúdo enviado e o resultado.
O parceiro não tem tela no MySign, mas tem leitor: a área de integrações exibe o contrato do webhook (cabeçalhos, receita da assinatura, exemplo de conteúdo e obrigações de quem recebe) para o desenvolvedor do outro lado implementar sem procurar documentação fora do produto.
Aplicações parceiras e chave de API
A aplicação parceira é o cadastro de quem está autorizado a operar por integração. Ela tem nome (único na empresa), descrição, uma unidade padrão e uma pasta padrão para os documentos que criar, e um vencimento opcional da chave. Nasce ativa.
A chave aparece uma vez
A chave de API é gerada pela plataforma no momento do cadastro e mostrada uma única vez, com o aviso de guardá-la na hora. Depois disso, nem o administrador consegue vê-la: a tela mostra só o início e o fim da chave (por exemplo, mys_a1b2c3d4…9f2c), o suficiente para saber qual chave está em qual sistema. A chave completa não vai para log nem para a trilha de auditoria.
Quem fechar a tela sem copiar a chave não tem recuperação: a saída é trocar a chave. A troca é imediata, e a chave anterior deixa de funcionar no mesmo instante, sem período de transição e sem duas chaves válidas em paralelo. Por isso o diálogo de troca exige digitar o nome da aplicação antes de liberar o botão.
Vencimento, inativação e exclusão
- Chave com vencimento passa a ser recusada depois da data, e a recusa informa que ela venceu, não que é inválida. Quem chama já provou ter uma chave que existiu, e dizer o motivo economiza horas de investigação.
- Inativar a aplicação corta o acesso e interrompe os avisos de webhook, sem apagar o histórico de documentos e entregas.
- Excluir a aplicação encerra o acesso; o histórico continua consultável.
Cada uso da chave registra quando e de onde ela foi usada. A grade de aplicações mostra o último uso, que é o que responde "esse parceiro ainda está vivo?".
Quem faz o quê
Há dois níveis de permissão. Quem tem a permissão de ver integrações consulta aplicações, inscrições e entregas, o que basta para investigar um aviso que não chegou. Quem tem a permissão de gerenciar integrações cadastra e altera aplicações, troca chave e segredo, cria inscrições e reenvia entregas. Quem investiga uma falha não precisa poder trocar a chave de produção.
Criar e enviar um documento pela API
O parceiro cria o documento com uma chamada só, mandando de uma vez os dados do documento, os arquivos e os signatários:
POST api/v3/mysign/integration/documents
X-Api-Key: mys_a1b2c3d4_...
Content-Type: application/json
{
"integration_id": "OS-88213",
"unit_id": "...",
"folder_id": "...",
"title": "Contrato de prestação de serviços, OS 88213",
"message": "Segue o contrato para assinatura.",
"signing_mode": "parallel",
"expires_at": "AAAA-MM-DDTHH:MM:SSZ",
"send_immediately": true,
"files": [
{ "name": "contrato.pdf", "content_base64": "JVBERi0xLjQK..." }
],
"signers": [
{
"name": "José da Silva",
"email": "ze@exemplo.com",
"document_number": "52998224725",
"birth_date": "1979-11-02",
"role_id": "...",
"routing_order": 1,
"required_assurance_level": "advanced",
"notification_channel": "email"
}
]
}
Os arquivos vão em base64 dentro do JSON, e não em multipart. É uma escolha deliberada para integrações de sistemas legados, nas quais montar multipart é fonte constante de erro. O teto do corpo é de 20 MB, somando os arquivos decodificados. Não há variante multipart.
Valem as mesmas regras de qualquer documento: pelo menos um arquivo, pelo menos um signatário, só PDF, limites de tamanho e os dados exigidos pelo nível de prova de cada signatário. A unidade vem da requisição ou, na falta, da unidade padrão da aplicação; sem nenhuma das duas, a criação é recusada. A pasta segue a mesma lógica, mas sem pasta o documento é criado mesmo assim. O documento nasce como rascunho, marcado com a aplicação de origem.
Idempotência por integration_id
O campo integration_id é o identificador do documento no sistema do parceiro. Repetir a chamada com o mesmo identificador devolve o documento já criado, com 200 e o cabeçalho X-Idempotent-Replay: true, em vez de criar outro; a criação nova responde 201. A resposta repetida traz o documento como está agora, não como estava na criação. O identificador é único por aplicação: dois parceiros podem numerar os documentos deles do mesmo jeito sem se atrapalhar. Sem integration_id, a criação funciona, mas sem garantia de idempotência.
Criar e enviar na mesma chamada
Com send_immediately: true, o documento é criado e enviado: os arquivos são selados num PDF único e os convites saem aos signatários. Se a selagem falhar (PDF corrompido, protegido por senha, acima do limite), o documento volta a rascunho e o parceiro recebe 201 com status: "draft" e o motivo em seal_error. Não é erro HTTP: o documento existe, e a informação de que a selagem falhou não pode se perder.
Signatários e níveis pela API
Cada item de signers descreve quem assina, em que ordem e com que força de prova. O signatário não precisa ter conta nem cadastro prévio: ele existe por si, com os dados informados na criação.
| Campo | O que é |
|---|---|
name, email | Identificação e canal do convite. |
document_number, birth_date | Documento e data de nascimento, conferidos na assinatura de nível avançado. |
role_id | Papel do signatário (contratante, testemunha...), do catálogo de papéis da empresa. |
routing_order | Posição na ordem de assinatura. |
required_assurance_level | Nível de prova exigido: simple ou advanced. |
notification_channel | Canal do convite. Hoje, email. |
Níveis de prova
O MySign segue os níveis da Lei 14.063/2020, declarados por signatário antes do envio:
- simples (
simple): posse do link do convite. O signatário abre, declara os próprios dados e assina. Uso típico: ciência de comunicado ou recebimento. - avançada (
advanced): posse do link, mais um código de uso único enviado ao signatário, mais a conferência do documento e da data de nascimento contra o que foi informado na criação, mais as evidências de conexão. É o padrão do produto, e por isso o documento e o nascimento do signatário são dados exigidos nesse nível. - qualificada (
qualified): certificado ICP-Brasil do próprio signatário. Está prevista no modelo, mas ainda não está disponível: declarar esse nível é recusado na validação, com erro explícito.
Assinar com método mais fraco que o exigido é recusado; método mais forte é aceito e registrado como tal. O nível alcançado fica gravado na assinatura e impresso na folha de verificação.
Ordem de assinatura
O campo signing_mode do documento decide o que a posição significa. Em parallel, todos são convidados no envio e a posição é só ordem de exibição. Em sequential, a posição é uma raia: só quem está na posição corrente recebe o convite, e quando todos dela assinam a próxima é liberada automaticamente. Vários signatários podem dividir a mesma posição ("os dois diretores assinam antes das testemunhas").
O campo attachment_group_id (grupo de anexos pedidos ao signatário, como foto do documento) é aceito no corpo, mas hoje é ignorado: signatário criado pela API nasce sem grupo de anexos.
Consultar a situação e baixar o documento final
Com a mesma chave, o parceiro acompanha o documento e busca as peças geradas:
| Método e caminho | Uso |
|---|---|
GET api/v3/mysign/integration/documents/{id} | Consultar a situação atual do documento. |
GET api/v3/mysign/integration/documents/by-integration-id/{integrationId} | Consultar pelo identificador do próprio parceiro, sem guardar o id do MySign. |
GET api/v3/mysign/integration/documents/{id}/artifacts/{kind}/url | Obter a URL de download de uma peça. |
POST api/v3/mysign/integration/documents/{id}/cancel | Cancelar o documento, com motivo obrigatório. |
Situações do documento
A situação segue o ciclo de vida de qualquer documento do MySign: draft (em montagem), sent (enviado e selado, ninguém assinou), partially_signed (ao menos um assinou), awaiting_review (todos assinaram, há anexo obrigatório aguardando conferência da empresa), completed (concluído), declined (um signatário recusou), canceled (o emissor encerrou) e expired (o prazo venceu). Os quatro últimos são terminais: nada mais muda neles.
As peças
O PDF nunca vem no corpo da resposta nem no webhook. O parceiro pede a URL da peça e baixa direto do armazenamento; a URL é assinada e vale por pouco tempo (5 minutos), então deve ser pedida na hora do download, nunca guardada. O valor de {kind} indica a peça:
sealed: o PDF único e imutável que os signatários leem e assinam, gerado no envio.verification_sheet: a folha de verificação, gerada na conclusão, com signatários, provas e a trilha inteira.certified: o entregável final, gerado na conclusão: o selado mais a folha de verificação, assinado com o certificado digital da empresa.
Pedir uma peça que ainda não existe (o certified de um documento não concluído, ou o sealed antes de a selagem terminar) responde um conflito explicando que a peça ainda não foi gerada. A certificação é assíncrona: logo depois da conclusão, o selado já está disponível enquanto a peça definitiva é produzida.
Escopo de leitura
Todas essas rotas filtram pela aplicação da chave. Documento de outra aplicação, ou criado por alguém na tela, responde 404, igual a um documento inexistente.
Webhooks: inscrição, eventos e assinatura da entrega
Para receber avisos, a aplicação cria uma inscrição de webhook: uma URL sua, obrigatoriamente https, e o conjunto de eventos que quer receber. Não existe "receber tudo por padrão". Uma aplicação pode ter várias inscrições, com URLs e conjuntos diferentes. Ao criar a inscrição, a plataforma gera um segredo, mostrado uma única vez (e de novo só ao trocá-lo), com o qual cada entrega é assinada. Só há aviso sobre documentos criados por integração: documento criado pela tela não avisa ninguém, porque não há aplicação a avisar.
Os eventos
- Documento:
document_created,document_updated,document_sent,document_sent_to_trash,document_deleted,document_awaiting_review,document_completed,document_declined,document_canceled,document_expired,document_certified. - Signatário:
subscriber_added,subscriber_updated,subscriber_removed,signing_link_sent,subscriber_viewed,subscriber_signed,subscriber_declined. - Anexo:
attachment_uploaded,attachment_verified,attachment_rejected.
Os nomes são os do vocabulário já usado pelos parceiros (subscriber_signed, e não "signer_signed"). Atenção ao comportamento atual: a recusa de um signatário chega como document_declined (não como subscriber_declined), a espera por conferência de anexo chega como document_updated, e envio à lixeira e exclusão não geram aviso.
O que o MySign envia
POST /webhooks/mysign HTTP/1.1
Content-Type: application/json
X-MySign-Event: subscriber_signed
X-MySign-Delivery: 0199c7f2-1a23-7cdb-a104-c6be8477a980
X-MySign-Timestamp: 1786000964
X-MySign-Signature: sha256=9f2c4a...
{
"event": "subscriber_signed",
"occurred_at": "AAAA-MM-DDTHH:MM:SS.ffffffZ",
"document": {
"id": "...",
"integration_id": "OS-88213",
"status": "partially_signed",
"verification_code": "..."
}
}
A assinatura é um HMAC-SHA256 da string {timestamp}.{corpo bruto}, calculado com o segredo da inscrição. O conteúdo é magro de propósito: traz o evento, o instante, o documento (id, identificador do parceiro, situação e código de verificação) e nada de e-mail, telefone, CPF, endereço de rede ou arquivo. Webhook viaja para fora e fica em log de quem recebe; quem precisa do detalhe consulta a API com a chave. O contrato reserva os blocos signer (id, nome, situação) e attachment (rótulo), mas as entregas atuais não os trazem: não dependa deles.
O que se espera do parceiro
- Responder 2xx em menos de 10 segundos; acima disso é timeout e vira nova tentativa.
- Verificar a assinatura antes de processar; sem isso, qualquer um que descubra a URL injeta eventos.
- Recusar entregas com
X-MySign-Timestampde mais de 5 minutos, contra reapresentação. - Tolerar repetição: a entrega é "ao menos uma vez". Se o 200 se perder no caminho, o MySign tenta de novo; o id em
X-MySign-Deliveryé a chave de deduplicação. - Ignorar campos desconhecidos: campo novo não é versão nova da API.
Fila de entregas, reenvio e desativação
Cada aviso vira uma entrega: uma linha com o conteúdo congelado, a situação e o histórico de tentativas. Sucesso e falha são registrados, o que responde a pergunta que todo parceiro faz um dia: "vocês me mandaram o aviso do documento X?".
Situações de uma entrega
- pendente (
pending): aguardando a próxima tentativa. - entregue (
delivered): o parceiro respondeu 2xx. - falhou (
failed): a tentativa deu erro; outra está agendada. - não entregue (
dead): as tentativas se esgotaram. A entrega fica registrada, visível, com o último erro. Não some.
São cinco tentativas: a primeira no ato e as seguintes com intervalos crescentes, de um minuto a algumas horas. A fila é despachada a cada minuto, e réplicas do sistema nunca entregam o mesmo aviso duas vezes. Para cada entrega, a tela mostra o conteúdo enviado, o número de tentativas, o último código HTTP, o último erro e a próxima tentativa agendada, com um atalho para listar só as não entregues.
Reenvio
Qualquer entrega pode ser reenviada manualmente, inclusive as não entregues e as já entregues (parceiro que perdeu o processamento pede reenvio). O reenvio manda exatamente o que o aviso original dizia, e não a situação atual do documento: um aviso de "documento enviado" reenviado depois da conclusão continua sendo o aviso de "documento enviado". A entrega volta a pendente com a contagem de tentativas zerada.
Desativação automática
Uma inscrição que acumula 20 entregas não entregues seguidas é desativada sozinha, com o motivo e a data registrados. Um aviso entregue com sucesso zera essa sequência. A desativação não dispara nenhuma mensagem: quem descobre, descobre pela tela, onde o motivo aparece junto do botão Reativar. Reativar zera a contagem de falhas, e qualquer operação numa inscrição desativada é recusada até que ela seja reativada.
Teste da URL
A inscrição tem um teste: a plataforma envia na hora um evento sintético ping (com event, occurred_at e subscription_id), assinado com o segredo da inscrição, e devolve de forma síncrona o código HTTP, o tempo de resposta e o erro, se houver. É a única entrega que não passa pela fila: não cria linha de entrega nem conta como falha, e o ping não pode ser assinado como evento.
Erros e limites
Os erros seguem o padrão da plataforma: um código textual e o status HTTP correspondente. Os que o parceiro pode receber na API:
| Código | HTTP | Quando |
|---|---|---|
mysign.integration.key_missing.unauthorized | 401 | Sem o cabeçalho X-Api-Key. |
mysign.integration.key_invalid.unauthorized | 401 | Chave desconhecida, malformada, de aplicação inativa ou excluída. |
mysign.integration.key_expired.unauthorized | 401 | Chave vencida. Distinto do inválido, de propósito. |
mysign.integration.unit_required | 422 | Sem unidade na requisição e sem unidade padrão na aplicação. |
mysign.integration.payload_too_large | 422 | Corpo acima de 20 MB (arquivos decodificados). |
mysign.integration.invalid_base64 | 422 | Conteúdo de arquivo que não decodifica. |
mysign.integration.files_required | 422 | Criação sem nenhum arquivo. |
mysign.integration.signers_required | 422 | Criação sem nenhum signatário. |
mysign.integration.document_not_found | 404 | Documento inexistente ou de outra aplicação. |
Erros de regra do documento em si (arquivo que não é PDF, nível de prova sem os dados exigidos, documento que não pode mais ser cancelado) chegam com os códigos do próprio documento, no mesmo formato.
Na administração, os erros mais comuns são nome de aplicação repetido (409), inscrição para uma URL que a aplicação já usa (409), URL sem https (422), inscrição sem nenhum evento (422), operação em inscrição desativada (409) e registro alterado por outra pessoa desde a leitura (412), caso em que a tela recarrega e pede para repetir.
Limites em vigor
- Corpo da criação por API: 20 MB, somando os arquivos decodificados.
- Timeout por tentativa de entrega de webhook: 10 segundos.
- Tentativas por entrega: 5; entregas não entregues seguidas até desativar a inscrição: 20.
- Validade da URL de download de uma peça: 5 minutos.
Esses limites são configuração do servidor, não da empresa: a tela os exibe onde eles explicam um comportamento, mas não os edita. Não há, hoje, limite de requisições por chave de API; a referência adotada para quando houver é de 120 requisições por minuto por chave, e 30 por minuto para a criação de documento, com resposta 429.
