Antes de começar
A API do Ideia Signer permite colocar documentos em assinatura a partir do seu sistema, acompanhar quem já assinou e baixar o arquivo assinado.
- Endereço da API:
https://app.ideiasigner.com.br - Autenticação: cabeçalho
X-Api-Key: sua-app|<chave>em todas as chamadas - Formato: JSON (o envio de arquivo usa
multipart/form-data) - Referência completa: todas as 45 operações, com parâmetros e modelos
A chave de acesso
Toda chave está ligada a uma organização do Ideia Signer: ela só enxerga e cria documentos daquela organização. Para receber a sua, fale com o nosso suporte.
X-Api-Key: sua-app|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Atenção: a chave é um segredo. Guarde-a no seu servidor e nunca a coloque em código que roda no navegador ou no celular do usuário.
Postman e Insomnia
Na seção Arquivos para baixar estão as coleções prontas, com todas as operações e uma pasta "00. Fluxo de assinatura (na ordem)" com o caminho completo, passo a passo.
- Postman: importe a coleção e o ambiente, escolha o ambiente "Ideia Signer — Produção" e
preencha só a variável
apiKey. Os passos 1, 2 e 4 já guardamuploadId,documentIdeactionUrlsozinhos para o passo seguinte. - Insomnia: importe o arquivo, abra o Base Environment (
Ctrl/Cmd + E) e preenchaapiKey. O Insomnia não roda os scripts de captura: copie oiddo passo 1 parauploadIde odocumentIddo passo 2 paradocumentId.
A sequência em uma tela
[seu sistema] [Ideia Signer]
arquivo .pdf
│
│ (1) POST /api/uploads (multipart)
├──────────────────────────────────────────────►
│ ◄────────────────────────── { id, name, contentType, location }
│ │
│ guarde esse "id" = uploadId │
│ │
│ (2) POST /api/documents (JSON: files[] + flowActions[])
├──────────────────────────────────────────────►
│ ◄────────────────────────── [ { uploadId, documentId } ]
│ │
│ ┌─────────────┴──────────────┐
│ │ o Signer envia o e-mail de │
│ │ "ação pendente" para os │
│ │ participantes do passo 1 │
│ └────────────────────────────┘
│
│ (3) (opcional) POST /api/documents/{id}/action-url
├──────────────────────────────────────────────► ← link direto de assinatura
│ ◄────────────────────────── { url, embedUrl } (redirecionar ou iframe)
│
│ (4) webhook DocumentConcluded (ou GET .../signatures-details)
│ ◄──────────────────────────────────────────────
│
│ (5) GET /api/documents/{id}/content?type=Signatures
├──────────────────────────────────────────────►
│ ◄────────────────────────── PDF assinado (binário)
Os dois passos obrigatórios são o 1 e o 2. O resto é acompanhar e retirar o resultado. A regra
que amarra os dois: o id devolvido pelo upload é exatamente o que vai em files[].id na criação
do documento.
Passo 1: enviar o arquivo
POST /api/uploads envia o arquivo e devolve um
identificador temporário. Nada é criado ainda: o upload é só um arquivo guardado no servidor.
curl -X POST "https://app.ideiasigner.com.br/api/uploads" \
-H "X-Api-Key: $IDEIA_SIGNER_KEY" \
-F "file=@./Contrato.pdf"
Resposta (FileModel):
{
"id": "0429c723-a66d-4e55-a912-ff636d1b2745",
"name": "Contrato.pdf",
"contentType": "application/pdf",
"location": "https://app.ideiasigner.com.br/..."
}
| Campo | Para que serve no passo 2 |
|---|---|
id |
vira files[].id: é o elo entre os dois passos |
name |
vira files[].name (nome original do arquivo) |
contentType |
vira files[].contentType (define PAdES para PDF e CAdES para o resto) |
location |
endereço de pré-visualização, útil para mostrar o arquivo antes de confirmar |
Alternativa: arquivo em Base64
POST /api/uploads/bytes dá o mesmo
resultado, mas o arquivo vai em Base64 dentro de um JSON. É mais simples quando o seu sistema já tem
os bytes em memória.
curl -X POST "https://app.ideiasigner.com.br/api/uploads/bytes" \
-H "X-Api-Key: $IDEIA_SIGNER_KEY" \
-H "Content-Type: application/json" \
-d '{"bytes":"JVBERi0xLjQK..."}'
Devolve { "id", "size", "digest" }. O digest é o MD5 do que chegou, para você conferir a
integridade antes de criar o documento.
Um upload por arquivo. Se o documento tem 3 anexos, são 4 uploads (1 principal + 3).
Passo 2: criar o documento
POST /api/documents cria o documento e
o fluxo de assinatura na mesma chamada.
curl -X POST "https://app.ideiasigner.com.br/api/documents" \
-H "X-Api-Key: $IDEIA_SIGNER_KEY" \
-H "Content-Type: application/json" \
-d '{
"files": [{
"displayName": "Contrato de prestação de serviços",
"id": "0429c723-a66d-4e55-a912-ff636d1b2745",
"name": "Contrato.pdf",
"contentType": "application/pdf"
}],
"description": "Contrato anual — renovação",
"flowActions": [{
"type": "Signer",
"step": 1,
"title": "Contratante",
"user": {
"name": "João da Silva",
"identifierType": "Cpf",
"identifier": "81976153069",
"email": "joao.silva@example.com",
"phone": "+55 11 91234-5678"
},
"allowElectronicSignature": true
}]
}'
Resposta (CreateDocumentResult[]). É uma lista, com um item por arquivo enviado:
[{ "uploadId": "0429c723-...", "documentId": "9f2e1c44-..." }]
Guarde o documentId: ele é a chave de todas as chamadas seguintes.
Campos que importam
| Campo | Obrigatório | O que faz |
|---|---|---|
files[] |
sim | Cada arquivo vira um documento separado (a não ser com isEnvelope) |
flowActions[] |
sim | Quem assina ou aprova, e em que ordem |
isEnvelope + envelopeName |
— | Junta todos os arquivos em um único documento (só PDF) |
description |
— | Texto (até 600 caracteres) mostrado ao participante e no e-mail |
folderId / newFolderName |
— | Guarda o documento numa pasta existente ou numa nova |
attachments[] |
— | Anexos que acompanham o documento (também precisam de upload antes) |
observers[] |
— | Quem recebe cópia sem precisar assinar |
disablePendingActionNotifications |
— | Não avisa os participantes do passo 1 |
disableNotifications |
— | Não avisa ninguém neste documento |
notifiedEmails[] |
— | E-mails extras avisados na conclusão |
expirationDate |
— | Data limite para assinar (a hora é descartada) |
tags[] |
— | Pares { label, value } para reencontrar o documento depois (GET /api/documents?Tags=) |
signatureType |
— | None, Simple, Advanced, Qualified |
forceCadesSignature |
— | Força CAdES mesmo em PDF |
timestampEnabled |
— | Carimbo do tempo nas assinaturas |
convertToPdfA + pdfAProfile |
— | Converte o resultado para PDF/A |
securityContextId |
— | Contexto de segurança (política de certificados) específico |
templateId + templateFieldValues |
— | Preenche um modelo cadastrado no Signer |
participantsDataFile |
— | Planilha de participantes (também vem de um upload) |
Montando o flowActions[]
| Campo | O que faz |
|---|---|
type |
Signer, Approver, SignRule, ApproverRule |
step |
A ordem. Mesmo número = ao mesmo tempo; números diferentes = um depois do outro |
user |
Participante único (Signer/Approver): name, email, identifier, identifierType, phone |
ruleUsers[] |
Grupo de participantes (SignRule/ApproverRule) |
numberRequiredActions |
Quantos do grupo precisam agir (ex.: 2 de 4 sócios) |
title |
Nome do papel ("Contratante", "Testemunha") |
allowElectronicSignature |
true = aceita assinatura eletrônica; false = exige certificado digital |
requireSmsAuthenticationToSignElectronically |
Código por SMS antes de assinar |
requireWhatsappAuthenticationToSignElectronically |
Código por WhatsApp antes de assinar |
prePositionedMarks[] |
Posição da rubrica ou assinatura no PDF (veja Posicionar a assinatura no PDF) |
Um depois do outro: o segundo só é avisado quando o primeiro termina.
"flowActions": [
{ "type": "Signer", "step": 1, "user": { "name": "João", "email": "joao@example.com", "identifier": "81976153069" } },
{ "type": "Approver", "step": 2, "user": { "name": "Maria", "email": "maria@example.com", "identifier": "12345678909" } }
]
Dois ao mesmo tempo: os dois são avisados na hora e assinam em qualquer ordem.
"flowActions": [
{ "type": "Signer", "step": 1, "user": { "name": "João", "email": "joao@example.com", "identifier": "81976153069" } },
{ "type": "Signer", "step": 1, "user": { "name": "Maria", "email": "maria@example.com", "identifier": "12345678909" } }
]
Regra "2 de 4": quatro sócios podem assinar, bastam dois.
"flowActions": [{
"type": "SignRule",
"step": 1,
"ruleName": "Diretoria",
"numberRequiredActions": 2,
"ruleUsers": [
{ "name": "Sócio A", "email": "a@example.com", "identifier": "11111111111" },
{ "name": "Sócio B", "email": "b@example.com", "identifier": "22222222222" },
{ "name": "Sócio C", "email": "c@example.com", "identifier": "33333333333" },
{ "name": "Sócio D", "email": "d@example.com", "identifier": "44444444444" }
]
}]
Passo 3 (opcional): levar quem assina direto para a tela
Por padrão o Signer já envia o e-mail de ação pendente. Use este passo quando quiser que a assinatura
aconteça dentro do seu sistema, sem passar pelo e-mail:
POST /api/documents/{id}/action-url.
curl -X POST "https://app.ideiasigner.com.br/api/documents/$DOC_ID/action-url" \
-H "X-Api-Key: $IDEIA_SIGNER_KEY" \
-H "Content-Type: application/json" \
-d '{ "identifier": "81976153069", "emailAddress": "joao.silva@example.com", "requireEmailAuthentication": false }'
Resposta: { "url": "...", "embedUrl": "..." }. Use url para redirecionar e embedUrl para
mostrar a assinatura dentro da sua página (veja Assinatura dentro do seu sistema).
Se a pessoa tem mais de uma ação pendente no mesmo documento, informe também o
flowActionId(ele vem emGET /api/documents/{id}).
Combinação usual: criar o documento com disablePendingActionNotifications: true e gerar a
action-url. Assim o Signer não manda e-mail e tudo acontece na sua interface.
Passos 4 e 5: acompanhar e baixar
Acompanhar
| Forma | Chamada | Quando usar |
|---|---|---|
| Webhook (recomendado) | cadastrado no painel da organização | Produção. Você recebe DocumentConcluded, DocumentSigned, DocumentRefused, DocumentCanceled, DocumentExpired, DocumentApproved, DocumentsCreated, DocumentDeleted |
| Consulta pontual | GET /api/documents/{id} |
Tela de detalhe; traz a situação e os flowActions com seus ids |
| Detalhe das assinaturas | GET /api/documents/{id}/signatures-details |
Quem assinou, quando e com que tipo de assinatura |
| Listagem | GET /api/documents?Status=Pending |
Painéis e relatórios |
Situações possíveis: Pending, Refused, FlowConcluded, Concluded, Canceled, Expired.
Não fique consultando
GET /api/documents/{id}em repetição para saber se já assinaram: é para isso que existe o webhook.
Webhooks
Para ativar, cadastre o endereço do seu sistema na seção de integrações da
página da sua organização. A cada evento, o
Signer faz um POST nesse endereço com o corpo { "type": "...", "data": { ... } }. O conteúdo de
data muda conforme o evento; os formatos estão na referência, na seção de
modelos (Webhooks.*).
Sempre confira o documento pela API antes de tomar uma decisão importante (por exemplo, liberar um pagamento) com base num webhook.
Baixar
# arquivo direto
curl -L "https://app.ideiasigner.com.br/api/documents/$DOC_ID/content?type=Signatures" \
-H "X-Api-Key: $IDEIA_SIGNER_KEY" -o assinado.pdf
| Variante | Chamada | Devolve |
|---|---|---|
| Arquivo | GET /api/documents/{id}/content?type=... |
O arquivo |
| Base64 | GET /api/documents/{id}/content-b64?type=... |
JSON com os bytes |
| Link temporário | GET /api/documents/{id}/ticket?type=... |
Um link (bom para entregar ao navegador sem expor a chave) |
Valores de type: Original, Signatures (o assinado), PrinterFriendlyVersion,
OriginalWithMarks, SigningTags, SignatureMarks, SignaturesManifest.
Posicionar a assinatura no PDF
Se a rubrica precisa cair num lugar exato da página, entra um passo entre o upload e a criação do documento.
POST /api/uploads → POST /api/marks-sessions/documents → [a pessoa posiciona no iframe]
│
devolve o MESMO corpo, agora │
com prePositionedMarks[] │
▼
POST /api/documents
POST /api/marks-sessions/documents: mande o mesmo corpo que mandaria paraPOST /api/documents. Resposta:{ id, embedUrl }.- Abra o
embedUrlnum iframe (veja Assinatura dentro do seu sistema). A pessoa arrasta as marcas sobre o PDF. - Pegue o resultado pelo evento do iframe ou por
GET /api/marks-sessions/{id}. - Mande esse corpo, agora com
flowActions[].prePositionedMarks[]preenchido, paraPOST /api/documents.
Se você só quer criar a sessão com os dados mínimos (sem e-mail ou CPF de quem assina), use
POST /api/marks-sessions. A sessão
vale por 1 hora depois de criada.
Se você já sabe as coordenadas, pule a sessão e mande direto em prePositionedMarks[]:
"prePositionedMarks": [{
"type": "SignatureVisualRepresentation",
"pageNumber": 1,
"topLeftX": 100, "topLeftY": 600,
"width": 200, "height": 60,
"uploadId": "0429c723-..."
}]
topLeftX/topLeftY marcam o canto superior esquerdo da marca, em pontos do PDF
(1 pt = 1/72 de polegada). uploadId prende a marca a um arquivo; se ficar vazio, a marca vale para
todos os arquivos enviados. Tipos de marca: SignatureVisualRepresentation, SignatureInitials,
AuthenticationStamp.
Se você não tem as coordenadas medidas, use a sessão de marcas: acertar a posição por tentativa e erro sai mais caro que integrar o iframe.
Assinatura dentro do seu sistema
O componente IdeiaSignerWidget mostra a tela de assinatura (ou de posicionamento de marcas) dentro
da sua página, num iframe. Inclua o script:
<script src="https://statics.redeideia.com.br/signer/doc/signer-widget-0.7.0.min.js"
crossorigin="anonymous"></script>
Crie o componente e escute os eventos:
var widget = new IdeiaSignerWidget();
widget.on(widget.events.documentSigned, function (e) {
// documento e.id assinado
});
widget.on(widget.events.documentApproved, function (e) {
// documento e.id aprovado
});
Ou um único callback para todos os eventos:
widget.listen(function (e) {
if (e.type === widget.events.documentSigned) {
// ...
} else if (e.type === widget.events.documentApproved) {
// ...
}
});
Por fim, mostre o iframe com render():
// embedUrl: vem do passo 3 (action-url) ou da sessão de marcas
// 'embed-container': id do elemento que vai receber o iframe
widget.render(embedUrl, 'embed-container', page, scale);
// ou passando o elemento direto
widget.renderElement(embedUrl, document.getElementById('embed-container'), page, scale);
page(opcional): página em que o documento abre. Use'-1'para abrir sempre na última.scale(opcional): zoom inicial, como texto ('100') ouwidget.scaleOptions.S100.
Sempre confira no seu servidor, pela API, se o documento foi mesmo concluído: os callbacks do navegador podem ser disparados por outros scripts da página.
Configurações do componente
Passe um objeto ao criar o IdeiaSignerWidget, por exemplo
new IdeiaSignerWidget({ disableDocumentPreview: true }):
| Atributo | Tipo | O que faz |
|---|---|---|
enableNotifications |
boolean | Por padrão, a assinatura dentro do seu sistema não envia notificações ao concluir. Use true para enviar (ou setEnableNotifications) |
disableDocumentPreview |
boolean | true esconde a pré-visualização: aparecem só o botão de assinar e os dados de quem assina (ou setDisableDocumentPreview) |
enableRefusal |
boolean | true mostra a opção de recusar (ou setEnableRefusal) |
culture |
string | Idioma: "pt", "en" ou "es" |
Posicionamento de marcas no iframe
Com o embedUrl da sessão de marcas, escute o evento marksPositioned:
widget.on(widget.events.marksPositioned, function (e) {
// e.data traz o corpo da criação de documento já com as posições
});
widget.render(embedUrl, 'embed-container');
Ao concluir, cada item de flowActions do corpo enviado na criação da sessão volta com
prePositionedMarks preenchido. O mesmo corpo também pode ser lido em
GET /api/marks-sessions/{id}.
Depois de criado
| Necessidade | Chamada |
|---|---|
| Trocar quem assina / corrigir e-mail | POST /api/documents/{id}/flow |
| Cancelar (exige motivo) | POST /api/documents/{id}/cancellation |
| Recusar (exige motivo) | POST /api/documents/{id}/refusal |
| Nova versão do arquivo | POST /api/documents/{id}/versions |
| Nova versão de envelope | POST /api/documents/{id}/envelope/versions |
| Mover para pasta | POST /api/documents/{id}/folder (ou /batch/folder) |
| Reenviar o aviso a um participante | POST /api/notifications/flow-action-reminder |
| Avisar vários de uma vez | POST /api/users/notify-pending |
| Atualizar e-mails avisados | PUT /api/documents/{id}/notified-emails |
| Excluir | DELETE /api/documents/{id} |
| Validar as assinaturas de um PDF externo | POST /api/documents/validate-signatures |
| Validar pelo código de verificação | GET /api/documents/keys/{key}/signatures |
Fluxo reutilizável
Quando o mesmo grupo de pessoas assina sempre, cadastre o fluxo uma vez em
POST /api/document-flows e reaproveite.
Atenção: POST /api/documents não tem um campo que aponte para o fluxo. O reaproveitamento
é feito no seu código: você lê o fluxo e copia os flowActions dele para o corpo da criação.
POST /api/document-flows (uma vez, cadastra o modelo)
│
▼
GET /api/document-flows/{id} → devolve flowActions[] no mesmo formato do POST /api/documents
│
├──────────► copie esse flowActions[] para o corpo
▼
POST /api/uploads → POST /api/documents
Gestão: GET /api/document-flows (lista) e
GET/PUT/DELETE em /api/document-flows/{id}.
O campo areActionsOrdered do fluxo diz se as ações são uma depois da outra ou ao mesmo tempo.
Criação em lote
Para muitos documentos, divida em lotes: 100 documentos = 10 requisições de 10, e não 1 de 100.
- Envie cada lote com
disablePendingActionNotifications: true. - Quando todos os lotes terminarem, chame
POST /api/users/notify-pendinguma única vez.
Assim ninguém recebe e-mail no meio de um lote que ainda pode falhar.
Códigos de erro
| Código | Significado | Causa comum |
|---|---|---|
400 |
Erro de sintaxe | Campo obrigatório faltando (files, flowActions) |
401 |
Não autenticado | X-Api-Key ausente ou inválida |
403 |
Sem permissão | A chave é válida, mas a aplicação não tem permissão para a operação |
422 |
Erro de regra | Id não encontrado. Quase sempre um uploadId errado ou já usado |
O corpo do 422 segue o modelo ErrorModel (code, message, details). Alguns códigos:
DocumentNotFound, FolderNotFound, CertificateNotFound, CpfMismatch, CpfNotExpected,
InvalidFlowAction, DocumentInvalidKey. A lista não é completa e pode crescer.
Erros comuns na integração
422no passo 2: ofiles[].idnão é oidque o upload devolveu, ou esse upload não é da organização da sua chave. Refaça o passo 1 e use oidnovo.- Ninguém recebeu e-mail:
disableNotificationsoudisablePendingActionNotificationsficaramtrue. - O segundo participante não foi avisado: ele está num
stepmaior e o primeiro ainda não assinou. Confira ostep. - Criou 3 documentos em vez de 1: 3 itens em
files[]semisEnvelope: true. - A assinatura caiu no lugar errado: confira
pageNumbere se as coordenadas estão em pontos do PDF (e não em pixels da sua tela de pré-visualização).
Valores aceitos
| Tipo | Valores |
|---|---|
FlowActionType |
Signer, Approver, SignRule, ApproverRule |
IdentifierTypes |
Cpf, Passport, EcuadorBceId, ParaguayCedulaIdentidad, ParaguayRuc, ParaguayPassport |
DocumentStatus |
Pending, Refused, FlowConcluded, Concluded, Canceled, Expired |
DocumentFilterStatus |
PendingOrRefused, Concluded, CanceledOrExpired, Pending, Refused, Canceled, Expired |
DocumentDownloadTypes / DocumentTicketType |
Original, Signatures, PrinterFriendlyVersion, OriginalWithMarks, SigningTags, SignatureMarks, SignaturesManifest |
SignatureTypes |
None, Simple, Advanced, Qualified |
AuthenticationTypes |
SMS, AuthenticatorApp, Email, Login, Application, Selfie, Datavalid, Pix, AccessCode, Whatsapp, Liveness, IdScan |
DocumentMarkType |
SignatureVisualRepresentation, SignatureInitials, AuthenticationStamp |
NotificationLanguage |
Pt, Es, En |
WebhookTypes |
DocumentsCreated, DocumentSigned, DocumentApproved, DocumentConcluded, DocumentRefused, DocumentCanceled, DocumentExpired, DocumentDeleted, InvoiceClosed |
Lista de conferência
- A chave da API está guardada como segredo no servidor, nunca no navegador ou no aplicativo.
- O upload e a criação do documento são feitos no servidor.
- O
uploadIdé descartável: usou noPOST /api/documents, pode esquecer. - O
documentIdestá salvo no seu banco, ligado ao registro de origem. - O webhook está configurado, em vez de consultas repetidas.
- O
422no passo 2 é tratado com um novo upload. - Lotes grandes são divididos, com
notify-pendingno final.