Gå till huvudinnehål
Certyneo
Offentligt API v1

Integrera elektronisk signatur i din stack

Skicka kuvert, följ signaturer, ta emot webhooks. Enkelt REST API, OpenAPI 3.0, curl/Node/Python-exempel — allt för att koppla Certyneo till din HRIS, CRM eller affärsmjukvara på några timmar.

Snabbstart

Tre steg: skapa en API-nyckel från inställningarna, koda din PDF i base64, skicka. Svaret innehåller `signUrl` som du kan dela direkt med mottagaren.

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"])

Prova API:et från dina verktyg

Postman-samlingen och RapidAPI-arket genereras från OpenAPI-specifikationen som också dokumenterar denna sida. De tre förblir därför justerade med det verkliga API:et, endpoint för endpoint, snarare än att divergera vid första tillägg.

Postman-samling

De 25 förfrågningarna organiserade efter domän — kuvert, dokument, mallar, sigill, webhooks — med ett exempel på brödtext och svar för var och en. Klistra in din nyckel i samlingens apiKey-variabel och kör sedan GET /health: den kräver ingen autentisering och bekräftar att din konfiguration är bra före det första autentiserade anropet.

RapidAPI-ark

Samma katalog över endpoints, testbar direkt från webbläsaren. Testbänken förväntar två distinkta huvuden: RapidAPI-nyckeln som plattformen tilldelar dig och din Certyneo-nyckel i Authorization — det är den andra som faktiskt autentiserar anropet.

Kuvert

Skapande, sändning, statusövervakning, annullering. Ett kuvert kan innehålla flera dokument och flera undertecknare (parallell eller sekventiell).

Webbooks

Alla kuvert- och mottagarhändelser (`envelope.sent`, `recipient.signed`, `envelope.completed`…) levererade till din valda URL — komplett lista på /developers/webhooks. HMAC SHA-256 på varje payload för att verifiera ursprunget.

Enkel autentisering

Bearer-token. En nyckel per miljö (test / prod). Återkallningsbar omedelbar. Gräns 100 req/min/nyckel, burst på 200, ren 429 med Retry-After-rubrik.

Tillgängliga endpoints

Alla offentliga vägar: konto, dokument, kuvert, mallar, webhooks, elektroniska sigill, API-nycklar och fakturering. Alla accepterar en Bearer-token och returnerar 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

Modell för innehållskapsul

En mall registrerar en gång för alla PDF-filen, rollerna och placeringen av signeringsfält, och återanvänds sedan vid varje sändning: skicka dess identifierare i templateId istället för documentIds, och de positionerade fälten kopieras om på det skapade kuvertet.

  • Mallar skapas från instrumentpanelen (Mallar → Ny mall), där du överför dokumentet och placerar sedan fälten med musen — det är det enklaste sättet. API:et tillåter också att skapa dem via POST /api/v1/templates, genom att tillhandahålla dokument, roller och fält; notera att fält där positioneras i absoluta koordinater (sida, x, y, bredd, höjd), så du måste känna till PDF:ens layout.
  • På ett konto som ännu inte har registrerat någon mall returnerar GET /api/v1/templates en tom lista. Det är normalt beteende, inte en autentiseringsfel.
  • Listan innehåller endast mallar som tillhör användaren som äger API-nyckeln. En mall som skapats av en kollega finns inte i listan, även inom en delad arbetsyta: generera nyckeln från kontot som äger mallen.
  • templateId och documentIds är ömsesidigt uteslutande: skicka antingen det ena eller det andra, aldrig båda eller inget av dem.
  • Ange minst lika många SIGNER-mottagare som mallen har undertecknarroller, annars nekas skapandet med 400. Fältet signerCount som returneras av listan anger det förväntade antalet.
  • Mallens signeringsnivå ärvs av kuvertet, såvida inte begäran uttryckligen skickar 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.

Från Power Automate eller Zapier

Åtgärden "Skapa ett kuvert" för våra no-code-anslutningar täcker endast mallvägen: fältet Mall är obligatoriskt där. För ett ad hoc-dokument som ändras vid varje körning, använd åtgärden "Ladda upp ett dokument" och sedan en rå HTTP-åtgärd till POST /api/v1/envelopes genom att skicka det returnerade documentIds.

Sändning av dokument: två godkända former

POST /api/v1/documents accepterar filen på två sätt, efter eget val. Samma kontroller gäller i båda fallen: tillåtna typer, gräns på 50 MB, verifiering av binär signatur och antivirusanalys.

  • I multipart/form-data, med en del som heter file. Det är den klassiska formen, den för curl -F och de flesta biblioteken.
  • I rå brödtext: filens oktetter utgör begärandets brödtext, och Content-Type-huvudet anger dess typ (application/pdf till exempel). Användbar från ett verktyg som överför innehållet som det är, utan att linda in begäran — det är vad Power Automate-kopplingen gör.
  • I raw body är filnamnet inte på plats i body: ange det via X-File-Name-huvudet eller parametern ?fileName=. Utan det namnges dokumentet efter sin typ.
  • En icke-stödd typ svarar 415 och namnger de två accepterade formaten, och en body som annonseras som multipart men inte är läsbar svarar 400. Ingen av dessa är ett serverfel.
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 signaturfält

Utan mall skapar ett kuvert från documentIds inga förpositionerade fält: mottagaren får dokumentet utan någon signeringsplats. Matrisen fields, överfördl i samma skapelseanrop, placerar varje fält på punkten — det är motsvarigheten på API-sidan till vad en mall sparar en gång för alla.

  • Koordinaterna är i PDF-poäng, ursprung i övre vänstra hörnet av sidan och Y-axel nedåt (en A4-sida mäter 595 × 842 poäng). x och y anger övre vänstra hörnet av fältet, width och height dess storlek.
  • pageNumber börjar på 1, documentIndex börjar på 0. Ett sidnummer bortom dokumentet avvisas inte vid skapelse: fältet ignoreras vid underteckningstillfället och visas inte någonstans — det är det första att kontrollera när ett fält saknas i anropet.
  • recipientEmail måste matcha en av mottagarna från samma anrop, utan skiftlägeskänslighet. Annars misslyckas skapelsen genom att lista alla felaktiga rader, vilket undviker att korrigera dem en efter en.
  • fields och templateId utesluter varandra: en mall bär redan sin egen layout. Matrisen fields används därför bara med documentIds.
  • Accepterade typer: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX och RADIO_GROUP. required är sant som standard; placeholder och dateFormat är valfria, och options beaktas bara för RADIO_GROUP.
  • Ett kuvert accepterar högst 100 fält, 20 dokument och 50 mottagare — din plans gränser kan vara lägre.
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.

Textankar: placera ett fält utan att känna till koordinaterna

I stället för koordinater kan ett fält citera en text som är tryckt i dokumentet: anchorText letar upp det i PDF:en och servern beräknar positionen vid skapelse. Det är läget att föredra när dokumentet återskapas vid varje sändning — kopplingsbrev, kontraktsgenerator — eftersom layouten ändras medan anmärkningen "Kundens signatur" förblir. anchorPlacement anger på vilken sida av texten fältet placeras (right som standard, annars below, above eller left) och anchorIndex väljer förekomsten när texten visas flera gånger.

x och y förblir obligatoriska även med ett ankar: de fungerar som fallback. Ett ankar som inte hittas orsakar inte att skapelsen misslyckas — fältet behåller den bokstavliga positionen du angav, utan fel eller varning i svaret. Ange därför ett rimligt fallback i stället för 0,0 och verifiera renderingen vid en första sändning.

Autentisering

Varje anrop bär en API-nyckel i Authorization-huvudet. Nycklar genereras från Inställningar → API-nycklar och visas bara en gång.

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 produktion, sk_test_… för sandbox. Rubrik: Authorization: Bearer <clé>.
  • Omfång: envelopes, documents, webhooks, seals — i läsning (:read) eller skrivning (:write). Skrivning medför läsning; omfånget * ger alla rättigheter.
  • Nycklarna sk_test_ skapar resurser i sandlådan, exkluderade från kvoten och faktureringen. Inget riktigt e-postmeddelande skickas till mottagaren, om inte dennes adress matchar det sändande kontots e-post — användbart för att testa hela flödet på dig själv.
  • Fel: 401 ogiltig nyckel, 403 otillräckligt omfång, 429 gräns för datahastighet överskriden, 402 månatlig kvot nådd.

Formulär för svar

En sak att känna till innan du skriver din klient: samlingar är inkapslade i ett data-objekt, medan enskilda resurser returneras platt. Att läsa response.data.data på en enskild resurs returnerar därför undefined.

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

Hastighetsgränser

Gränserna garanterar stabil servicekvalitet för alla kunder. Om du behöver mer, kontakta oss.

  • 100 förfrågningar per minut per API-nyckel
  • Burst tolererat upp till 200 förfrågningar på mindre än 10 sekunder
  • 429-svar med Retry-After-rubrik som anger fördröjningen i sekunder