Integreer elektronische handtekeningen in uw stack
Verzend enveloppen, volg handtekeningen, ontvang webhooks. Eenvoudige REST API, OpenAPI 3.0, curl/Node/Python-voorbeelden — alles wat u nodig hebt om Certyneo in enkele uren op uw HRIS, CRM of bedrijfssoftware aan te sluiten.
Drie stappen: maak een API-sleutel aan via instellingen, codeer uw PDF in base64, verzend. Het antwoord bevat de `signUrl` die u direct met de ontvanger kunt delen.
Enveloppen
# 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"])De API vanuit uw tools uitproberen
De Postman-collectie en RapidAPI-kaart worden gegenereerd op basis van de OpenAPI-specificatie die ook deze pagina documenteert. De drie blijven dus aligned met de echte API, endpoint voor endpoint, in plaats van uit elkaar te groeien bij de eerste toevoeging.
Postman-collectie
De 25 verzoeken ingedeeld per domein — enveloppen, documenten, sjablonen, zegels, webhooks — met een voorbeeld van de body en het antwoord voor elk. Plak uw sleutel in de variabele apiKey van de collectie, en voer vervolgens GET /health uit: deze vereist geen authenticatie en bevestigt dat uw configuratie correct is voordat de eerste geverifieerde oproep wordt gedaan.
Maken, verzenden, statusvoortgang, annulering. Een envelop kan meerdere documenten en meerdere ondertekenaars bevatten (parallel of sequentieel).
Webhooks
Ontvang `envelope.created`, `envelope.completed`, `envelope.declined` op de URL van uw keuze. HMAC SHA-256 op elke payload om de origine te verifiëren.
Alle envelop- en geadresseerde-gebeurtenissen (`envelope.sent`, `recipient.signed`, `envelope.completed`…) afgeleverd op de URL van uw keuze — volledige lijst op /developers/webhooks. HMAC SHA-256 op elke payload om de oorsprong te verifiëren.
Eenvoudige authenticatie
Bearer-token. Eén sleutel per omgeving (test / productie). Direct intrekbaar. Limiet van 100 verzoeken/minuut/sleutel, piek van 200, 429 eigen met Retry-After-header.
12 routes die de volledige cyclus dekken: enveloppen, documenten, webhooks, API-sleutels. Alle routes accepteren een Bearer token en retourneren JSON.
De 52 openbare routes: account, documenten, enveloppen, sjablonen, webhooks, elektronische zegels, API-sleutels en facturering. Allemaal accepteren een Bearer-token en retourneren JSON.
| Methode | Pad | Beschrijving |
|---|---|---|
| GET | /api/v1/account/me | Identiteit van geverifieerde beller (id, e-mailadres, abonnement) : test van identificatie zonder vereist bereik |
| GET | /api/v1/sandbox | De gegevens tellen die met testsleutels zijn aangemaakt (na 30 dagen automatisch verwijderd) |
| DELETE | /api/v1/sandbox | Alle gegevens verwijderen die met testsleutels zijn aangemaakt, zonder de echte gegevens aan te raken |
| POST | /api/v1/documents | PDF uploaden (multipart) : retourneert de document-id |
| GET | /api/v1/documents | Documenten weergeven |
| GET | /api/v1/documents/{id} | Metagegevens van een document lezen |
| DELETE | /api/v1/documents/{id} | Een document verwijderen |
| GET | /api/v1/envelopes | Enveloppen weergeven (filteren met ?status= en ?limit=) |
| POST | /api/v1/envelopes | Een enveloppe maken (status DRAFT) : op basis van een templateId, of van documentIds met een optionele velden-array |
| GET | /api/v1/envelopes/{id} | Status van een enveloppe lezen |
| PATCH | /api/v1/envelopes/{id} | Een DRAFT-enveloppe wijzigen |
| DELETE | /api/v1/envelopes/{id} | Een DRAFT-enveloppe verwijderen (409 na verzending : annuleer in plaats daarvan) |
| POST | /api/v1/envelopes/{id}/send | Een DRAFT-enveloppe verzenden : verstuurt de uitnodigingen |
| POST | /api/v1/envelopes/{id}/void | Een verzonden enveloppe annuleren die nog niet volledig is ondertekend : in afwachting zijnde ondertekenaars worden op de hoogte gesteld |
| GET | /api/v1/envelopes/{id}/audit-trail | PDF van eIDAS-auditlogboek downloaden |
| POST | /api/v1/envelopes/{id}/embed-url | Retourneert de ondertekenings-URL van een ontvanger, voorzien van framingautorisatie voor de gevraagde oorsprong. Aanroepen op het moment van klikken: de autorisatie is twee uur geldig. |
| GET | /api/v1/audit-anchors/{root} | Openbaar : metagegevens van een verankerd auditkavel, of bewijsbestand .ots met ?format=ots (zonder authenticatie) |
| POST | /api/v1/audit-anchors/verify | Openbaar : een auditinvoer en het bewijs ervan verifiëren aan de hand van de verankerde Merkle-wortel (zonder authenticatie, geeft niets prijs) |
| GET | /api/v1/envelopes/{id}/signed-document | Ondertekende PDF downloaden (na COMPLETED) |
| GET | /api/v1/envelopes/bulk | Uw bulk-verzendingen weergeven |
| POST | /api/v1/envelopes/bulk | Massale verzending: N enveloppen maken op basis van een sjabloon en CSV (alleen Standard/Business) |
| GET | /api/v1/envelopes/bulk/{id} | Voortgang van een massale verzending: tellers, fouten per rij, gemaakte enveloppen |
| GET | /api/v1/templates | Herbruikbare envelopsjablonen weergeven |
| POST | /api/v1/templates | Een sjabloon maken (documenten, rollen, gepositioneerde velden) |
| GET | /api/v1/workspaces | Werkruimten weergeven waarin enveloppen kunnen worden aangemaakt |
| POST | /api/v1/sepa-mandates | De PDF van een SEPA-machtiging en de DRAFT-enveloppe ervan genereren, velden al geplaatst |
| POST | /api/v1/payroll-adapters/normalize | Een loonlijst-CSV normaliseren (Silae, Sage Paie, PayFit, Lucca) naar het massale verzendingsformaat |
| POST | /api/v1/ag-copropriete | Een enveloppe voor algemene vergadering van appartementscomplex maken (resoluties en aandelen) |
| POST | /api/v1/ag-copropriete/{envelopeId}/votes | De stemmen van een eigenaar registreren op de resoluties van de vergadering |
| POST | /api/v1/ag-copropriete/{envelopeId}/tally | De vergadering uitsluitend tellen: resultaat per resolutie, gewogen naar aandeel |
| GET | /api/v1/videos/{videoId} | Een bewaarde identiteitsvideo downloaden: GDPR-toegangsrecht (art. 15) |
| GET | /api/v1/webhooks | Webhooks weergeven |
| POST | /api/v1/webhooks | Een webhook registreren: geeft het handtekeningsgeheim eenmalig terug |
| GET | /api/v1/webhooks/{id} | Een webhookabonnement lezen |
| PATCH | /api/v1/webhooks/{id} | URL, gebeurtenissen of actieve status wijzigen |
| DELETE | /api/v1/webhooks/{id} | Webhook verwijderen |
| POST | /api/v1/seals | Een gekwalificeerde elektronische zegel op een document plaatsen |
| GET | /api/v1/seals/{id} | De status van een zegel lezen |
| GET | /api/v1/seals/{id}/certificate | Het zegelbewijs downloaden |
| GET | /api/v1/payslips/workspaces | Loonstrookjes: de ruimten waarvoor deze sleutel distribueert, bezeten of gedelegeerd door een klant (boekhoudkantoren, loonbeheerders) |
| GET | /api/v1/payslips/employees | Loonstrookjes: het register van werknemers, inclusief degenen die elektronische overhandiging hebben geweigerd (papieren strookje verschuldigd) |
| PUT | /api/v1/payslips/employees | Salarislips: werknemers uit het register toevoegen of bijwerken (nooit verwijderen) |
| POST | /api/v1/payslips | Een salarislip (PDF) in de kluis van een werknemer plaatsen: verzegeld, 50 jaar bewaard, opnieuw proberen zonder duplicaat |
| GET | /api/v1/payslips | Toegediende salarislips weergeven met hun consultatiebewijs |
| GET | /api/v1/keys | API-sleutels weergeven |
| POST | /api/v1/keys | Een API-sleutel maken: het geheim wordt slechts eenmaal weergegeven |
| PATCH | /api/v1/keys/{id} | Een sleutel hernoemen of intrekken |
| DELETE | /api/v1/keys/{id} | Een sleutel verwijderen |
| GET | /api/v1/billing/usage | Verbruik van de huidige periode en geraamde kosten |
| GET | /api/v1/status | Servicestatus |
| GET | /api/v1/health | Gezondheidscontrole: database, wachtrij en objectopslag |
| GET | /api/v1/openapi | Machine-leesbare OpenAPI-specificatie |
Enveloppesjablonen
Een sjabloon registreert eenmaal voor altijd de PDF, de rollen en de locatie van ondertekenningsvelden, en wordt vervolgens bij elke verzending hergebruikt: geef de bijbehorende identificatie in templateId door in plaats van documentIds, en de gepositioneerde velden worden naar de gemaakte enveloppe gekopieerd.
- • Sjablonen worden gemaakt via het dashboard (Sjablonen → Nieuw sjabloon), waar u het document uploadt en vervolgens de velden met de muis positioneert — dit is het eenvoudigste pad. De API maakt het ook mogelijk deze via POST /api/v1/templates aan te maken door de documenten, rollen en velden op te geven; let op, velden worden hier met absolute coördinaten gepositioneerd (pagina, x, y, breedte, hoogte), dus u moet de opmaak van de PDF kennen.
- • Op een account dat nog geen sjabloon heeft opgeslagen, retourneert GET /api/v1/templates een lege lijst. Dit is het normale gedrag, geen authenticatieprobleem.
- • De lijst bevat alleen sjablonen die eigendom zijn van de gebruiker die de API-sleutel bezit. Een sjabloon gemaakt door een collega staat daar niet in, zelfs niet binnen een gedeelde werkruimte: genereer de sleutel vanuit het account dat eigenaar is van het sjabloon.
- • templateId en documentIds sluiten elkaar uit: verzend het ene of het ander, nooit beide en nooit geen van beide.
- • Geef minstens zoveel SIGNER-ontvangers op als het sjabloon ondertekeningsrollen heeft, anders wordt het aanmaken in 400 geweigerd. Het veld signerCount dat door de lijst wordt geretourneerd geeft het verwachte aantal aan.
- • Het ondertekeniningsniveau van het sjabloon wordt door de enveloppe overgenomen, tenzij het verzoek expliciet signatureLevel doorgeeft.
# 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.Vanuit Power Automate of Zapier
De actie "Enveloppe aanmaken" van onze no-code connectors dekt alleen het sjabloonpad: het veld Sjabloon is daar verplicht. Voor een ad-hoc-document dat bij elke uitvoering verandert, gebruikt u de actie "Document uploaden" en vervolgens een ruwe HTTP-actie naar POST /api/v1/envelopes met de geretourneerde documentIds.
Documentverzending: twee geaccepteerde vormen
POST /api/v1/documents accepteert het bestand op twee manieren, naar keuze. In beide gevallen gelden dezelfde controles: toegestane typen, limiet van 50 MB, binaire handtekeningverificatie en antivirusscan.
- • In multipart/form-data, met een onderdeel met de naam file. Dit is de klassieke vorm, die van curl -F en van de meeste bibliotheken.
- • In onbewerkte body: de bytes van het bestand vormen de body van de verzoek, en de header Content-Type geeft het type aan (bijvoorbeeld application/pdf). Nuttig van een tool die de inhoud ongewijzigd doorgeeft, zonder het verzoek in te pakken — dit is wat de Power Automate-connector doet.
- • In onbewerkte body heeft de bestandsnaam geen plaats in de body: geef het op via de header X-File-Name of de parameter ?fileName=. Zonder het wordt het document genoemd naar het type.
- • Een niet-ondersteund type reageert 415 met vermelding van de twee geaccepteerde vormen, en een body die als multipart wordt aangekondigd maar onleesbaar is, reageert 400. Geen van beide is een serverfout.
# 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.Plaatsing van ondertekenningsvelden
Zonder sjabloon heeft een enveloppe gemaakt van documentIds geen vooraf gepositioneerde velden: de ondertekenaar ontvangt het document zonder plaats om te ondertekenen. De tabel fields, in dezelfde aanroep doorgegeven, positioneert elk veld tot op het puntje nauwkeurig — dit is het equivalent aan API-zijde van wat een sjabloon eenmaal voor altijd opslaat.
- • De coördinaten zijn in PDF-punten, oorsprong in de linkerbovenhoek van de pagina en Y-as naar beneden (een A4-pagina is 595 × 842 punten groot). x en y geven de linkerbovenhoek van het veld aan, width en height zijn de grootte.
- • pageNumber begint op 1, documentIndex begint op 0. Een paginanummer buiten het document wordt niet bij aanmaak geweigerd: het veld wordt genegeerd op het moment van ondertekening en verschijnt nergens — dit is het eerste wat u moet controleren wanneer een veld niet wordt gevonden.
- • recipientEmail moet overeenkomen met een van de ontvangers in dezelfde aanroep, zonder onderscheid naar hoofdletters. Anders mislukt het aanmaken en worden alle foutieve rijen vermeld, wat het corrigeren ervan één voor één voorkomt.
- • fields en templateId sluiten elkaar uit: een sjabloon bevat al zijn eigen opmaak. De tabel fields wordt dus alleen gebruikt met documentIds.
- • Geaccepteerde typen: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX en RADIO_GROUP. required is standaard true; placeholder en dateFormat zijn optioneel, en options wordt alleen gebruikt voor RADIO_GROUP.
- • Een enveloppe accepteert maximaal 100 velden, 20 documenten en 50 ontvangers — de limieten van uw plan kunnen lager zijn.
# 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.Tekstankers: een veld plaatsen zonder coördinaten te kennen
In plaats van coördinaten kan een veld een in het document afgedrukte tekst aanhalen: anchorText vindt het in de PDF en de server berekent de positie bij aanmaak. Dit is de modus die de voorkeur verdient wanneer het document bij elke verzending opnieuw wordt gegenereerd — adresseringsdruk, contractgenerator — omdat de pagina-indeling verschuift terwijl de vermelding « Handtekening van de klant » blijft staan. anchorPlacement geeft aan aan welke kant van de tekst het veld wordt geplaatst (standaard right, anders below, above of left) en anchorIndex kiest de voorvallen wanneer de tekst meerdere keren voorkomt.
x en y blijven verplicht, zelfs met een anker: ze dienen als terugval. Een anker dat niet kan worden gevonden, leidt niet tot mislukking van de aanmaak — het veld behoudt de letterlijke positie die u hebt opgegeven, zonder fout of waarschuwing in het antwoord. Geef daarom een waarschijnlijke terugval op in plaats van 0,0 en controleer de weergave bij een eerste verzending.
Geïntegreerde handtekening: ondertekenen zonder uw toepassing te verlaten
Uw klant raadpleegt en ondertekent zijn document vanuit uw eigen interface. De ceremonie opent zich in een venster boven uw pagina en hij keert automatisch bij u terug zodra deze is voltooid. Aan serverzijde niets nieuws: u maakt de envelop zoals gewoonlijk aan door redirectUrl in te vullen en vertrouwt het SDK de handtekening-URL van de ontvanger toe.
- • Roep Certyneo.sign() rechtstreeks in uw klikhandler aan en geef uw serveroproep door via getUrl. Een await vóór sign() treedt uit de gebruikersgebaar: Safari en Firefox blokkeren dan het venster. Het SDK opent het onmiddellijk en laadt het wanneer uw belofte wordt opgelost.
- • redirectUrl is het retourkanaal. We sturen de ondertekenaar daarheen terug door certyneo_status (completed of declined) en certyneo_envelope toe te voegen. Laad hetzelfde script op deze retourpagina: dit is het dat het portalvenster dat achter is gebleven in kennis stelt.
- • In embedded mode zijn onze eigen call-to-action-elementen verborgen. Uw klant ziet nooit een uitnodiging om een Certyneo-account aan te maken.
- • Als de browser het venster weigert, schakelt de SDK automatisch over naar volledige paginaredirectie. Het parcours is identiek voor de ondertekenaar en uw retourpagina ontvangt exact dezelfde parameters.
- • Er bestaat opzettelijk geen callback "de gebruiker heeft het verlaten": de status van het venster is niet leesbaar vanaf uw pagina, en zo'n callback zou ten onrechte worden geactiveerd. Een handtekening die niet wordt voltooid, blijft in behandeling totdat de webhook wordt ontvangen.
// 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.De browsergebeurtenis is geen bewijs van ondertekening
onCompleted is een weergavesignaal, verzonden door een browser en dus vervalst door iedereen vanaf zijn console. Schakel een dossier nooit om naar "ondertekend" op basis hiervan: gebruik het om het scherm te vernieuwen en vertrouw op de ondertekende webhook envelope.completed die uw server ontvangt voor de werkelijke status. Dit is de klassieke valkuil van betalingsintegraties, en het herhaalt zich hier identiek.
Ontwikkelen op uw computer
Met een testsleutel accepteert redirectUrl http://localhost (en 127.0.0.1): u bouwt het volledige parcours op uw machine voordat u het implementeert. Een echte sleutel weigert dit, zodat geen productie-envelop een echte ondertekenaar terugverwijst naar een machine die niet van hem is.
Toon de ceremonie op uw pagina
De framemodus geeft de handtekening weer in uw interface, zonder venster. Het vereist één stap meer dan de venstermodus: bewijzen dat de site die het weergeeft van u is. Dit voorkomt dat een derde onze ceremonies in een frame plaatst om uw klanten te misleiden.
- • Declareer uw site in Instellingen → Geïntegreerde handtekening, en publiceer de aangegeven DNS-record. Een exact adres: een subdomein of ander poort telt als een ander site.
- • Bij elke handtekening vraagt u om een verse URL naar POST /api/v1/envelopes/{id}/embed-url. Deze draagt de weergavemachtiging en is twee uur geldig, wat overeenkomt met het moment van klikken, niet met het moment van creatie van de envelop.
- • Twee trajecten kunnen niet in een frame plaatsvinden: de gekwalificeerde handtekening, waarvan de identiteitsverificatie weigert ook in een frame te worden geplaatst, en betaling bij handtekening. In beide gevallen wordt de ondertekenaar naar een volledig venster geleid.
- • Het bericht "Aangedreven door Certyneo" verdwijnt uit het frame vanaf het Business-plan. De framemodus zelf is inbegrepen vanaf het Standard-plan.
// 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.Laten ondertekenen zonder dat er e-mail wordt verzonden
Een portaal dat de ceremonie bij hem weergeeft heeft vaak onze uitnodiging niet nodig: deze arriveert naast zijn eigen pad en stelt een account voor aan een klant die dat niet wil. Geef de waarde NONE aan het meldingskanaal van een ontvanger en niets meer wordt hem verzonden — u brengt hem naar zijn ondertekening.
- • De instelling is per ontvanger, niet per envelop: u kunt de klant die u host tot zwijgen brengen en het e-mailbericht behouden voor een externe medeverantwoordelijke, die geen portaal heeft.
- • Het is voorbehouden aan ondertekenaars en fiatteurs, de enigen aan wie u een link moet bezorgen. U leest het in de response van creatie en verzending, of u vraagt een verse URL aan op het moment van klikken op POST /api/v1/envelopes/{id}/embed-url.
- • Automatische herinneringen stoppen vanzelf voor deze ontvanger: we hebben hem nooit geschreven, we beginnen niet met een herinnering. De andere ontvangers worden normaal gesproken herinnerd.
- • Het ondertekenningscertificaat vermeldt dit, per ontvanger. Een auditdossier dat hier stil zou zijn, zou kunnen doen geloven dat deze ondertekenaar een uitnodiging van ons heeft ontvangen die nooit heeft bestaan.
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.Geef de naam van uw klant weer als afzender
Standaard leest de ondertekenaar de naam van de API-sleuteleigenaar. Als u documenten van meerdere bedrijven met één sleutel laat ondertekenen, geef dan het veld afzender door bij het maken van de envelop: de handtekenenpagina en de uitnodigings- en herinneringsberichten tonen dan de naam van het betrokken bedrijf.
- • Gereserveerd voor het Business-plan en hoger. Voor een lager plan wordt het maken geweigerd in plaats van de ondertekenaar een ander dan de verwachte naam te laten zien.
- • De naam is een weergave: het certificaat en het audittrail behouden de echte afzender, en e-mails gaan altijd vanaf Certyneo.
- • Het adres is optioneel. Zonder deze ziet de ondertekenaar alleen de naam, nooit het adres van de API-sleuteleigenaar.
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"
}
}Authenticatie
Elk verzoek bevat een API-sleutel in de Authorization-header. Sleutels worden gegenereerd via Instellingen → API-sleutels en worden slechts eenmaal weergegeven.
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" } }- • Formaat: sk_live_… in productie, sk_test_… voor de sandbox. Header: Authorization: Bearer <clé>.
- • Bereiken: envelopes, documents, webhooks, seals — in leesmodus (:read) of schrijfmodus (:write). Schrijven impliceert lezen; het bereik * geeft alle rechten.
- • sk_test_-sleutels maken resources in de sandbox aan, uitgesloten van quota en facturering. Er wordt geen echte e-mail naar de ontvanger verstuurd, tenzij het adres overeenkomt met het e-mailadres van het verzendende account — handig om de volledige flow op uzelf te testen.
- • Fouten: 401 ongeldige sleutel, 403 onvoldoende bereik, 429 snelheidslimiet overschreden, 402 maandelijks quota bereikt.
Vorm van antwoorden
Een belangrijk punt voordat u uw client schrijft: collecties zijn ingekapseld in een data-object, terwijl individuele resources volledig worden geretourneerd. Het lezen van response.data.data op een individuele resource retourneert dus 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": [ /* … */ ]
}De limieten garanderen stabiele servicekwaliteit voor alle klanten. Neem contact met ons op als u meer nodig hebt.
100 verzoeken per minuut per API-sleutel
- • 100 verzoeken per minuut per API-sleutel
- • Een piek van maximaal 200 verzoeken in minder dan 10 seconden wordt getolereerd
- • Respons 429 met header Retry-After die de vertraging in seconden aangeeft