API REST: o SignSession Contract
O Servidor implementa o SignSession Contract, a API que uma aplicação cliente chama para abrir uma Sessão de Assinatura vinculada a um CPF, opcionalmente em nome de uma Empresa, e assinar documentos nela. Esta página trata da autenticação, do ciclo de vida da sessão, de cada operação, do envelope de erro e de qual documento é a especificação do contrato.
Com o Servidor em execução, o contrato legível por máquina é servido em /openapi/v1.json (OpenAPI
3.1) e uma referência navegável em /scalar. Os dois respondem sem credencial. Esta página é o
guia conceitual; o documento publicado é a fonte de verdade para os detalhes de cada campo.
Versão do contrato e caminho base
Toda operação é servida sob /v1, e nada mais responde: uma chamada a uma rota sem o prefixo é
recusada com 404 ENDPOINT_NOT_FOUND. v1 é a versão do contrato, a única à qual um cliente deve
se fixar. O campo version do documento OpenAPI é a versão do build do Servidor e não diz nada sobre
compatibilidade de protocolo.
Autenticação
Toda operação exige o header X-API-Key, com uma chave de API emitida para uma Aplicação
Cliente no console administrativo. Qualquer uma das chaves de uma aplicação autentica toda a
superfície; a chave não restringe nada dentro dela. Chaves ausentes, desconhecidas, revogadas,
expiradas e de aplicações desativadas são todas recusadas da mesma forma, com 401 UNAUTHORIZED.
Trate um sessionId e um signatureId como tokens de portador (bearer tokens) daquilo que
identificam: qualquer chave aceita pode usar uma sessão ou buscar um documento cujo id ela tenha.
Toda resposta, inclusive as de erro, traz um X-Correlation-Id gerado pelo Servidor. Informe-o
ao relatar um problema; ele leva o operador a todo o rastro da requisição.
O ciclo de vida da sessão
POST /v1/sessions (cpf, pin[, cnpj]) ──▶ 201 { sessionId, expiresIn, expiresAt }
│
├──▶ GET /v1/sessions/status?sessionId=… is it still active? (never extends it)
├──▶ GET /v1/certificates/info?sessionId=… which certificate, which verdict
├──▶ POST /v1/signatures (sessionId, document) ──▶ 202 { signatureId, fileName }
├──▶ POST /v1/signatures/batch (sessionId, files[]) ──▶ 202 { results[] }
│ └──▶ GET /v1/signatures/{signatureId}/document ──▶ 200 PDF | 409 | 422
└──▶ POST /v1/sessions/deactivate (sessionId) ──▶ 200
- Crie uma sessão com o CPF e o PIN do titular, e com um CNPJ para assinar em nome de uma Empresa. O Servidor tenta primeiro os Certificados do Cofre guardados para esse CPF. Se nenhum servir, as estações de trabalho que têm um certificado do CPF são solicitadas a provar que têm o PIN em uso ali, e o Servidor confere cada prova contra o PIN que você enviou. O PIN não vai além do Servidor: nenhuma estação de trabalho o recebe, e ele nunca é apresentado ao token. Se nenhuma estação de trabalho tiver esse PIN em cache, o titular recebe uma solicitação no Tray App e esta requisição fica aberta até que ele responda ou a solicitação expire (60 s por padrão). Leve isso em conta no timeout do seu cliente. O certificado que confirmar o PIN é o que fica vinculado à sessão.
- Assine na sessão, um documento por vez ou em lote. A assinatura inteira acontece dentro da requisição e normalmente leva alguns segundos.
- Busque o PDF assinado pelo id da assinatura. É também aí que se lê o resultado de uma assinatura.
- Desative a sessão quando o trabalho terminar, ou deixe a janela de inatividade se esgotar.
Há no máximo uma sessão ativa por CPF, ou por CPF e CNPJ numa sessão em nome de uma Empresa; criar outra para o mesmo par substitui a anterior. Assinar estende a janela de inatividade; consultar o status, não. Uma sessão também termina quando a Franquia de Assinaturas opcional da implantação se esgota.
Uma sessão vinculada a um Certificado do Cofre se apoia em um segredo guardado apenas na memória
do Servidor, então reiniciar o Servidor a encerra: o cliente recebe SESSION_EXPIRED na chamada
seguinte e se recupera criando uma nova sessão com o mesmo PIN. Uma sessão vinculada a uma estação de
trabalho sobrevive ao mesmo reinício.
A partir do Servidor 1.13.0, só estações de trabalho com o Workstation 1.5.0 ou posterior recebem
pedidos de prova de PIN ou solicitações de PIN. Uma máquina com uma versão anterior continua assinando
nas sessões já vinculadas a ela, mas, na criação de sessão, conta como offline: um titular cujas
máquinas tenham todas uma versão anterior recebe 422 WORKSTATION_OFFLINE até que uma delas seja
atualizada. Veja Instalação da estação de trabalho.
Operações
POST /v1/sessions: criar uma Sessão de Assinatura
curl -s https://trustbridge.example.com/v1/sessions \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{ "cpf": "12345678909", "pin": "1234", "sessionDuration": 3600, "email": "holder@example.com" }'
| Campo | ||
|---|---|---|
cpf | obrigatório | Onze dígitos, sem pontuação. Os dígitos verificadores são conferidos, e os onze valores de dígitos repetidos são recusados, com 400 INVALID_REQUEST. Numa sessão em nome de uma Empresa, continua sendo o CPF da pessoa: o responsável pelo e-CNPJ da Empresa. |
pin | obrigatório | O PIN do certificado, qualquer que seja a custódia. Para um Certificado do Cofre, a senha que abre o arquivo dele. |
cnpj | opcional | A Empresa em nome da qual assinar, com o e-CNPJ dela. Catorze caracteres, sem pontuação e em maiúsculas: doze dígitos ou letras (o CNPJ alfanumérico é aceito tanto quanto o numérico) seguidos de dois dígitos verificadores. Os dígitos verificadores são conferidos, e doze repetições de um mesmo caractere são recusadas, com 400 INVALID_REQUEST. Se omitido, a sessão é da pessoa, como antes. |
sessionDuration | opcional | Em segundos. Se omitido, vale a janela padrão do Servidor; acima do máximo, o valor é reduzido ao máximo, não recusado. |
email | opcional | Um endereço alternativo do signatário, usado apenas quando o certificado vinculado não traz nenhum. Sem ele, um certificado assim é recusado no momento da assinatura com CERT_INCOMPLETE_IDENTITY. |
{ "sessionId": "8f3c…", "cpf": "12345678909", "expiresIn": 3600, "expiresAt": "2026-09-21T15:04:05Z" }
expiresIn é sempre a janela efetivamente concedida. Recusas:
404 CERT_NOT_FOUND: nenhum certificado para o CPF (e CNPJ) em lugar nenhum.422 CERT_NOT_ACTIVE: todo certificado do CPF (e CNPJ) tem um veredito diferente de ativo.401 INVALID_PIN: todo certificado candidato foi tentado e nenhum aceitou o PIN.422 PIN_NOT_AVAILABLE: não foi possível fazer nenhuma comparação. Uma solicitação expirou, foi recusada ou não pôde ser exibida; um Certificado do Cofre não pôde ser aberto; ou tentativas recentes demais contra o certificado não conferiram, e ele só volta a ser consultado quando elas saírem da janela.detailsdiz qual.422 WORKSTATION_OFFLINE: toda máquina com um certificado ativo está offline, ou com uma versão do Workstation anterior à 1.5.0.429 TOO_MANY_PIN_ATTEMPTS: bloqueio por CPF.
Sessão em nome de uma Empresa
Envie cnpj junto com cpf para assinar com o e-CNPJ de uma Empresa. O cpf continua sendo o da
pessoa: o responsável por esse e-CNPJ, cujo PIN é este.
curl -s https://trustbridge.example.com/v1/sessions \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d '{ "cpf": "12345678909", "cnpj": "12ABC34501DE35", "pin": "1234" }'
{ "sessionId": "c71d…", "cpf": "12345678909", "cnpj": "12ABC34501DE35", "expiresIn": 3600, "expiresAt": "2026-09-21T15:04:05Z" }
- A correspondência é exata. Com
cnpj, só um e-CNPJ que traga esse CNPJ e esse CPF pode vincular a sessão, nunca o e-CPF da própria pessoa. Sem ele, só o e-CPF da pessoa pode, nunca um e-CNPJ, mesmo que traga o mesmo CPF. - Uma sessão ativa por CPF e CNPJ. A sessão da pessoa e a da Empresa dela convivem, e as de dois responsáveis pela mesma Empresa também. Encerrar uma não afeta a outra.
- O bloqueio por PIN continua por CPF, qualquer que seja o
cnpjenviado, ou nenhum: um mesmo cartão costuma guardar os dois certificados atrás de um só PIN, então as falhas em qualquer um deles contam juntas. - As respostas devolvem o
cnpjsempre que trazem o CPF da sessão: na criação, na desativação e na descrição do certificado. Uma sessão sem ele responde sem nenhum membrocnpj(nem comnull), então uma integração que nunca o envia não vê nada de novo.
GET /v1/sessions/status?sessionId=…: verificar uma sessão
Responde o estado da sessão e quanto tempo ela ainda tem. Um id que não identifica nada ativo ainda
responde 200 com active: false; omitir o id resulta em 400. Pode ser consultado periodicamente
sem risco; nunca estende a janela. Não há como perguntar se um CPF tem uma sessão: um cliente que
perdeu o id cria uma nova sessão.
{ "active": true, "sessionId": "8f3c…", "expiresIn": 3412, "expiresAt": "2026-09-21T15:04:05Z" }
POST /v1/sessions/deactivate: encerrar uma sessão
curl -s https://trustbridge.example.com/v1/sessions/deactivate \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" -d '{ "sessionId": "8f3c…" }'
Encerra a sessão imediatamente e descarta o segredo em que ela se apoiava (o PIN que uma estação de
trabalho tinha em cache para ela, ou a senha que o Servidor guardava para abrir um Certificado do
Cofre). Não é idempotente: sem nada ativo, responde 401 SESSION_EXPIRED. A resposta informa o
CPF lido da sessão (e o cnpj dela, numa sessão em nome de uma Empresa), o id, active: false e
endedAt.
GET /v1/certificates/info?sessionId=…: descrever o certificado vinculado
O certificado ao qual a sessão está vinculada, como a plataforma o registrou pela última vez: cpf
(o titular do certificado, que não precisa ser igual ao CPF da sessão; num e-CNPJ, o CPF do
responsável pelo certificado em nome da Empresa), cnpj (só num e-CNPJ), subjectName, issuer,
serialNumber, notBefore, notAfter e status. Verifique status antes de assinar: um
veredito pode mudar enquanto a sessão está ativa, e só ACTIVE pode assinar. Exige uma sessão ativa;
nunca a estende.
POST /v1/signatures: assinar um documento
Há dois formatos de corpo. JSON, com o documento codificado em base64:
curl -s https://trustbridge.example.com/v1/signatures \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d "{ \"sessionId\": \"8f3c…\", \"document\": \"$(base64 -w0 contract.pdf)\", \"fileName\": \"contract.pdf\" }"
Ou multipart, com um campo sessionId e o PDF como parte de arquivo (o nome do arquivo é tirado da
parte):
curl -s https://trustbridge.example.com/v1/signatures \
-H "X-API-Key: $API_KEY" \
-F "sessionId=8f3c…" -F "document=@contract.pdf"
Qualquer parte de arquivo é lida como o documento, seja qual for o nome do campo. Só uma é assinada:
quando a requisição traz várias, vence document, depois file, depois a primeira que chegou.
Responde 202:
{ "signatureId": "a1b2…", "fileName": "contract.pdf", "status": "PROCESSING", "acceptedAt": "2026-09-21T14:10:00Z" }
fileName é o nome com que o Servidor assinou o documento, que nem sempre é o enviado: o fileName
da requisição, ou o nome da própria parte de arquivo (filename* quando a parte traz um);
document.pdf quando esse nome está ausente ou vazio; e cortado em 260 caracteres, o que pode levar a
extensão junto. Quando uma requisição multipart trouxe várias partes de arquivo, ele indica qual foi
assinada.
Um 202 não significa "deu certo". Depois que o documento chega ao serviço de assinatura, esta
operação responde o id aconteça o que acontecer em seguida, porque o id é o único caminho de volta a
um documento que pode ter sido assinado. O resultado é lido na busca. signatureId é o id do
documento no próprio Lacuna Signer. Só PDFs são assinados (422 UNSUPPORTED_DOCUMENT); um documento
acima de Signing:MaxDocumentBytes (10 MB por padrão, medidos sobre os bytes decodificados) resulta
em 413 DOCUMENT_TOO_LARGE; nenhum documento resulta em 400 INVALID_DOCUMENT; um sessionId
ausente resulta em 400 INVALID_REQUEST.
Duas respostas do serviço de assinatura significam coisas opostas. 422 SIGNER_REJECTED é o serviço
recusando a requisição (em geral o documento, às vezes outra coisa que a requisição indicou; details
diz qual): reenviá-la sem mudança traz a mesma resposta. 502 SIGNER_ERROR é o serviço inacessível,
limitando requisições ou falhando antes de o documento chegar a ele: nada foi assinado, e o mesmo
documento pode ser reenviado quando o serviço voltar.
POST /v1/signatures/batch: assinar vários documentos
Somente multipart/form-data: um campo sessionId e uma parte de arquivo por documento, até
Signing:MaxBatchItems (50 por padrão).
curl -s https://trustbridge.example.com/v1/signatures/batch \
-H "X-API-Key: $API_KEY" \
-F "sessionId=8f3c…" -F "files=@a.pdf" -F "files=@b.pdf" -F "files=@c.pdf"
Responde 202 com um resultado por documento, na ordem em que as partes chegaram:
{
"results": [
{ "fileName": "a.pdf", "signatureId": "a1b2…", "status": "PROCESSING", "error": null },
{ "fileName": "b.pdf", "signatureId": null, "status": "ERROR",
"error": { "code": "DOCUMENT_TOO_LARGE", "message": "…" } },
{ "fileName": "c.pdf", "signatureId": "c3d4…", "status": "PROCESSING", "error": null }
],
"acceptedAt": "2026-09-21T14:10:00Z"
}
Cada documento é independente: um que falhou traz status: "ERROR" e um código do mesmo vocabulário,
enquanto os demais trazem ids. Leia os resultados, não o código de status. Cada item, com falha ou
não, recebe o nome pela mesma regra do fileName da assinatura individual. A chamada inteira só falha
por algo que valha para todos eles: nenhum sessionId (400 INVALID_REQUEST), nenhuma sessão ativa,
um certificado que não pode assinar, mais documentos que o limite (400 INVALID_REQUEST) ou nenhum
(400 INVALID_DOCUMENT). Os documentos são assinados vários de cada vez, até
Signing:SignerConcurrency, e a chamada inteira é aguardada, então um lote grande leva o tempo de
assinar todos os documentos dele. Um lote conta como uma chamada para o throttle e para a
Franquia de Assinaturas.
GET /v1/signatures/{signatureId}/document: buscar o documento assinado
curl -s https://trustbridge.example.com/v1/signatures/a1b2…/document \
-H "X-API-Key: $API_KEY" -o signed.pdf -w '%{http_code}\n'
| Status | Significado |
|---|---|
200 | O PDF assinado, como corpo da resposta. |
409 DOCUMENT_NOT_READY | Ainda está sendo assinado. Pergunte de novo. |
422 DOCUMENT_UNAVAILABLE | Terminou sem versão assinada: details diz Refused, Canceled ou Expired. Não há o que esperar. |
404 DOCUMENT_NOT_FOUND | Nenhum documento tem esse id, inclusive um que o serviço de assinatura não guarda. |
502 SIGNER_ERROR | Não foi possível consultar o serviço de assinatura (inacessível, limitando requisições ou com falha); o documento não foi afetado. Pergunte de novo em instantes. |
O Servidor não armazena nada, então o tempo durante o qual um documento pode ser buscado é a retenção
do Lacuna Signer. Qualquer chave de API válida pode buscar qualquer documento cujo id conheça,
inclusive um criado por outra Aplicação Cliente. Isso é o contrato, e não um descuido: trate um
signatureId como um token de portador do documento dele.
O envelope de erro
Todo erro chega em um único envelope. code é uma string, não um conjunto fechado: trate um código
desconhecido como uma falha inesperada, e não como um erro de parsing. Decida com base em code,
nunca em message.
{ "error": { "code": "CERT_NOT_ACTIVE", "message": "…", "details": "…" } }
"O CPF", abaixo, significa o CPF e o CNPJ juntos numa sessão em nome de uma Empresa. O bloqueio por PIN é a única exceção, e continua por CPF.
| Código | HTTP | Significado |
|---|---|---|
INVALID_REQUEST | 400, 415 | Requisição malformada, ou um corpo em um media type que a operação não lê. details diz o que estava errado: por exemplo, um sessionId ausente, ou um CPF ou CNPJ com dígitos verificadores errados. |
INVALID_DOCUMENT | 400 | Nenhum documento a assinar chegou, ou ele estava vazio. |
UNAUTHORIZED | 401 | A chave de API não foi aceita. |
SESSION_EXPIRED | 401 | Nenhuma Sessão de Assinatura ativa tem o sessionId informado: expirada, desativada, substituída, esgotada ou interrompida. Crie uma nova sessão. |
INVALID_PIN | 401 | O PIN não abriu nenhum Certificado do Cofre do CPF e é diferente do PIN em uso em todas as estações de trabalho que têm um certificado dele: todo candidato foi tentado, e nenhum conferiu. |
CERT_NOT_FOUND | 404 | Na criação: nenhum certificado para o CPF em lugar nenhum, nem no cofre nem em uma estação de trabalho. Na leitura ou na assinatura: o certificado vinculado não está mais disponível. |
DOCUMENT_NOT_FOUND | 404 | Nenhum documento tem esse id de assinatura. |
ENDPOINT_NOT_FOUND | 404 | Nenhuma operação responde a esse método e caminho. Verifique o prefixo /v1. |
DOCUMENT_NOT_READY | 409 | Ainda está sendo assinado. Vale perguntar de novo. |
DOCUMENT_TOO_LARGE | 413 | O documento ou o corpo da requisição excede o limite do Servidor; details informa o tamanho e o limite. |
CERT_NOT_ACTIVE | 422 | Todo certificado do CPF, ou o certificado vinculado, tem um veredito diferente de ativo (EXPIRED, REVOKED, UNTRUSTED, STALE). |
DOCUMENT_UNAVAILABLE | 422 | O documento terminou sem versão assinada: recusado, cancelado ou expirado. Não há o que esperar. |
PIN_NOT_AVAILABLE | 422 | Não foi possível fazer nenhuma comparação: uma solicitação expirou, foi recusada ou não pôde ser exibida, um Certificado do Cofre não pôde ser aberto, ou tentativas recentes demais contra o certificado não conferiram. details diz qual. |
WORKSTATION_OFFLINE | 422 | Todo certificado ativo do CPF está em uma estação de trabalho, e todas elas estão offline (depois da tolerância de reconexão, em uma assinatura). |
CERT_DATA_UNAVAILABLE | 422 | Os dados do próprio certificado, necessários para assinar, não estão guardados para ele. |
CERT_INCOMPLETE_IDENTITY | 422 | O certificado não identifica o titular o suficiente para assinar; details indica o campo que falta. Um endereço de e-mail é o único campo que o email da sessão pode suprir. |
UNSUPPORTED_DOCUMENT | 422 | Não é um PDF. |
SIGNER_REJECTED | 422 | O serviço de assinatura recusou a requisição, em geral o próprio documento; details traz a explicação dele e diz qual. Repetir sem mudança dá o mesmo resultado. |
SIGN_TIMEOUT | 422 | A assinatura não terminou dentro do tempo dado a uma requisição (60 s por padrão); nada foi assinado. |
SERVER_BUSY | 429 | O Servidor está executando tantas chamadas do contrato quanto aceita e a fila dele está cheia. Nada na requisição foi recusado: tente de novo com um backoff próprio, com jitter. Nenhum Retry-After é enviado. |
TOO_MANY_PIN_ATTEMPTS | 429 | O bloqueio por PINs incorretos do CPF está em vigor, qualquer que seja o cnpj enviado com o CPF, ou nenhum. Refere-se a um CPF, em todas as chaves de API; tentar de novo piora a situação. Some à medida que as falhas mais antigas saem da janela (15 min por padrão). |
INTERNAL_ERROR | 500 | Não foi possível concluir a requisição; é seguro tentar de novo. |
SIGNER_ERROR | 502 | Não foi possível consultar o serviço de assinatura: inacessível, limitando requisições ou respondendo com uma falha própria. Em uma assinatura, só chega antes de o documento ter chegado ao serviço, então nada foi assinado; em uma busca, não diz nada sobre o documento. |
Dois 429 diferentes. SERVER_BUSY diz respeito ao Servidor naquele momento e se resolve sozinho;
TOO_MANY_PIN_ATTEMPTS diz respeito ao certificado de uma pessoa e não se resolve com novas
tentativas. Um cliente que decide só pelo status vai tratá-los da mesma forma, e é por isso que são
códigos separados.
A especificação
A descrição normativa do contrato é a especificação de referência do SignSession
(SignSession — Documentação de referência), escrita em português a partir da implementação deste
Servidor e adotada pelo autor da especificação do contrato no lugar do documento de integração
anterior. Peça uma cópia à Lacuna Software. O documento OpenAPI que um Servidor em execução serve em
/openapi/v1.json é gerado a partir do próprio Servidor e mantido idêntico ao que ele responde. Se os
dois discordarem, um deles está errado: informe a diferença em vez de supor que ela é intencional.
Os códigos que o documento OpenAPI marca como TrustBridge extension são os que a especificação original não definia. A especificação atual os traz com a mesma marca; eles fazem parte do contrato como qualquer outro.
Vindo do documento de integração anterior
Um cliente escrito com base no documento de integração anterior, ou na outra implementação do contrato (o CertSession), encontra estas respostas. Todas elas agora são o contrato, e duas são silenciosas: produzem um comportamento diferente sem nenhum erro que o indique.
| O que um cliente encontra | O que fazer |
|---|---|
Toda rota tem o prefixo /v1. Uma rota sem o prefixo responde 404 ENDPOINT_NOT_FOUND. | Use o prefixo em todas as chamadas. Não há header nem media type de versão. |
Uma sessão é identificada pelo sessionId, e não por um CPF. Só a criação recebe um CPF; status, informações do certificado, assinatura e desativação recebem o id. | Guarde o sessionId. Nenhuma chamada o recupera a partir de um CPF. |
expiresIn nunca é nulo. Um sessionDuration omitido concede a janela padrão, e não uma ilimitada. | Silencioso. Leia expiresIn e expiresAt na resposta, em vez de supor a janela que você pediu. |
| Assinar estende a sessão em vez de encerrá-la, a menos que a implantação tenha definido uma Franquia de Assinaturas (uma franquia de 1 dá sessões de uso único). | Silencioso. Um cliente que cria uma sessão por documento continua funcionando, ao custo de mais uma confirmação de PIN a cada vez. Para encerrar a sessão junto com o documento, chame POST /v1/sessions/deactivate. |
Um cpf precisa ser um CPF real: dígitos verificadores conferidos, valores de dígitos repetidos recusados. | 400 INVALID_REQUEST. Valide os dígitos verificadores também no seu formulário; o pattern do schema (^[0-9]{11}$) não consegue expressá-los. |
Uma chamada de assinatura sem sessionId é malformada, individual ou em lote. | 400 INVALID_REQUEST: corrija a requisição. Um 401 SESSION_EXPIRED significa criar uma sessão e tentar de novo. |
| Os certificados são validados quanto à cadeia e à revogação, não só quanto à expiração. | CERT_NOT_ACTIVE com UNTRUSTED, REVOKED ou STALE onde uma verificação só de expiração assinaria. |
| O Servidor descarta carga. | 429 SERVER_BUSY. Tente de novo após um backoff próprio; usar lotes reduz a frequência com que isso acontece. |
| O resultado é lido na busca. Não há webhook a registrar. | Consulte GET /v1/signatures/{signatureId}/document até receber 200 ou 422. |
Qualquer chave de API válida busca qualquer documento cujo signatureId conheça. | Trate o id como um token de portador: não o registre em log nem o entregue a quem não deve ter o documento. |
Como escrever um cliente robusto
- Guarde o
sessionId. Nenhuma chamada o recupera a partir de um CPF. - Esteja pronto para
SESSION_EXPIREDem qualquer chamada e recupere-se criando uma nova sessão. Você não tem como saber se uma implantação definiu uma Franquia de Assinaturas, nem deveria. - Leia o resultado na busca. Um
202diz que o documento foi aceito, não assinado. Consulte o endpoint do documento periodicamente enquanto receber409; pare em200ou422. - Defina um timeout generoso em
POST /v1/sessions. Uma criação que vai para uma solicitação no Tray aguarda uma pessoa, até o timeout da solicitação mais alguns segundos. - Decida com base em
error.codee trate os dois 429 de forma diferente. Não reenvie sem mudança um documento recusado comSIGNER_REJECTED; reenvie um que recebeuSIGNER_ERROR. - Use lotes quando tiver muitos documentos. Uma chamada, uma vaga no throttle, um débito na franquia.
- Envie
emailse algum certificado com que você assina puder não trazer endereço. - Envie
cnpjsó para assinar em nome de uma Empresa. Uma sessão sem ele nunca se vincula a um e-CNPJ, e uma com ele nunca se vincula ao e-CPF da pessoa.
Testando o contrato manualmente
A Lacuna Software pode fornecer uma coleção do Postman com o contrato como este Servidor o implementa,
com um environment que traz um pequeno PDF codificado em base64 e um cnpj de exemplo. Importe os
dois, cole em apiKey uma chave de API emitida na tela Aplicações Cliente e execute as
requisições em ordem: crie uma sessão (acompanhe a solicitação no Tray App se não houver PIN em
cache), assine um documento e busque-o. Uma segunda requisição de criação faz o mesmo para uma
Empresa, enviando o cnpj do environment. A coleção grava sessionId e signatureId no
environment, então não é preciso colar nada entre um passo e outro. Quando a coleção e o
/openapi/v1.json publicado pelo Servidor discordarem, vale o documento publicado.