Integrați semnătura electronică în stack-ul dvs.
Trimiteți pluve, urmăriți semnăturile, primiți webhooks. API REST simplu, OpenAPI 3.0, exemple curl/Node/Python — tot ceea ce trebuie pentru a conecta Certyneo la HRIS, CRM sau software-ul dvs. în câteva ore.
Trei pași: creați o cheie API din setări, codificați PDF-ul în base64, trimiteți. Răspunsul conține `signUrl` pe care îl puteți partaja direct cu destinatarul.
Pluve
# 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"])Încercați API-ul din instrumentele dumneavoastră
Colecția Postman și fișa RapidAPI sunt generate din specificația OpenAPI care documentează și această pagină. Cele trei rămân deci aliniate cu API-ul real, endpoint cu endpoint, în loc să diverge la primul adaos.
Colecția Postman
Cele 25 de cereri aranjate după domeniu — plicuri, documente, șabloane, sigilii, webhook-uri — cu un exemplu de corp și răspuns pentru fiecare. Lipiți cheia dumneavoastră în variabila apiKey a colecției, apoi lansați GET /health: nu necesită nicio autentificare și confirmă că configurația dumneavoastră este bună înainte de primul apel autentificat.
Creație, trimitere, urmărire de stare, anulare. O pluă poate conține mai multe documente și mai mulți semnatari (paralel sau secvențial).
Webhooks
Primiți `envelope.created`, `envelope.completed`, `envelope.declined` pe URL-ul dvs. HMAC SHA-256 pe fiecare payload pentru a verifica originea.
Toate evenimentele de plic și destinatar (`envelope.sent`, `recipient.signed`, `envelope.completed`…) livrate la URL-ul dvs. de alegere — listă completă pe /developers/webhooks. HMAC SHA-256 pe fiecare sarcină pentru a verifica originea.
Autentificare simplă
Token de tip „bearer”. O cheie pentru fiecare mediu (test / producție). Revocabilă instantaneu. Limită de 100 de solicitări/minut/cheie, vârf de 200, 429 propriu cu antetul Retry-After.
12 rute acoperind ciclul complet: pluve, documente, webhooks, chei API. Toate rutele acceptă Bearer token și returnează JSON.
Toate rutele publice: cont, documente, plicuri, șabloane, webhooks, ștampile electronice, chei API și facturare. Toate acceptă un token Bearer și returnează JSON.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/account/me | Identity of the authenticated caller (id, email, plan) — scope-less credential probe |
| POST | /api/v1/documents | Upload a PDF (multipart) — returns document id |
| GET | /api/v1/documents | List documents |
| GET | /api/v1/documents/{id} | Fetch document metadata |
| DELETE | /api/v1/documents/{id} | Delete document |
| GET | /api/v1/envelopes | List envelopes (filter with ?status= and ?limit=) |
| POST | /api/v1/envelopes | Create envelope (status: DRAFT) — from a templateId, or from documentIds with an optional fields array |
| GET | /api/v1/envelopes/{id} | Fetch envelope state |
| PATCH | /api/v1/envelopes/{id} | Update DRAFT envelope |
| DELETE | /api/v1/envelopes/{id} | Void / delete DRAFT envelope |
| POST | /api/v1/envelopes/{id}/send | Dispatch DRAFT — sends invitations |
| GET | /api/v1/envelopes/{id}/audit-trail | Download eIDAS audit-trail PDF |
| GET | /api/v1/audit-anchors/{root} | Public: metadata of an anchored audit batch, or the .ots proof file with ?format=ots (no auth) |
| POST | /api/v1/audit-anchors/verify | Public: verify an audit entry + proof against its anchored Merkle root (no auth, reveals nothing) |
| GET | /api/v1/envelopes/{id}/signed-document | Download signed PDF (once COMPLETED) |
| GET | /api/v1/envelopes/bulk | List your bulk-send jobs |
| POST | /api/v1/envelopes/bulk | Bulk send: create N envelopes from one template + a CSV (Standard/Business only) |
| GET | /api/v1/envelopes/bulk/{id} | Bulk-send job progress: counts, per-row failures, created envelopes |
| GET | /api/v1/templates | List reusable envelope templates |
| POST | /api/v1/templates | Create a template (documents, roles, positioned fields) |
| POST | /api/v1/sepa-mandates | Generate a SEPA mandate PDF and its DRAFT envelope, fields already placed |
| POST | /api/v1/payroll-adapters/normalize | Normalise a payroll CSV (Silae, Sage Paie, PayFit, Lucca) into the bulk-send shape |
| POST | /api/v1/ag-copropriete | Create a condominium general-meeting envelope (resolutions + ownership shares) |
| POST | /api/v1/ag-copropriete/{envelopeId}/votes | Record a co-owner's votes on the meeting resolutions |
| POST | /api/v1/ag-copropriete/{envelopeId}/tally | Tally the meeting - per-resolution result weighted by ownership shares |
| GET | /api/v1/videos/{videoId} | Download a stored identity video - GDPR art. 15 access path |
| GET | /api/v1/webhooks | List webhooks |
| POST | /api/v1/webhooks | Register webhook — returns the signing secret once |
| GET | /api/v1/webhooks/{id} | Fetch webhook subscription |
| PATCH | /api/v1/webhooks/{id} | Update url / events / active state |
| DELETE | /api/v1/webhooks/{id} | Unregister |
| POST | /api/v1/seals | Apply a qualified electronic seal to a document |
| GET | /api/v1/seals/{id} | Fetch seal status |
| GET | /api/v1/seals/{id}/certificate | Download the seal certificate |
| GET | /api/v1/keys | List API keys |
| POST | /api/v1/keys | Create API key — the secret is shown once |
| PATCH | /api/v1/keys/{id} | Rename / revoke key |
| DELETE | /api/v1/keys/{id} | Delete key |
| GET | /api/v1/billing/usage | Current period usage and projected cost |
| GET | /api/v1/status | Service status |
| GET | /api/v1/openapi | Machine-readable OpenAPI specification |
Modeluri de înveliș
Un șablon înregistrează o dată pentru totdeauna PDF-ul, rolurile și locația câmpurilor de semnare, apoi se reutilizează la fiecare trimitere: transmiteți identificatorul acestuia în templateId în loc de documentIds, iar câmpurile poziționate sunt recopiate pe plicul creat.
- • Șabloanele se creează din tabloul de bord (Șabloane → Șablon nou), unde depuneți documentul și apoi poziționați câmpurile cu mouse-ul — acesta este calea cea mai simplă. API permite și crearea lor prin POST /api/v1/templates, furnizând documentele, rolurile și câmpurile; atenție, câmpurile sunt poziționate în coordonate absolute (pagină, x, y, lățime, înălțime), deci trebuie să cunoașteți aspectul PDF-ului.
- • Pe un cont care nu a înregistrat încă nici un șablon, GET /api/v1/templates returnează o listă goală. Acesta este comportamentul normal, nu o eroare de autentificare.
- • Lista conține doar șabloanele aparținând utilizatorului proprietar al cheii API. Un șablon creat de un coleg nu apare pe ea, chiar și într-un spațiu de lucru partajat: generați cheia din contul care deține șablonul.
- • templateId și documentIds se exclud reciproc: trimiteți unul sau altul, niciodată amândoi nici nici una din ele.
- • Furnizați cel puțin atât de mulți destinatari SIGNER cât are șablonul roluri semnătare, altfel crearea este respingă cu 400. Câmpul signerCount returnat de listă indică numărul așteptat.
- • Nivelul de semnătură al modelului este moștenit de către plic, decât dacă cererea transmite în mod explicit 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.De la Power Automate sau Zapier
Acțiunea « Creează un plic » din conectoarele noastre fără cod acoperă doar calea după model: câmpul Model este obligatoriu. Pentru un document ad hoc care se schimbă la fiecare execuție, utilizați acțiunea « Încărcă un document » apoi o acțiune HTTP brută către POST /api/v1/envelopes transmițând documentIds-ul returnat.
Trimiterea documentului: două forme acceptate
POST /api/v1/documents acceptă fișierul în două moduri, la alegere. Aceleași controale se aplică în ambele cazuri: tipuri autorizate, plafon de 50 Mo, verificarea semnăturii binare și analiză antivirus.
- • În multipart/form-data, cu o parte numită file. Aceasta este forma clasică, cea a curl -F și a majorității bibliotecilor.
- • În corp brut: octeții fișierului constituie corpul cererii, iar antetul Content-Type indică tipul acestuia (application/pdf de exemplu). Util din parte unui instrument care transmite conținutul în forma lui brută, fără a înfășura cererea — aceasta este ceea ce face conectorul Power Automate.
- • În corp brut, numele fișierului nu are loc în corp: indicați-l prin antetul X-File-Name sau prin parametrul ?fileName=. Fără acesta, documentul este numit după tipul său.
- • Un tip nesuportat răspunde 415 numind cele două forme acceptate, iar un corp anunțat ca multipart dar ilizibil răspunde 400. Nici unul dintre acestea nu este o eroare de server.
# 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.Plasarea campurilor de semnare
Fără model, un plic creat din documentIds nu are niciun câmp pre-poziționat: semnatarul primește documentul fără un loc unde să semneze. Tabloul fields, transmis în același apel de creare, plasează fiecare câmp la punct exact — este echivalentul, pe partea API, a ceea ce un model înregistrează o dată pentru totdeauna.
- • Coordonatele sunt în puncte PDF, originea în colțul din stânga sus al paginii și axa Y în jos (o pagină A4 măsoară 595 × 842 puncte). x și y desemnează colțul din stânga sus al câmpului, width și height dimensiunea acestuia.
- • pageNumber începe de la 1, documentIndex începe de la 0. Un număr de pagină dincolo de document nu este respins la creare: câmpul este ignorat la momentul semnării și nu apare nicăieri — aceasta este primul lucru de verificat atunci când un câmp lipsește apelului.
- • recipientEmail trebuie să corespundă unuia dintre destinatarii din același apel, fără distincție între majuscule și minuscule. Altfel, crearea eșuează prin enumerarea tuturor liniilor defectuoase, ceea ce evită corectarea lor una după alta.
- • fields și templateId se exclud reciproc: un model poartă deja propria sa punere în pagină. Tabloul fields se utilizează deci doar cu documentIds.
- • Tipuri acceptate: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX și RADIO_GROUP. required valorează true în mod implicit; placeholder și dateFormat sunt opționale, iar options este reținut doar pentru RADIO_GROUP.
- • Un plic acceptă maximum 100 de câmpuri, 20 de documente și 50 de destinatari — limitele planului dvs. putând fi mai mici.
# 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.Ancore de text: plasați un câmp fără a cunoaște coordonatele
Mai degrabă decât coordonate, un câmp poate cita un text imprimat în document: anchorText îl localizează în PDF și serverul calculează poziția la creare. Acesta este modul de preferat atunci când documentul este regenerat la fiecare trimitere — litere cu corespondență, generator de contracte — deoarece punerea în pagină se mișcă în timp ce menționarea « Semnătura clientului » rămâne. anchorPlacement indică de ce parte a textului se plasează câmpul (right în mod implicit, altfel below, above sau left) și anchorIndex alege apariția atunci când textul apare de mai multe ori.
x și y rămân obligatorii chiar și cu o ancoră: servesc ca rezervă. O ancoră nelocalizată nu face ca crearea să eșueze — câmpul păstrează poziția literală pe care ați furnizat-o, fără eroare sau avertisment în răspuns. Indicați deci o rezervă plauzibilă mai degrabă decât 0,0, și verificați redarea pe o primă trimitere.
Autentificare
Fiecare apel poartă o cheie API în antetul Authorization. Cheile se generează din Setări → Chei API și sunt afișate o singură dată.
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" } }- • Format: sk_live_… în producție, sk_test_… pentru sandbox. Antet: Authorization: Bearer <clé>.
- • Domenii: envelopes, documents, webhooks, seals — în citire (:read) sau scriere (:write). Scrierea implică citirea; domeniul * acordă toate drepturile.
- • Cheile sk_test_ creează resurse în sandbox, excluse din cotă și factură. Niciun e-mail real nu este trimis destinatarului, cu excepția cazului în care adresa acestuia se potrivește cu e-mailul contului expeditor — util pentru a testa fluxul complet pe tine însuți.
- • Erori: 401 cheie nevalidă, 403 domeniu insuficient, 429 limită de debit depășită, 402 cotă lunară atinsă.
Forma răspunsurilor
Un punct de cunoscut înainte de a scrie clientul dvs.: colecțiile sunt încapsulate într-un obiect data, în timp ce resursele unitare sunt returnate plat. Citirea response.data.data pe o resursă unitară returnează deci 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": [ /* … */ ]
}Limitele garantează o calitate de serviciu stabilă pentru toți clienții. Dacă aveți nevoie de mai mult, contactați-ne.
100 cereri pe minut pe cheie API
- • 100 de solicitări pe minut per cheie API
- • Se tolerează un vârf de trafic de până la 200 de solicitări în mai puțin de 10 secunde
- • Răspuns 429 cu antet Retry-After indicând întârzierea în secunde