Zum Hauptinhalt springen
Certyneo
Öffentliche API v1

Integrieren Sie elektronische Signaturen in Ihren Tech-Stack

Versenden Sie Umschläge, verfolgen Sie Signaturen, empfangen Sie Webhooks. Einfache REST-API, OpenAPI 3.0, curl/Node/Python-Beispiele — alles, um Certyneo in wenigen Stunden an Ihr HRIS, CRM oder Geschäftssoftware anzubinden.

Schnelleinstieg

Drei Schritte: Erstellen Sie einen API-Schlüssel in den Einstellungen, kodieren Sie Ihr PDF in Base64, senden Sie es ab. Die Antwort enthält die `signUrl`, die Sie direkt mit dem Empfänger teilen können.

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

API von Ihren Tools aus ausprobieren

Die Postman-Sammlung und das RapidAPI-Blatt werden aus der OpenAPI-Spezifikation generiert, die diese Seite ebenfalls dokumentiert. Alle drei bleiben also auf die echte API abgestimmt, Endpoint für Endpoint, anstatt bei der ersten Erweiterung abzuweichen.

Postman-Sammlung

Die 25 Anfragen, nach Domäne sortiert – Umschläge, Dokumente, Vorlagen, Siegel, Webhooks – mit Beispiel-Text und Antwort für jede. Fügen Sie Ihren Schlüssel in die Variable apiKey der Sammlung ein und führen Sie GET /health aus: Dies erfordert keine Authentifizierung und bestätigt, dass Ihre Konfiguration vor dem ersten authentifizierten Aufruf korrekt ist.

RapidAPI-Blatt

Der gleiche Endpoint-Katalog, direkt im Browser ausprobierbar. Der Teststand erwartet zwei unterschiedliche Header: den RapidAPI-Schlüssel, den Ihnen die Plattform zuweist, und Ihren Certyneo-Schlüssel in Authorization – der zweite autorisiert den Aufruf tatsächlich.

Umschläge

Erstellung, Versand, Statusverfolgung, Stornierung. Ein Umschlag kann mehrere Dokumente und mehrere Unterzeichner enthalten (parallel oder sequenziell).

Webhooks

Alle Umschlags- und Empfängerereignisse (`envelope.sent`, `recipient.signed`, `envelope.completed`…) werden an die URL Ihrer Wahl geliefert — vollständige Liste unter /developers/webhooks. HMAC SHA-256 für jede Payload, um die Herkunft zu überprüfen.

Einfache Authentifizierung

Bearer Token. Ein Schlüssel pro Umgebung (Test/Produktion). Sofort widerrufbar. Limit 100 Anfragen/Min/Schlüssel, Burst von 200, saubere 429-Antwort mit Retry-After-Header.

Verfügbare Endpoints

Die 52 öffentlichen Routen: Konto, Dokumente, Umschläge, Vorlagen, Webhooks, elektronische Siegel, API-Schlüssel und Abrechnung. Alle akzeptieren ein Bearer-Token und geben JSON zurück.

MethodePfadBeschreibung
GET/api/v1/account/meIdentität des authentifizierten Aufrufers (ID, E-Mail, Plan): Test von Kennungen ohne erforderlichen Umfang
GET/api/v1/sandboxDie mit Testschlüsseln erstellten Daten zählen (nach 30 Tagen automatisch gelöscht)
DELETE/api/v1/sandboxAlle mit Testschlüsseln erstellten Daten löschen, ohne die echten Daten anzutasten
POST/api/v1/documentsPDF hochladen (Multipart): gibt die Dokument-ID zurück
GET/api/v1/documentsDokumente auflisten
GET/api/v1/documents/{id}Metadaten eines Dokuments lesen
DELETE/api/v1/documents/{id}Dokument löschen
GET/api/v1/envelopesUmschläge auflisten (mit ?status= und ?limit= filtern)
POST/api/v1/envelopesUmschlag erstellen (Status DRAFT): aus einer templateId oder aus documentIds mit optionalem fields-Array
GET/api/v1/envelopes/{id}Status eines Umschlags lesen
PATCH/api/v1/envelopes/{id}DRAFT-Umschlag ändern
DELETE/api/v1/envelopes/{id}DRAFT-Umschlag löschen (409 nach dem Versand: stattdessen abbrechen)
POST/api/v1/envelopes/{id}/sendDRAFT-Umschlag versenden: verschickt die Einladungen
POST/api/v1/envelopes/{id}/voidVersendeten Umschlag abbrechen, der noch nicht vollständig unterzeichnet ist: wartende Unterzeichner werden benachrichtigt
GET/api/v1/envelopes/{id}/audit-trailPDF des eIDAS-Nachweispfads herunterladen
POST/api/v1/envelopes/{id}/embed-urlGibt die Signatur-URL eines Empfängers mit einer Autorisierung für den angeforderten Ursprung zurück. Wird beim Klick aufgerufen: Die Autorisierung ist zwei Stunden gültig.
GET/api/v1/audit-anchors/{root}Öffentlich: Metadaten eines verankerten Audit-Lots oder Nachweisdatei .ots mit ?format=ots (ohne Authentifizierung)
POST/api/v1/audit-anchors/verifyÖffentlich: einen Audit-Eintrag und seinen Nachweis gegen die verankerte Merkle-Wurzel überprüfen (ohne Authentifizierung, offenbart nichts)
GET/api/v1/envelopes/{id}/signed-documentSigniertes PDF herunterladen (nach COMPLETED)
GET/api/v1/envelopes/bulkIhre Massenversände auflisten
POST/api/v1/envelopes/bulkMassenversand: N Umschläge aus einer Vorlage und einer CSV-Datei erstellen (nur Standard/Business)
GET/api/v1/envelopes/bulk/{id}Fortschritt eines Massenversands: Zähler, Fehler pro Zeile, erstellte Umschläge
GET/api/v1/templatesWiederverwendbare Umschlagvorlagen auflisten
POST/api/v1/templatesEine Vorlage erstellen (Dokumente, Rollen, positionierte Felder)
GET/api/v1/workspacesArbeitsbereiche auflisten, in denen Sie einen Umschlag erstellen können
POST/api/v1/sepa-mandatesDas PDF eines SEPA-Mandats und seinen DRAFT-Umschlag generieren, Felder bereits platziert
POST/api/v1/payroll-adapters/normalizeEine Gehalts-CSV-Datei (Silae, Sage Paie, PayFit, Lucca) in das Massenversandformat normalisieren
POST/api/v1/ag-coproprieteEinen Umschlag für eine Eigentümerversammlung erstellen (Beschlüsse und Miteigentumsanteile)
POST/api/v1/ag-copropriete/{envelopeId}/votesDie Abstimmungen eines Eigentümers zu den Beschlüssen der Versammlung erfassen
POST/api/v1/ag-copropriete/{envelopeId}/tallyDie Versammlung auszählen: Ergebnis pro Beschluss, gewichtet nach Miteigentumsanteilen
GET/api/v1/videos/{videoId}Ein konserviertes Identitätsvideo herunterladen: DSGVO-Auskunftsrecht (Art. 15)
GET/api/v1/webhooksWebhooks auflisten
POST/api/v1/webhooksEinen Webhook registrieren: gibt das Signaturgeheimnis nur einmal zurück
GET/api/v1/webhooks/{id}Ein Webhook-Abonnement lesen
PATCH/api/v1/webhooks/{id}Die URL, die Ereignisse oder den aktiven Status ändern
DELETE/api/v1/webhooks/{id}Den Webhook abmelden
POST/api/v1/sealsEin qualifiziertes elektronisches Siegel auf ein Dokument anbringen
GET/api/v1/seals/{id}Den Status eines Siegels lesen
GET/api/v1/seals/{id}/certificateDas Zertifikat des Siegels herunterladen
GET/api/v1/payslips/workspacesGehaltsabrechnungen: die Räume, für die dieser Schlüssel verteilt, gehalten oder delegiert wird, von Kunden (Buchhaltungskanzleien, Gehaltsabrechnungsverwaltungen)
GET/api/v1/payslips/employeesGehaltsabrechnungen: das Arbeitnehmerverzeichnis, mit denen, die die elektronische Zustellung abgelehnt haben (Papiergeldzettel fällig)
PUT/api/v1/payslips/employeesGehaltsabrechnungen: Mitarbeiter aus dem Register hinzufügen oder aktualisieren (werden nie entfernt)
POST/api/v1/payslipsEine Gehaltsabrechnung (PDF) im Tresor eines Mitarbeiters hinterlegen: versiegelt, 50 Jahre lang aufbewahrt, Wiederholung ohne Duplikat
GET/api/v1/payslipsBereitgestellte Gehaltsabrechnungen mit Einsichtsnachweisen auflisten
GET/api/v1/keysAPI-Schlüssel auflisten
POST/api/v1/keysAPI-Schlüssel erstellen: Das Geheimnis wird nur einmal angezeigt
PATCH/api/v1/keys/{id}Einen Schlüssel umbenennen oder widerrufen
DELETE/api/v1/keys/{id}Einen Schlüssel löschen
GET/api/v1/billing/usageVerbrauch der aktuellen Periode und prognostizierte Kosten
GET/api/v1/statusServicestatus
GET/api/v1/healthIntegritätsprüfung: Datenbank, Warteschlange und Objektspeicher
GET/api/v1/openapiMaschinenlesbarer OpenAPI-Spezifikation

Umschlagvorlagen

Eine Vorlage speichert einmalig das PDF, die Rollen und die Position der Signaturfelder und wird dann bei jedem Versand wiederverwendet: Übergeben Sie deren Identifikator in templateId statt in documentIds, und die positionierten Felder werden in den erstellten Umschlag kopiert.

  • • Vorlagen werden über das Dashboard erstellt (Vorlagen → Neue Vorlage), wo Sie das Dokument hochladen und die Felder mit der Maus positionieren – das ist der einfachste Weg. Die API ermöglicht es auch, sie per POST /api/v1/templates zu erstellen, indem Dokumente, Rollen und Felder bereitgestellt werden; beachten Sie, dass Felder dort in absoluten Koordinaten positioniert werden (Seite, x, y, Breite, Höhe), daher müssen Sie das Layout des PDF kennen.
  • • Auf einem Konto, das noch keine Vorlage gespeichert hat, gibt GET /api/v1/templates eine leere Liste zurück. Das ist das normale Verhalten, kein Authentifizierungsfehler.
  • • Die Liste enthält nur Vorlagen, die dem Benutzer gehören, dem der API-Schlüssel gehört. Eine von einem Kollegen erstellte Vorlage wird nicht angezeigt, auch nicht in einem gemeinsamen Arbeitsbereich: Generieren Sie den Schlüssel über das Konto, das die Vorlage besitzt.
  • • templateId und documentIds schließen sich gegenseitig aus: Senden Sie das eine oder das andere, niemals beide oder keines von beiden.
  • • Geben Sie mindestens so viele SIGNER-Empfänger an, wie die Vorlage Unterzeichner-Rollen hat, sonst wird die Erstellung mit 400 abgelehnt. Das von der Liste zurückgegebene Feld signerCount gibt die erwartete Anzahl an.
  • • Die Signierungsstufe der Vorlage wird vom Umschlag geerbt, es sei denn, die Anfrage übergibt explizit 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.

Über Power Automate oder Zapier

Die Aktion « Umschlag erstellen » unserer No-Code-Connectoren deckt nur den vorlagengesteuerten Weg ab: das Feld Vorlage ist darin obligatorisch. Für ein Ad-hoc-Dokument, das sich bei jeder Ausführung ändert, verwenden Sie die Aktion « Dokument hochladen » und dann eine rohe HTTP-Aktion zu POST /api/v1/envelopes, wobei Sie die zurückgegebene documentIds übergeben.

Dokumentversand: zwei akzeptierte Formen

POST /api/v1/documents akzeptiert die Datei auf zwei Arten, zur Wahl. Die gleichen Kontrollen gelten in beiden Fällen: zulässige Typen, Obergrenze von 50 Mo, Überprüfung der binären Signatur und Antivirenscan.

  • • In multipart/form-data mit einem Teil namens file. Dies ist die klassische Form, die von curl -F und den meisten Bibliotheken verwendet wird.
  • • Im unformatiert körper: die Bytes der Datei bilden den Anforderungstext, und der Header Content-Type gibt ihren Typ an (z.B. application/pdf). Nützlich von einem Tool, das den Inhalt wie er ist übermittelt, ohne die Anfrage zu verpacken — dies ist das, was der Power Automate-Konnektor tut.
  • • Im unformatiert körper hat der Dateiname keinen Platz im Text: geben Sie ihn über den Header X-File-Name oder den Parameter ?fileName= an. Ohne ihn wird das Dokument nach seinem Typ benannt.
  • • Ein nicht unterstützter Typ antwortet mit 415 und nennt die beiden akzeptierten Formen, und ein als multipart angekündigter aber unlesbarer Text antwortet mit 400. Keines von beiden ist ein Serverfehler.
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.

Platzierung der Signaturfelder

Ohne Vorlage hat ein Umschlag, der aus documentIds erstellt wird, kein vordefiniertes Feld: Der Unterzeichner erhält das Dokument ohne Unterschriftsort. Das Feld fields, das im selben Erstellungsaufruf übertragen wird, platziert jedes Feld auf den Punkt genau – es ist das API-Äquivalent dessen, was eine Vorlage ein für alle Mal speichert.

  • • Die Koordinaten werden in PDF-Punkten angegeben, der Ursprung befindet sich oben links auf der Seite und die Y-Achse zeigt nach unten (eine A4-Seite misst 595 × 842 Punkte). x und y bezeichnen die obere linke Ecke des Feldes, width und height seine Größe.
  • • pageNumber beginnt bei 1, documentIndex bei 0. Eine Seitennummer außerhalb des Dokuments wird bei der Erstellung nicht abgelehnt: das Feld wird zum Zeitpunkt der Unterzeichnung ignoriert und erscheint nirgendwo — das ist das Erste, das überprüft werden muss, wenn ein Feld beim Aufruf fehlt.
  • • recipientEmail muss einem der Empfänger des gleichen Aufrufs entsprechen, ohne Berücksichtigung der Groß- und Kleinschreibung. Andernfalls schlägt die Erstellung fehl und listet alle fehlerhaften Zeilen auf, was vermeidet, sie einzeln zu korrigieren.
  • • fields und templateId schließen sich gegenseitig aus: eine Vorlage bringt bereits ihr eigenes Layout mit sich. Das Array fields wird daher nur mit documentIds verwendet.
  • • Akzeptierte Typen: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX und RADIO_GROUP. required ist standardmäßig wahr; placeholder und dateFormat sind optional, und options wird nur für RADIO_GROUP berücksichtigt.
  • • Eine Umschlag akzeptiert maximal 100 Felder, 20 Dokumente und 50 Empfänger — die Limits Ihres Plans können niedriger sein.
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.

Text-Anker: ein Feld platzieren, ohne die Koordinaten zu kennen

Anstelle von Koordinaten kann ein Feld einen im Dokument gedruckten Text zitieren: anchorText lokalisiert ihn im PDF und der Server berechnet die Position bei der Erstellung. Dies ist der bevorzugte Modus, wenn das Dokument bei jedem Versand neu generiert wird — Seriendruck, Vertragsgenerator — da sich das Layout verschiebt, während die Angabe „Unterschrift des Kunden" bleibt. anchorPlacement gibt an, auf welcher Seite des Textes sich das Feld befindet (standardmäßig right, sonst below, above oder left) und anchorIndex wählt das Vorkommen aus, wenn der Text mehrmals erscheint.

x und y bleiben auch mit einem Anker obligatorisch: sie dienen als Fallback. Ein nicht gefundener Anker führt nicht zu einem Fehlschlag der Erstellung — das Feld behält die wörtliche Position bei, die Sie angegeben haben, ohne Fehler oder Warnung in der Antwort. Geben Sie daher einen plausiblen Fallback an, statt 0,0, und überprüfen Sie das Rendering bei einem ersten Versand.

Integrierte Signatur: Unterschreiben, ohne Ihre Anwendung zu verlassen

Ihr Kunde konsultiert und unterzeichnet sein Dokument über Ihre eigene Schnittstelle. Die Zeremonie wird in einem Fenster über Ihrer Seite geöffnet, und er kehrt nach Abschluss automatisch zu Ihnen zurück. Auf der Serverseite gibt es nichts Neues: Sie erstellen den Umschlag wie gewohnt, indem Sie redirectUrl angeben, und übergeben dann dem SDK die Signatur-URL des Empfängers.

  • • Rufen Sie Certyneo.sign() direkt in Ihrem Klick-Handler auf und übergeben Sie Ihren Serveraufruf über getUrl. Ein await vor sign() beendet die Benutzergeste: Safari und Firefox blockieren dann das Fenster. Das SDK öffnet es sofort und lädt es, wenn sich Ihr Promise auflöst.
  • • redirectUrl ist der Rückgabekanal. Wir leiten den Unterzeichner dorthin weiter und fügen certyneo_status (completed oder declined) und certyneo_envelope hinzu. Laden Sie dasselbe Skript auf diese Rückgabenseite: Es teilt dem Portal-Fenster mit, das offen im Hintergrund geblieben ist.
  • • Im integrierten Modus werden unsere eigenen Call-to-Action-Elemente unterdrückt. Ihr Kunde sieht niemals eine Aufforderung, ein Certyneo-Konto zu erstellen.
  • • Falls der Browser das Fenster ablehnt, wechselt das SDK automatisch zur vollständigen Seitenumleitung. Der Ablauf ist für den Unterzeichner identisch, und Ihre Rückgabenseite erhält exakt dieselben Parameter.
  • • Es gibt absichtlich keinen Rückruf "der Benutzer hat abgebrochen": Der Fensterzustand ist von Ihrer Seite aus nicht lesbar, und ein solcher Rückruf würde fälschlicherweise ausgelöst. Eine Signatur, die nicht ankommt, bleibt bis zum Webhook ausstehend.
JavaScriptjavascript
// 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.

Das Browser-Ereignis ist kein Signaturbeweis

onCompleted ist ein Anzeigesignal, das von einem Browser ausgegeben wird und daher von jedem von seiner Konsole aus gefälscht werden kann. Bringen Sie einen Fall niemals auf dieser Grundlage in den Status "signiert": Verwenden Sie es, um den Bildschirm zu aktualisieren, und verlassen Sie sich auf den Webhook mit signiertem envelope.completed, den Ihr Server erhält, um den tatsächlichen Status zu bestätigen. Dies ist die klassische Falle bei Zahlungsintegrationen, und sie wiederholt sich hier identisch.

Entwicklung auf Ihrem Rechner

Mit einem Test-Schlüssel akzeptiert redirectUrl http://localhost (und 127.0.0.1): Sie können den gesamten Ablauf auf Ihrem Rechner einrichten, bevor Sie ihn bereitstellen. Ein echter Schlüssel lehnt dies ab, damit kein Produktions-Umschlag einen echten Unterzeichner auf einen Rechner zurückleitet, der nicht der seine ist.

Die Zeremonie auf Ihrer Seite anzeigen

Der Rahmenmodus zeigt die Signatur in Ihrer Schnittstelle an, ohne Fenster. Er erfordert einen Schritt mehr als der Fenstermodus: nachzuweisen, dass die Website, die ihn anzeigt, Ihnen gehört. Dies verhindert, dass ein Dritter unsere Zeremonien umrahmt, um Ihre Kunden zu täuschen.

  • • Deklarieren Sie Ihre Website unter Einstellungen → Integrierte Signatur und veröffentlichen Sie dann den angegebenen DNS-Eintrag. Eine genaue Adresse: eine Subdomain oder ein anderer Port zählt als separate Website.
  • • Bei jeder Signatur fordern Sie eine neue URL bei POST /api/v1/envelopes/{id}/embed-url an. Sie trägt die Anzeigeerlaubnis und ist zwei Stunden lang gültig, was dem Zeitpunkt des Klicks entspricht, nicht der Erstellung des Umschlags.
  • • Zwei Abläufe können nicht in einem Rahmen stattfinden: die qualifizierte Signatur, deren Identitätsprüfung sich ihrerseits weigert, umrahmt zu werden, und die Zahlung bei der Signatur. In beiden Fällen wird der Unterzeichner zu einem vollständigen Fenster geleitet.
  • • Der Hinweis „Unterstützt durch Certyneo" verschwindet aus dem Rahmen ab dem Business-Plan. Der Rahmenmodus selbst ist bereits im Standard-Plan enthalten.
JavaScriptjavascript
// 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.

Unterschrift ohne dass eine E-Mail versendet wird

Ein Portal, das die Zeremonie bei ihm anzeigt, benötigt oft keine Einladung von uns: Sie kommt neben seinem eigenen Weg an und bietet ein Konto einem Kunden an, der keins möchte. Setzen Sie den Benachrichtigungskanal eines Empfängers auf NONE und ihm wird nichts mehr gesendet – Sie bringen ihn selbst zu seiner Unterschrift.

  • • Die Einstellung ist pro Empfänger, nicht pro Umschlag: Sie können den von Ihnen gehosteten Kunden zum Schweigen bringen und die E-Mail für einen externen Mitunterzeichner behalten, der kein Portal hat.
  • • Es ist den Unterzeichnern und Genehmigern vorbehalten, den einzigen, denen Sie einen Link übergeben müssen. Sie lesen ihn in der Antwort der Erstellung und des Versands, oder Sie fordern eine neue URL zum Zeitpunkt des Klicks unter POST /api/v1/envelopes/{id}/embed-url an.
  • • Automatische Nachverfolgungen enden von selbst für diesen Empfänger: Wir haben ihm nie geschrieben, wir beginnen nicht mit einer Nachverfolgung. Die anderen Empfänger werden weiterhin normal nachverfolgt.
  • • Das Unterschriftszertifikat erwähnt es, Empfänger für Empfänger. Eine Beweisakte, die sich dazu ausschweigen würde, könnte den Anschein erwecken, dass dieser Unterzeichner eine Einladung von uns erhalten hat, die nie existiert hat.
JSONjson
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.

Den Namen Ihres Kunden als Absender anzeigen

Standardmäßig liest der Unterzeichner den Namen des API-Schlüsseleigentümers. Wenn Sie Dokumente mehrerer Unternehmen mit einem einzigen Schlüssel signieren lassen, übergeben Sie das Feld sender bei der Erstellung des Umschlags: Die Signaturseite und die Einladungs- und Erinnerungs-E-Mails zeigen dann den Namen des betroffenen Unternehmens an.

  • • Reserviert für den Business-Plan und darüber hinaus. Bei einem niedrigeren Plan wird die Erstellung abgelehnt, anstatt den Unterzeichner einen anderen Namen als den erwarteten lesen zu lassen.
  • • Der Name ist eine Anzeige: Das Zertifikat und der Audit-Trail bewahren den tatsächlichen Absender, und E-Mails werden immer von Certyneo versendet.
  • • Die Adresse ist optional. Ohne sie sieht der Unterzeichner nur den Namen, niemals die Adresse des API-Schlüsseleigentümers.
JSONjson
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"
  }
}

Authentifizierung

Jeder Aufruf trägt einen API-Schlüssel im Authorization-Header. Schlüssel werden über Einstellungen → API-Schlüssel generiert und nur einmal angezeigt.

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_… in der Produktion, sk_test_… für die Sandbox. Header: Authorization: Bearer <Schlüssel>.
  • • Bereiche: envelopes, documents, webhooks, seals — im Lese- (:read) oder Schreibmodus (:write). Schreiben impliziert Lesen; der Bereich * gewährt alle Rechte.
  • • sk_test_-Schlüssel erstellen Ressourcen in der Sandbox, ausgeschlossen von Kontingent und Abrechnung. Es wird keine echte E-Mail an den Empfänger gesendet, es sei denn, dessen Adresse stimmt mit der E-Mail-Adresse des sendenden Kontos überein – nützlich, um den gesamten Ablauf an sich selbst zu testen.
  • • Fehler: 401 ungültiger Schlüssel, 403 unzureichender Bereich, 429 Ratengrenze überschritten, 402 monatliches Kontingent erreicht.

Form der Antworten

Ein wichtiger Punkt vor dem Schreiben Ihres Clients: Sammlungen sind in einem data-Objekt gekapselt, während einzelne Ressourcen flach zurückgegeben werden. Das Lesen von response.data.data auf einer einzelnen Ressource gibt daher undefined zurück.

Sammlung — gekapseltjson
// GET /api/v1/envelopes
// Collections are WRAPPED in a "data" array.
{
  "data": [
    { "id": "env_abc123", "subject": "Contrat", "status": "SENT" }
  ]
}
Einzelne Ressource — flachjson
// GET /api/v1/envelopes/{id}
// Single resources are returned FLAT — no "data" envelope.
{
  "id": "env_abc123",
  "subject": "Contrat",
  "status": "COMPLETED",
  "recipients": [ /* … */ ]
}

Durchsatzbegrenzungen

Die Limits garantieren stabilen Service für alle Kunden. Wenn Sie mehr benötigen, kontaktieren Sie uns.

  • • 100 Anfragen pro Minute pro API-Schlüssel
  • • Burst toleriert bis zu 200 Anfragen in weniger als 10s
  • • 429-Antwort mit Retry-After-Header, der die Verzögerung in Sekunden angibt

Weiter gehen