Integre assinatura eletrônica em sua stack
Envie envelos, acompanhe assinaturas, receba webhooks. API REST simples, OpenAPI 3.0, exemplos curl/Node/Python — tudo para conectar a Certyneo ao seu HRIS, CRM ou software corporativo em poucas horas.
Início rápido
Três etapas: crie uma chave API nas configurações, codifique seu PDF em base64, envie. A resposta contém o `signUrl` que você pode compartilhar diretamente com o destinatário.
# 1. Upload the PDF (multipart) and capture the returned document id.
DOC_ID=$(curl -s -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@contrat.pdf" | jq -r .id)
# 2. Create a DRAFT envelope referencing the uploaded document.
ENV_ID=$(curl -s -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d "{
\"subject\": \"Contrat de prestation\",
\"documentIds\": [\"$DOC_ID\"],
\"recipients\": [
{ \"email\": \"client@example.com\", \"name\": \"Marie Dubois\", \"role\": \"SIGNER\" }
]
}" | jq -r .id)
# 3. Dispatch the envelope — this sends the invitation email/SMS.
curl -X POST https://certyneo.com/api/v1/envelopes/$ENV_ID/send \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"// Plain fetch, no SDK to install.
const auth = { Authorization: `Bearer ${process.env.CERTYNEO_API_KEY}` };
// 1. Upload the PDF (multipart).
const fd = new FormData();
fd.append("file", new Blob([pdfBuffer], { type: "application/pdf" }), "contrat.pdf");
const doc = await fetch("https://certyneo.com/api/v1/documents", {
method: "POST", headers: auth, body: fd,
}).then((r) => r.json());
// 2. Create the DRAFT envelope.
const envelope = await fetch("https://certyneo.com/api/v1/envelopes", {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({
subject: "Contrat de prestation",
documentIds: [doc.id],
recipients: [
{ email: "client@example.com", name: "Marie Dubois", role: "SIGNER" },
],
}),
}).then((r) => r.json());
// 3. Dispatch — this triggers the invitation channel for every recipient.
await fetch(`https://certyneo.com/api/v1/envelopes/${envelope.id}/send`, {
method: "POST", headers: auth,
});
console.log(envelope.id);import os, requests
auth = {"Authorization": f"Bearer {os.environ['CERTYNEO_API_KEY']}"}
# 1. Upload the PDF (multipart).
with open("contrat.pdf", "rb") as f:
doc = requests.post(
"https://certyneo.com/api/v1/documents",
headers=auth,
files={"file": ("contrat.pdf", f, "application/pdf")},
).json()
# 2. Create the DRAFT envelope.
envelope = requests.post(
"https://certyneo.com/api/v1/envelopes",
headers={**auth, "Content-Type": "application/json"},
json={
"subject": "Contrat de prestation",
"documentIds": [doc["id"]],
"recipients": [
{"email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER"},
],
},
).json()
# 3. Dispatch — this triggers the invitation channel for every recipient.
requests.post(
f"https://certyneo.com/api/v1/envelopes/{envelope['id']}/send",
headers=auth,
)
print(envelope["id"])Experimentar a API a partir de suas ferramentas
A coleção Postman e a ficha RapidAPI são geradas a partir da especificação OpenAPI que documenta também esta página. Os três permanecem portanto alinhados na API real, endpoint por endpoint, em vez de divergirem na primeira adição.
Coleção Postman
As 25 requisições organizadas por domínio — envelopes, documentos, modelos, selos, webhooks — com um exemplo de corpo e resposta para cada uma. Cole sua chave na variável apiKey da coleção, depois execute GET /health: ela não requer nenhuma autenticação e confirma que sua configuração está correta antes da primeira chamada autenticada.
Envelos
Criação, envio, rastreamento de status, cancelamento. Um envelo pode conter vários documentos e vários signatários (paralelo ou sequencial).
Webhooks
Todos os eventos de envelope e destinatário (`envelope.sent`, `recipient.signed`, `envelope.completed`…) entregues no URL à sua escolha — lista completa em /developers/webhooks. HMAC SHA-256 em cada payload para verificar a origem.
Autenticação simples
Bearer token. Uma chave por ambiente (teste/produção). Revogável instantaneamente. Limite de 100 req/min/chave, burst de 200, 429 limpo com cabeçalho Retry-After.
Endpoints disponíveis
As 53 rotas públicas: conta, documentos, envelopes, modelos, webhooks, selos eletrônicos, chaves API e faturamento. Todas aceitam um token Bearer e retornam JSON.
| Método | Caminho | Descrição |
|---|---|---|
| GET | /api/v1/account/me | Identidade do chamador autenticado (id, e-mail, plano) : teste de identificadores sem escopo obrigatório |
| GET | /api/v1/sandbox | Contar os dados criados com as chaves de teste (excluídos automaticamente após 30 dias) |
| DELETE | /api/v1/sandbox | Excluir todos os dados criados com as chaves de teste, sem afetar os dados reais |
| POST | /api/v1/documents | Enviar um PDF (multipart) : retorna o id do documento |
| GET | /api/v1/documents | Listar os documentos |
| GET | /api/v1/documents/{id} | Ler os metadados de um documento |
| DELETE | /api/v1/documents/{id} | Eliminar um documento |
| GET | /api/v1/envelopes | Listar os envelopes (filtrar com ?status= e ?limit=) |
| POST | /api/v1/envelopes | Criar um envelope (status DRAFT) : a partir de um templateId, ou de documentIds com um array fields opcional |
| GET | /api/v1/envelopes/{id} | Ler o estado de um envelope |
| PATCH | /api/v1/envelopes/{id} | Modificar um envelope DRAFT |
| DELETE | /api/v1/envelopes/{id} | Eliminar um envelope DRAFT (409 uma vez enviado : cancelar em vez disso) |
| POST | /api/v1/envelopes/{id}/send | Enviar um envelope DRAFT : envia os convites |
| POST | /api/v1/envelopes/{id}/void | Cancelar um envelope enviado ainda não totalmente assinado : os signatários em espera são notificados |
| POST | /api/v1/envelopes/{id}/remind | Relembrar sob demanda os signatários aguardando um envelope enviado (um destinatário específico como opção) |
| GET | /api/v1/envelopes/{id}/audit-trail | Descarregar o PDF do diário de prova eIDAS |
| POST | /api/v1/envelopes/{id}/embed-url | Retorna a URL de assinatura de um destinatário, acompanhada de uma autorização de enquadramento para a origem solicitada. A chamar no momento do clique: a autorização é válida por duas horas. |
| GET | /api/v1/audit-anchors/{root} | Público : metadados de um lote de auditoria ancorado, ou ficheiro de prova .ots com ?format=ots (sem autenticação) |
| POST | /api/v1/audit-anchors/verify | Público : verificar uma entrada de auditoria e sua prova face à raiz de Merkle ancorada (sem autenticação, não revela nada) |
| GET | /api/v1/envelopes/{id}/signed-document | Descarregar o PDF assinado (uma vez COMPLETED) |
| GET | /api/v1/envelopes/bulk | Listar seus envios em massa |
| POST | /api/v1/envelopes/bulk | Envio em massa: criar N envelopes a partir de um modelo e um CSV (Standard/Business apenas) |
| GET | /api/v1/envelopes/bulk/{id} | Progresso de um envio em massa: contadores, falhas por linha, envelopes criados |
| GET | /api/v1/templates | Listar os modelos de envelope reutilizáveis |
| POST | /api/v1/templates | Criar um modelo (documentos, funções, campos posicionados) |
| GET | /api/v1/workspaces | Listar os espaços de trabalho nos quais pode criar um envelope |
| POST | /api/v1/sepa-mandates | Gerar o PDF de um mandato SEPA e seu envelope DRAFT, campos já colocados |
| POST | /api/v1/payroll-adapters/normalize | Normalizar um CSV de folha de pagamento (Silae, Sage Paie, PayFit, Lucca) no formato do envio em massa |
| POST | /api/v1/ag-copropriete | Criar um envelope de assembleia geral de condomínio (resoluções e quotas) |
| POST | /api/v1/ag-copropriete/{envelopeId}/votes | Registrar os votos de um condômino nas resoluções da assembleia |
| POST | /api/v1/ag-copropriete/{envelopeId}/tally | Apurar a assembleia: resultado por resolução, ponderado pelas quotas |
| GET | /api/v1/videos/{videoId} | Baixar um vídeo de identidade conservado: direito de acesso RGPD (art. 15) |
| GET | /api/v1/webhooks | Listar os webhooks |
| POST | /api/v1/webhooks | Registrar um webhook: retorna o segredo de assinatura uma única vez |
| GET | /api/v1/webhooks/{id} | Ler uma subscrição webhook |
| PATCH | /api/v1/webhooks/{id} | Modificar a URL, os eventos ou o estado ativo |
| DELETE | /api/v1/webhooks/{id} | Desinscrever o webhook |
| POST | /api/v1/seals | Apor um carimbo eletrônico qualificado em um documento |
| GET | /api/v1/seals/{id} | Ler o status de um carimbo |
| GET | /api/v1/seals/{id}/certificate | Baixar o certificado do carimbo |
| GET | /api/v1/payslips/workspaces | Bulletins de paie: os espaços para os quais essa chave distribui, detidos ou delegados por um cliente (consultórios contábeis, gestores de folha de pagamento) |
| GET | /api/v1/payslips/employees | Bulletins de paie: o registro dos assalariados, com aqueles que recusaram a entrega eletrônica (boletim em papel devido) |
| PUT | /api/v1/payslips/employees | Contracheques: adicionar ou atualizar funcionários do registro (nunca remove nenhum) |
| POST | /api/v1/payslips | Enviar um contracheque (PDF) para o cofre de um funcionário: selado, conservado 50 anos, nova tentativa sem duplicata |
| GET | /api/v1/payslips | Listar os contracheques enviados, com sua prova de consulta |
| GET | /api/v1/keys | Listar as chaves de API |
| POST | /api/v1/keys | Criar uma chave de API: o segredo é exibido apenas uma vez |
| PATCH | /api/v1/keys/{id} | Renomear ou revogar uma chave |
| DELETE | /api/v1/keys/{id} | Excluir uma chave |
| GET | /api/v1/billing/usage | Consumo do período atual e custo projetado |
| GET | /api/v1/status | Estado do serviço |
| GET | /api/v1/health | Verificação de saúde: banco de dados, fila de espera e armazenamento de objetos |
| GET | /api/v1/openapi | Especificação OpenAPI legível por máquina |
Modelos de envelope
Um modelo registra uma vez por todas o PDF, as funções e a localização dos campos de assinatura, e depois é reutilizado a cada envio: passe seu identificador em templateId em vez de documentIds, e os campos posicionados são copiados para o envelope criado.
- • Os modelos são criados a partir do painel de controle (Modelos → Novo modelo), onde você faz upload do documento e posiciona os campos com o mouse — este é o caminho mais simples. A API também permite criá-los via POST /api/v1/templates, fornecendo os documentos, as funções e os campos; observe que os campos são posicionados em coordenadas absolutas (página, x, y, largura, altura), então você precisa conhecer o layout do PDF.
- • Em uma conta que ainda não registrou nenhum modelo, GET /api/v1/templates retorna uma lista vazia. Este é o comportamento normal, não é uma falha de autenticação.
- • A lista contém apenas os modelos pertencentes ao usuário proprietário da chave API. Um modelo criado por um colega não aparece nela, mesmo dentro de um espaço de trabalho compartilhado: gere a chave a partir da conta que possui o modelo.
- • templateId e documentIds são mutuamente exclusivos: envie um ou outro, nunca ambos nem nenhum dos dois.
- • Forneça pelo menos tantos destinatários SIGNER quantas funções signatárias o modelo possui, caso contrário a criação é recusada em 400. O campo signerCount retornado pela lista indica o número esperado.
- • O nível de assinatura do modelo é herdado pelo envelope, a menos que a solicitação passe explicitamente signatureLevel.
# 1. Discover the templates saved on this account.
curl -s https://certyneo.com/api/v1/templates \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
# {
# "data": [
# { "id": "cmdq7f4k80001s6y2h1xa9pl3", "name": "Contrat de prestation",
# "signerCount": 2, "documentCount": 1, "signatureLevel": "SIMPLE" }
# ],
# "pagination": { "page": 1, "pageSize": 20, "total": 1, "pages": 1 }
# }
#
# An empty "data" array means no template exists on this account yet —
# create one from the dashboard, it is not an authentication problem.
# 2. Create the envelope FROM the template: no documentIds and no field
# coordinates, both are carried by the template. Pass one SIGNER
# recipient per signer role, in the template's role order.
curl -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Contrat de prestation",
"templateId": "cmdq7f4k80001s6y2h1xa9pl3",
"recipients": [
{ "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" },
{ "email": "legal@example.com", "name": "Paul Martin", "role": "SIGNER" }
]
}'
# 3. The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.A partir do Power Automate ou Zapier
A ação "Criar um envelope" dos nossos conectores sem código cobre apenas o caminho por modelo: o campo Modelo é obrigatório nele. Para um documento ad hoc que muda a cada execução, use a ação "Fazer upload de um documento" seguida de uma ação HTTP bruta para POST /api/v1/envelopes passando o documentIds retornado.
Envio do documento: duas formas aceitas
POST /api/v1/documents aceita o arquivo de duas formas, à escolha. Os mesmos controles se aplicam nos dois casos: tipos autorizados, limite de 50 Mo, verificação da assinatura binária e análise antivírus.
- • Em multipart/form-data, com uma parte nomeada file. Esta é a forma clássica, a do curl -F e da maioria das bibliotecas.
- • Em corpo bruto: os bytes do arquivo constituem o corpo da requisição, e o cabeçalho Content-Type fornece seu tipo (application/pdf por exemplo). Útil a partir de uma ferramenta que transmite o conteúdo tal qual, sem envolver a requisição — é o que faz o conector Power Automate.
- • Em corpo bruto, o nome do arquivo não tem lugar no corpo: indique-o via cabeçalho X-File-Name ou parâmetro ?fileName=. Sem ele, o documento é nomeado de acordo com seu tipo.
- • Um tipo não suportado responde 415 nomeando as duas formas aceitas, e um corpo anunciado como multipart mas ilegível responde 400. Nenhum dos dois é um erro de servidor.
# a. multipart/form-data — the classic shape.
curl -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@contrat.pdf;type=application/pdf"
# b. raw body — the file bytes ARE the body, typed by Content-Type.
# The filename has nowhere to live in the body, so pass it as a header
# (or ?fileName=). Without it the document is named after its type.
curl -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/pdf" \
-H "X-File-Name: contrat.pdf" \
--data-binary "@contrat.pdf"
# Both return the same 201 with the document id to pass as documentIds.Posicionamento dos campos de assinatura
Sem modelo, um envelope criado a partir de documentIds não tem nenhum campo pré-posicionado: o signatário recebe o documento sem local para assinar. O array fields, transmitido na mesma chamada de criação, coloca cada campo no ponto exato — é o equivalente, no lado da API, do que um modelo registra uma vez por todas.
- • As coordenadas estão em pontos PDF, com origem no canto superior esquerdo da página e eixo Y apontando para baixo (uma página A4 mede 595 × 842 pontos). x e y designam o canto superior esquerdo do campo, width e height seu tamanho.
- • pageNumber começa em 1, documentIndex começa em 0. Um número de página além do documento não é rejeitado na criação: o campo é ignorado no momento da assinatura e não aparece em lugar nenhum — é a primeira coisa a verificar quando um campo está faltando.
- • recipientEmail deve corresponder a um dos destinatários da mesma chamada, sem distinção de maiúsculas e minúsculas. Caso contrário, a criação falhará listando todas as linhas com falha, o que evita corrigi-las uma por uma.
- • fields e templateId são mutuamente exclusivos: um modelo já carrega seu próprio layout. O array fields é usado apenas com documentIds.
- • Tipos aceitos: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX e RADIO_GROUP. required é verdadeiro por padrão; placeholder e dateFormat são opcionais, e options é considerado apenas para RADIO_GROUP.
- • Um envelope aceita no máximo 100 campos, 20 documentos e 50 destinatários — os limites do seu plano podendo ser inferiores.
# Ad-hoc envelope WITH pre-placed fields — no template involved.
# Coordinates are PDF points, origin TOP-LEFT of the page, +Y downwards
# (A4 = 595 x 842 pt). x / y are the field box's top-left corner.
#
# The last field is positioned by ANCHOR instead of by eye: the server
# locates "Signature du client" in the PDF and computes the spot. x / y
# stay required there — they are the fallback if the text is not found.
curl -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Contrat de prestation",
"documentIds": ["cmdq7f4k80001s6y2h1xa9pl3"],
"recipients": [
{ "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" }
],
"fields": [
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "SIGNATURE",
"x": 90, "y": 640, "width": 180, "height": 44 },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "DATE_SIGNED",
"x": 320, "y": 640, "width": 140, "height": 30,
"dateFormat": "DD/MM/YYYY" },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "TEXT",
"x": 90, "y": 700, "width": 200, "height": 30,
"placeholder": "Fonction", "required": false },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "SIGNATURE",
"anchorText": "Signature du client", "anchorPlacement": "below",
"anchorIndex": 0,
"x": 90, "y": 640, "width": 180, "height": 44 }
]
}'
# The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.Âncoras textuais: colocar um campo sem conhecer as coordenadas
Em vez de coordenadas, um campo pode citar um texto impresso no documento: anchorText o localiza no PDF e o servidor calcula a posição na criação. Este é o modo a privilegiar quando o documento é regenerado a cada envio — mala direta, gerador de contratos — pois o layout se move enquanto a menção « Assinatura do cliente » permanece. anchorPlacement indica de qual lado do texto o campo se coloca (right por padrão, caso contrário below, above ou left) e anchorIndex escolhe a ocorrência quando o texto aparece várias vezes.
x e y permanecem obrigatórios mesmo com uma âncora: servem como fallback. Uma âncora não encontrada não causa falha na criação — o campo mantém a posição literal que você forneceu, sem erro nem aviso na resposta. Indique portanto um fallback plausível em vez de 0,0, e verifique a renderização em um primeiro envio.
Assinatura integrada: assine sem sair do seu aplicativo
Seu cliente consulta e assina seu documento a partir de sua própria interface. A cerimônia abre em uma janela acima de sua página e retorna automaticamente ao seu site quando concluída. No servidor, nada de novo: você cria o envelope como sempre, preenchendo redirectUrl, e depois confia ao SDK a URL de assinatura do destinatário.
- • Chame Certyneo.sign() diretamente no seu manipulador de clique e passe sua chamada de servidor por getUrl. Um await antes de sign() sai do gesto do usuário: Safari e Firefox bloqueiam a janela. O SDK a abre imediatamente e a carrega quando sua promessa é resolvida.
- • redirectUrl é o canal de retorno. Devolvemos o signatário ali adicionando certyneo_status (completed ou declined) e certyneo_envelope. Carregue o mesmo script nesta página de retorno: é ele que notifica a janela do portal que permaneceu aberta atrás.
- • Em modo integrado, nossos próprios apelos à ação são suprimidos. Seu cliente nunca vê um convite para criar uma conta Certyneo.
- • Se o navegador recusar a janela, o SDK muda automaticamente para redirecionamento de página inteira. O percurso é idêntico para o signatário e sua página de retorno recebe exatamente os mesmos parâmetros.
- • Intencionalmente não existe um callback "o usuário abandonou": o estado da janela não é legível a partir de sua página, e tal callback se dispararia incorretamente. Uma assinatura que não chega permanece pendente até o webhook.
// 1. Your server creates and sends the envelope, then hands the browser the
// recipient's signing URL. Nothing new on the API side:
// POST /api/v1/envelopes { …, "redirectUrl": "https://your-app.com/quote/42/signed" }
// POST /api/v1/envelopes/{id}/send → recipients[].accessToken
// signingUrl = "https://certyneo.com/sign/" + accessToken
// 2. On your quote page — load the SDK once:
// <script src="https://certyneo.com/embed.js"></script>
document.querySelector("#sign").addEventListener("click", () => {
Certyneo.sign({
// Called AFTER the window is already open, so no popup blocker ever
// sees a delay between the click and window.open.
getUrl: () =>
fetch("/api/quote/42/signature", { method: "POST" })
.then((r) => r.json())
.then((d) => d.signingUrl),
onCompleted: (e) => showConfirmation(e.envelopeId),
onDeclined: () => showDeclined(),
onError: (e) => showError(e),
});
});
// 3. On https://your-app.com/quote/42/signed — your return page — load the
// same script and render a short confirmation. It relays the outcome to
// the portal window behind it, then closes itself.O evento do navegador não é uma prova de assinatura
onCompleted é um sinal de exibição, emitido por um navegador, portanto falsificável por qualquer pessoa a partir de seu console. Nunca mude um dossiê para "assinado" com base nisso: use-o para atualizar a tela e confie no webhook assinado envelope.completed recebido por seu servidor para o estado real. Este é o armadilha clássica das integrações de pagamento, e se reproduz de forma idêntica aqui.
Desenvolver em sua máquina
Com uma chave de teste, redirectUrl aceita http://localhost (e 127.0.0.1): você monta todo o percurso em sua máquina antes de implantar. Uma chave real o recusa, para que nenhum envelope de produção devolva um signatário real para uma máquina que não é a dele.
Exibir a cerimônia na sua página
O modo iframe exibe a assinatura dentro da sua interface, sem janela. Requer uma etapa a mais do que o modo janela: provar que o site que a exibirá é seu. Isto é o que impede um terceiro de incorporar nossas cerimônias para enganar seus clientes.
- • Declare seu site em Configurações → Assinatura integrada, depois publique o registro DNS indicado. Um endereço exato: um subdomínio ou uma porta diferente conta como outro site.
- • A cada assinatura, solicite uma URL fresca em POST /api/v1/envelopes/{id}/embed-url. Ela carrega a autorização de exibição e é válida por duas horas, o que corresponde ao momento do clique, não à criação do envelope.
- • Dois percursos não podem ser executados em um iframe: a assinatura qualificada, cuja verificação de identidade recusa ser incorporada por sua vez, e o pagamento na assinatura. Em ambos os casos o signatário é direcionado para uma janela completa.
- • A menção "Powered by Certyneo" desaparece do iframe a partir do plano Business. O modo iframe em si está incluído desde o plano Standard.
// Mode cadre : la cérémonie s'affiche DANS votre page.
//
// 1. Déclarez votre site une fois pour toutes dans Réglages → Signature
// intégrée, et publiez l'enregistrement DNS qu'on vous y donne.
//
// 2. À chaque signature, votre serveur demande une URL fraîche. Elle porte
// l'autorisation qui permet au navigateur d'afficher la cérémonie chez
// vous, et vaut deux heures :
//
// POST /api/v1/envelopes/{id}/embed-url
// { "origin": "https://portail.exemple.fr" }
// -> { "signingUrl": "…", "expiresAt": "…" }
Certyneo.sign({
mode: "iframe",
el: "#zone-signature", // sélecteur ou nœud de votre page
getUrl: () =>
fetch("/api/devis/42/signature", { method: "POST" })
.then((r) => r.json())
.then((d) => d.signingUrl),
onCompleted: (e) => afficherConfirmation(e.envelopeId),
onDeclined: () => afficherRefus(),
});
// Le cadre parle à votre page par postMessage — pas besoin de page de retour,
// contrairement au mode fenêtre.Fazer assinar sem que nenhum e-mail seja enviado
Um portal que exibe a cerimônia nele muitas vezes não precisa do nosso convite: ele chega junto com seu próprio fluxo e oferece uma conta a um cliente que não a quer. Defina o valor NONE no canal de notificação de um destinatário e nada mais será enviado a ele — você o leva até sua assinatura.
- • A configuração é por destinatário, não por envelope: você pode silenciar o cliente que hospeda e manter o e-mail para um contrassinante externo, que não tem portal.
- • É reservado aos signatários e aprovadores, os únicos a quem você tem um link a entregar. Você o lê na resposta da criação e envio, ou solicita uma URL fresca no momento do clique para POST /api/v1/envelopes/{id}/embed-url.
- • Os relembretes automáticos param por si mesmos para este destinatário: nunca lhe escrevemos, não começamos com um relembrete. Os outros destinatários continuam sendo relembrados normalmente.
- • O certificado de assinatura o menciona, destinatário por destinatário. Um dossiê de prova que ficasse silencioso nisto deixaria crer que este signatário recebeu de nós um convite que nunca existiu.
POST /api/v1/envelopes
{
"subject": "Mandat de gestion",
"documentIds": ["doc_8f2c1a4b9e7d"],
"recipients": [
{
"email": "client@exemple.fr",
"name": "Camille Client",
"role": "SIGNER",
"notificationChannel": "NONE"
},
{
"email": "notaire@exemple.fr",
"name": "Maître Notaire",
"role": "SIGNER"
}
]
}
// La réponse rend le lien de chaque signataire :
//
// "recipients": [
// { "email": "client@exemple.fr", "accessToken": "…",
// "notificationChannel": "NONE" },
// { "email": "notaire@exemple.fr", "accessToken": "…",
// "notificationChannel": "EMAIL" }
// ]
//
// Le client ne reçoit rien : vous l'emmenez sur sa signature depuis votre
// portail. Le notaire, lui, reçoit son invitation comme d'habitude.Exibir o nome do seu cliente como remetente
Por padrão, o signatário lê o nome do titular da chave API. Se você fizer assinar documentos de várias empresas com uma única chave, passe o campo sender na criação do envelope: a página de assinatura e os e-mails de convite e lembrete exibem então o nome da empresa em questão.
- • Reservado ao plano Business e acima. Em um plano inferior, a criação é recusada em vez de deixar o signatário ler um nome diferente do esperado.
- • O nome é uma exibição: o certificado e a trilha de auditoria mantêm o remetente real, e os e-mails partem sempre de Certyneo.
- • O endereço é facultativo. Sem ele, o signatário vê apenas o nome, nunca o endereço do titular da chave.
POST /api/v1/envelopes
{
"subject": "Devis 2026-118",
"documentIds": ["doc_8f2c1a4b9e7d"],
"recipients": [
{ "email": "client@exemple.fr", "name": "Camille Client", "role": "SIGNER" }
],
"sender": {
"name": "1.2.3. Panneaux Solaires",
"email": "devis@123-panneaux-solaires.fr"
}
}Autenticação
Cada chamada carrega uma chave API no cabeçalho Authorization. As chaves são geradas em Configurações → Chaves API e são exibidas apenas uma vez.
GET /api/v1/account/me HTTP/1.1Host: certyneo.com
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
# 200 OK
{ "data": { "id": "usr_…", "email": "you@example.com", "plan": "BUSINESS", "environment": "live" } }- • Formato: sk_live_… em produção, sk_test_… para sandbox. Cabeçalho: Authorization: Bearer <clé>.
- • Escopos: envelopes, documents, webhooks, seals — em leitura (:read) ou escrita (:write). A escrita implica leitura; o escopo * concede todos os direitos.
- • As chaves sk_test_ criam recursos na caixa de areia, excluídos da cota e da faturação. Nenhum e-mail real é enviado ao destinatário, a menos que o endereço dele corresponda ao e-mail da conta que envia — útil para testar o fluxo completo em você mesmo.
- • Erros: 401 chave inválida, 403 escopo insuficiente, 429 limite de taxa excedido, 402 cota mensal atingida.
Formato das respostas
Um ponto importante a saber antes de escrever seu cliente: as coleções são encapsuladas em um objeto data, enquanto os recursos unitários são retornados de forma plana. Ler response.data.data em um recurso unitário retorna undefined.
// GET /api/v1/envelopes
// Collections are WRAPPED in a "data" array.
{
"data": [
{ "id": "env_abc123", "subject": "Contrat", "status": "SENT" }
]
}// GET /api/v1/envelopes/{id}
// Single resources are returned FLAT — no "data" envelope.
{
"id": "env_abc123",
"subject": "Contrat",
"status": "COMPLETED",
"recipients": [ /* … */ ]
}Limites de taxa
Os limites garantem qualidade de serviço estável para todos os clientes. Se precisar de mais, entre em contato conosco.
- • 100 requisições por minuto por chave API
- • Burst tolerado até 200 requisições em menos de 10s
- • Resposta 429 com cabeçalho Retry-After indicando o atraso em segundos