Gå til hovedinnhold
Certyneo
Offentlig API v1

Integrer elektronisk signatur i din stack

Send konvolutter, spor signaturer, motta webhooks. Enkel REST API, OpenAPI 3.0, curl/Node/Python-eksempler — alt du trenger for å koble Certyneo til din HRIS, CRM eller bedriftsprogramvare på få timer.

Rask start

Tre steg: opprett en API-nøkkel fra innstillingene, koder din PDF i base64, send. Svaret inneholder `signUrl` som du kan dele direkte med mottakeren.

cURLbash
# 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"
JavaScript / Nodets
// 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);
Pythonpython
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"])

Prøv API-en fra verktøyene dine

Postman-samlingen og RapidAPI-arket genereres fra OpenAPI-spesifikasjonen som også dokumenterer denne siden. De tre forblir derfor justert på det faktiske APIet, endpoint for endpoint, i stedet for å divergere ved første tillegg.

Postman-samling

De 25 forespørslene organisert etter domene — konvolutter, dokumenter, maler, sealer, webhooks — med et eksempel på kropp og svar for hver. Lim inn nøkkelen din i apiKey-variabelen i samlingen, deretter kjør GET /health: den krever ingen autentisering og bekrefter at konfigurasjonen din er god før det første autentiserte anropet.

RapidAPI-ark

Det samme katalog over endpoints, testable direkte fra nettleseren. Testbenken forventer to distinkte overskrifter: RapidAPI-nøkkelen som plattformen tildeler deg, og din Certyneo-nøkkel i Authorization — det er den andre som faktisk autoriserer anropet.

Konvolutter

Oppretting, sending, statussporing, avlysning. En konvolutt kan inneholde flere dokumenter og flere underskrivere (parallelt eller sekvensielt).

Webhooks

Alle konvolutt- og mottakerhendelser (`envelope.sent`, `recipient.signed`, `envelope.completed`…) levert til URL-en du velger — komplett liste på /developers/webhooks. HMAC SHA-256 på hver last for å verifisere opprinnelsen.

Enkel autentisering

Bearer token. En nøkkel per miljø (test / prod). Kan tilbakekalles øyeblikkelig. Grense på 100 forespørsler/min/nøkkel, burst på 200, ren 429-respons med Retry-After-header.

Tilgjengelige endepunkter

Alle offentlige ruter: konto, dokumenter, konvolutter, maler, webhooker, elektroniske segl, API-nøkler og fakturering. Alle godtar et Bearer-token og returnerer JSON.

MethodPathDescription
GET/api/v1/account/meIdentity of the authenticated caller (id, email, plan) — scope-less credential probe
POST/api/v1/documentsUpload a PDF (multipart) — returns document id
GET/api/v1/documentsList documents
GET/api/v1/documents/{id}Fetch document metadata
DELETE/api/v1/documents/{id}Delete document
GET/api/v1/envelopesList envelopes (filter with ?status= and ?limit=)
POST/api/v1/envelopesCreate 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}/sendDispatch DRAFT — sends invitations
GET/api/v1/envelopes/{id}/audit-trailDownload 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/verifyPublic: verify an audit entry + proof against its anchored Merkle root (no auth, reveals nothing)
GET/api/v1/envelopes/{id}/signed-documentDownload signed PDF (once COMPLETED)
GET/api/v1/envelopes/bulkList your bulk-send jobs
POST/api/v1/envelopes/bulkBulk 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/templatesList reusable envelope templates
POST/api/v1/templatesCreate a template (documents, roles, positioned fields)
POST/api/v1/sepa-mandatesGenerate a SEPA mandate PDF and its DRAFT envelope, fields already placed
POST/api/v1/payroll-adapters/normalizeNormalise a payroll CSV (Silae, Sage Paie, PayFit, Lucca) into the bulk-send shape
POST/api/v1/ag-coproprieteCreate a condominium general-meeting envelope (resolutions + ownership shares)
POST/api/v1/ag-copropriete/{envelopeId}/votesRecord a co-owner's votes on the meeting resolutions
POST/api/v1/ag-copropriete/{envelopeId}/tallyTally 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/webhooksList webhooks
POST/api/v1/webhooksRegister 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/sealsApply a qualified electronic seal to a document
GET/api/v1/seals/{id}Fetch seal status
GET/api/v1/seals/{id}/certificateDownload the seal certificate
GET/api/v1/keysList API keys
POST/api/v1/keysCreate 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/usageCurrent period usage and projected cost
GET/api/v1/statusService status
GET/api/v1/openapiMachine-readable OpenAPI specification

Modeller av udløpsområder

En mal registrerer en gang for alle PDF-en, rollene og plasseringen av signeringsfeltene, og blir deretter gjenbrukt ved hver sending: send identifikatoren i templateId i stedet for documentIds, og de posisjonerte feltene kopieres til den opprettede konvolutten.

  • Maler opprettes fra dashbordet (Maler → Ny mal), der du laster opp dokumentet og posisjonerer feltene med musen — dette er den enkleste måten. API-et tillater også å opprette dem via POST /api/v1/templates, ved å gi dokumentene, rollene og feltene; vær oppmerksom på at feltene der er posisjonert i absolutte koordinater (side, x, y, bredde, høyde), så du må kjenne PDF-layouten.
  • På en konto som ennå ikke har registrert noen mal, returnerer GET /api/v1/templates en tom liste. Dette er normal oppførsel, ikke en autentiseringsfeil.
  • Listen inneholder bare maler som tilhører brukeren som eier API-nøkkelen. En mal opprettet av en kollega er ikke oppført, selv innenfor et delt arbeidsområde: generer nøkkelen fra kontoen som eier malen.
  • templateId og documentIds utelukker hverandre: send enten det ene eller det andre, aldri begge eller ingen av dem.
  • Oppgi minst like mange mottakere av typen SIGNER som malen har underskriverroller, ellers blir opprettelsen avvist med 400. Feltet signerCount som returneres av listen indikerer det forventede antallet.
  • Signeringsnivået til malen arves av konvolutten, med mindre forespørselen eksplisitt sender signatureLevel.
cURLbash
# 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.

Fra Power Automate eller Zapier

Handlingen «Opprett en konvolutt» i koblingsverktøyene våre uten kode dekker bare malveien: Mal-feltet er obligatorisk der. For et ad hoc-dokument som endres ved hver kjøring, bruk handlingen «Last opp et dokument» og deretter en rå HTTP-handling til POST /api/v1/envelopes ved å sende den returnerte documentIds.

Dokumentsending: to former godtatt

POST /api/v1/documents godtar filen på to måter, etter eget valg. De samme kontrollene gjelder i begge tilfeller: autoriserte typer, 50 MB-grense, verifisering av binær signatur og antivirusanalyse.

  • I multipart/form-data, med en del kalt file. Dette er den klassiske formen, den fra curl -F og de fleste biblioteker.
  • I rå brødtekst: filens bytes utgjør kallet brødteksten, og Content-Type-hodet angir typen (for eksempel application/pdf). Nyttig fra et verktøy som sender innholdet som det er, uten å pakke inn kallet — det er det Power Automate-koblingen gjør.
  • I rå brødtekst har filnavnet ingen plass i brødteksten: angi det via X-File-Name-hodet eller ?fileName=-parameteren. Uten det blir dokumentet kalt etter typen.
  • En type som ikke støttes, svarer 415 ved å navngi de to aksepterte formene, og en brødtekst annonsert som multipart men ulleselig svarer 400. Ingen av dem er en serverfeil.
cURLbash
# 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.

Placering av signaturregistreringsfelter

Uten mal har en konvolutt opprettet fra documentIds ingen forhåndsstilte felt: underskriveren mottar dokumentet uten et sted å signere. Arrayen fields, overført i samme opprettelseskall, plasserer hvert felt punktfast — det er ekvivalenten på API-siden av det en mal registrerer en gang for alle.

  • Koordinatene er i PDF-punkter, opprinnelse øverst til venstre på siden og Y-aksen peker nedover (en A4-side måler 595 × 842 punkter). x og y angir øvre venstre hjørne av feltet, width og height angir størrelsen.
  • pageNumber starter på 1, documentIndex starter på 0. Et sidenummer utenfor dokumentet blir ikke avvist ved opprettelse: feltet ignoreres på signeringstidspunktet og vises ingensteds — det er det første å kontrollere når et felt mangler i kallet.
  • recipientEmail må samsvare med en av mottakerne fra samme kall, uten skille mellom små og store bokstaver. Ellers mislykkes opprettelsen ved å liste alle feilaktige linjer, noe som unngår å korrigere dem en etter en.
  • fields og templateId utelukker hverandre gjensidig: en mal har allerede sitt eget oppsett. Arrayen fields brukes derfor bare med documentIds.
  • Godtatte typer: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX og RADIO_GROUP. required er true som standard; placeholder og dateFormat er valgfri, og options blir kun tatt med for RADIO_GROUP.
  • En konvolutt godtar maksimalt 100 felt, 20 dokumenter og 50 mottakere — grensene for planen din kan være lavere.
cURLbash
# 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.

Tekstanker: plassere et felt uten å kjenne koordinatene

I stedet for koordinater kan et felt sitere en tekst som er skrevet ut i dokumentet: anchorText finner den i PDF-en og serveren beregner posisjonen ved opprettelse. Dette er modus som foretrekkes når dokumentet regenereres ved hver sending — brevkombinasjon, kontraktsgenerator — fordi oppsettet endres mens merknaden «Kundens signatur» forblir. anchorPlacement angir hvilken side av teksten feltet plasseres (right som standard, ellers below, above eller left) og anchorIndex velger forekomsten når teksten vises flere ganger.

x og y forblir obligatoriske selv med et anker: de tjener som tilbakefall. Et anker som ikke blir funnet, gjør ikke opprettelsen mislykkes — feltet beholder den bokstavelige posisjonen du oppga, uten feil eller advarsel i svaret. Gi derfor et plausibelt tilbakefall i stedet for 0,0, og kontroller gjengivelsen på en første sending.

Autentisering

Hvert anrop inneholder en API-nøkkel i Authorization-headeren. Nøkler genereres fra Innstillinger → API-nøkler og vises bare én gang.

HTTPhttp
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_… i produksjon, sk_test_… for sandkassen. Header: Authorization: Bearer <nøkkel>.
  • Omfang: envelopes, documents, webhooks, seals — i lesing (:read) eller skriving (:write). Skriving innebærer lesing; omfanget * gir alle rettigheter.
  • Nøkler sk_test_ oppretter ressurser i sandkassen, ekskludert fra kvoten og faktureringen. Det sendes ingen ekte e-post til mottakeren, med mindre adressen samsvarer med den sendende kontoens e-post — nyttig for å teste hele flyten på deg selv.
  • Feil: 401 ugyldig nøkkel, 403 utilstrekkelig omfang, 429 hastighetsgrense overskredet, 402 månedlig kvote nådd.

Formen på svar

Et poeng å vite før du skriver klienten din: samlinger er innkapslet i et dataobjekt, mens enhetlige ressurser returneres flatt. Lesing av response.data.data på en enhetlig ressurs returnerer derfor undefined.

Samling — pakketjson
// GET /api/v1/envelopes
// Collections are WRAPPED in a "data" array.
{
  "data": [
    { "id": "env_abc123", "subject": "Contrat", "status": "SENT" }
  ]
}
Enhetlig resurs — flatjson
// GET /api/v1/envelopes/{id}
// Single resources are returned FLAT — no "data" envelope.
{
  "id": "env_abc123",
  "subject": "Contrat",
  "status": "COMPLETED",
  "recipients": [ /* … */ ]
}

Gjennomstrømningsgrenser

Grensene garanterer stabil servicekvalitet for alle klienter. Hvis du trenger mer, kontakt oss.

  • 100 forespørsler per minutt per API-nøkkel
  • Burst tolerert opp til 200 forespørsler på mindre enn 10 sekunder
  • 429-respons med Retry-After-header som angir forsinkelsen i sekunder