Diese Seite wurde von KI aus der englischen Originalversion übersetzt. Maßgeblich ist die englische Version.

Für Entwickler

API-Dokumentation

Mit der Signeur REST-API kann Ihre Anwendung Signaturanfragen erstellen, deren Status überwachen und gesperrte PDFs herunterladen. Diese Dokumentation beschreibt die heute verfügbaren Endpunkte.

Basis-URLhttps://signeur.eu
OpenAPI 3.1-Spec

Authentifizierung

Alle API-Aufrufe erfordern einen Bearer-Token im Authorization-Header. Tokens werden mit SHA-256 gehasht und mit dem gespeicherten Hash verglichen — der Klartext wird nirgends persistiert.

Beispiel:

Authorization: Bearer sgn_live_xxx...

Beziehen Sie einen API-Schlüssel vom Dienstadministrator. Schlüsselformat ist sgn_live_<random>.

Fehlerantworten

Alle Fehler werden als JSON mit den Feldern error und message zurückgegeben. HTTP-Statuscodes folgen den Konventionen.

{
  "error": "invalid_signer_email",
  "message": "Field 'signer_email' is missing or not a valid email."
}
CodeBedeutung
400Bad request (validointi ei mene läpi)
401Authorization-otsikko puuttuu tai Bearer-token virheellinen
404Resurssia ei löytynyt tai se kuuluu toiselle organisaatiolle
409Konflikti: pyyntö on jo allekirjoitettu / ei vielä allekirjoitettu
410Resurssi on vanhentunut (linkki yli 30 päivää vanha)
429Liian monta pyyntöä — odota Retry-After-otsikon ilmoittama aika
500Palvelinvirhe (DB-, Storage- tai email-välitysvirhe)

Rate Limits

Eine Begrenzung pro Organisation ist noch nicht erzwungen. Nutzen Sie die API verantwortungsvoll — Missbrauch kann zur Widerrufung des API-Schlüssels führen. Volumenbasierte Limits werden später hinzugefügt.

Idempotenz

Alle POST-Endpunkte akzeptieren einen optionalen `Idempotency-Key`-Header (eine beliebige eindeutige Zeichenkette, typischerweise eine UUID). Wenn Sie eine Anfrage mit demselben Schlüssel erneut senden, spielt Signeur die ursprüngliche Antwort ab, anstatt ein Duplikat zu erstellen. Schlüssel sind organisationsbezogen und werden 24 Stunden aufbewahrt.

POST /api/v1/signatures
Authorization: Bearer sgn_live_...
Idempotency-Key: 0d8a2c41-7e3f-4b9d-bc59-2c5fd8a91f4d
Content-Type: application/json

{ … }

Wenn Sie denselben Schlüssel mit einem anderen Request-Body senden, gibt Signeur 409 idempotency_key_conflict zurück. Wiedergegebene Antworten enthalten den Header `Idempotent-Replayed: true` zur clientseitigen Erkennung.

Endpunkte

POST/api/v1/signatures

Signaturanfrage erstellen

Erstellt eine neue Signaturanfrage (1–20 Unterzeichner), speichert das PDF im Storage und sendet eine Einladungs-E-Mail an jeden Unterzeichner.

FeldTypErforderlichBeschreibung
titlestringjaTitel der Anfrage (erscheint in der Einladungs-E-Mail).
messagestringneinOptionale Nachricht, die jedem Unterzeichner angezeigt wird.
signers[]arrayjaArray aus 1–20 Unterzeichner-Objekten. Mindestens eines ist erforderlich.
signers[].emailstringjaE-Mail-Adresse des Unterzeichners.
signers[].namestringneinName des Unterzeichners (erscheint auf der Audit-Seite).
signers[].localestringneinE-Mail-Locale pro Unterzeichner: 'en' | 'fi' | 'fr' | 'de'. Fallback zur Top-Level-Locale, dann 'en'.
localestringneinStandard-Locale für Unterzeichner, die keine eigene angeben. Erlaubte Werte: 'en' | 'fi' | 'fr' | 'de'.
document.filenamestringjaUrsprünglicher Dateiname des PDFs.
document.content_base64stringjaPDF-Inhalt als Base64-codierter String (max. 10 MB decodiert).
metadataobjectneinFreies Schlüssel-Wert-Objekt, das wörtlich an der Anfrage gespeichert wird.

Abwärtskompatibilität: Der ältere Single-Signer-Body { "signer_email", "signer_name" } wird weiterhin akzeptiert und als einelementiges signers-Array behandelt. Neue Integrationen sollten das signers[]-Array verwenden.

Request-Body

curl -X POST https://signeur.eu/api/v1/signatures \
  -H "Authorization: Bearer sgn_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Order Agreement #1234",
    "message": "Please review and sign.",
    "locale": "en",
    "signers": [
      { "email": "buyer@example.com",  "name": "Anna Buyer" },
      { "email": "seller@example.com", "name": "Bob Seller", "locale": "fi" }
    ],
    "document": {
      "filename": "contract.pdf",
      "content_base64": "JVBERi0xLjQK..."
    },
    "metadata": { "deal_id": "D-42" }
  }'

Antwort

{
  "id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
  "status": "sent",
  "expires_at": "2026-06-13T10:51:51.813+00:00",
  "signers": [
    {
      "id": "9c0aa5ec-…",
      "email": "buyer@example.com",
      "name": "Anna Buyer",
      "access_token": "29ErQSUr8Ov…",
      "sign_url": "https://signeur.eu/sign/29ErQSUr8Ov…",
      "email_sent": true,
      "email_error": null,
      "locale": "en"
    },
    {
      "id": "f12d8b3c-…",
      "email": "seller@example.com",
      "name": "Bob Seller",
      "access_token": "kpqDAuVy9-…",
      "sign_url": "https://signeur.eu/sign/kpqDAuVy9-…",
      "email_sent": true,
      "email_error": null,
      "locale": "fi"
    }
  ]
}
GET/api/v1/signatures/{id}

Status der Signaturanfrage abrufen

Gibt den aktuellen Zustand der Anfrage, das vollständige Unterzeichner-Array und den Audit-Trail zurück. Zum Status-Polling verwenden.

Request-Body

curl https://signeur.eu/api/v1/signatures/<id> \
  -H "Authorization: Bearer sgn_live_..."

Antwort

{
  "id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
  "status": "signed",
  "title": "Order Agreement #1234",
  "created_at": "2026-05-14T10:51:51.813Z",
  "sent_at":    "2026-05-14T10:51:52.012Z",
  "signed_at":  "2026-05-14T10:52:24.374Z",
  "cancelled_at": null,
  "expires_at": "2026-06-13T10:51:51.813Z",
  "is_expired": false,

  "signers": [
    {
      "id": "9c0aa5ec-…",
      "email": "buyer@example.com",
      "name":  "Anna Buyer",
      "access_token": "29ErQSUr8Ov…",
      "sign_url": "https://signeur.eu/sign/29ErQSUr8Ov…",
      "status": "signed",
      "sent_at":   "2026-05-14T10:51:52.012Z",
      "opened_at": "2026-05-14T10:52:00.481Z",
      "signed_at": "2026-05-14T10:52:24.374Z",
      "declined_at": null,
      "decline_reason": null,
      "locale": "en"
    }
  ],

  "document_hash": "e5132c2fe36dfa219ec600b009d16ef38d20bf0849f7b01ba5ca6e22fec63b56",
  "audit_trail": { "events": [ … ] },
  "metadata": { "deal_id": "D-42" }
}
GET/api/v1/signatures/{id}/document

Signiertes PDF herunterladen

Gibt das gesperrte PDF als Binär zurück. Gibt 409 zurück, wenn die Anfrage noch nicht signiert ist.

Request-Body

curl https://signeur.eu/api/v1/signatures/<id>/document \
  -H "Authorization: Bearer sgn_live_..." \
  -o signed.pdf

Content-Type: application/pdf

GET/api/v1/signatures

Signaturanfragen auflisten

Gibt eine paginierte Liste der Anfragen der Organisation mit optionalen Filtern zurück.

FeldTypErforderlichBeschreibung
statusqueryneinNach Status filtern: pending | sent | opened | signed | cancelled | declined | expired | awaiting_stamp | stamp_failed.
created_fromqueryneinNur Anfragen zurückgeben, die am oder nach diesem ISO-8601-Zeitstempel erstellt wurden.
created_toqueryneinNur Anfragen zurückgeben, die vor diesem ISO-8601-Zeitstempel erstellt wurden.
limitqueryneinSeitengröße, 1–100. Standard 25.
cursorqueryneinOpaker Cursor aus dem next_cursor der vorherigen Antwort. Erstellen Sie keinen eigenen.

Request-Body

curl "https://signeur.eu/api/v1/signatures?status=sent&limit=10" \
  -H "Authorization: Bearer sgn_live_..."

Antwort

{
  "data": [
    {
      "id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
      "status": "sent",
      "title": "Order Agreement #1234",
      "signer_count": 2,
      "created_at": "2026-05-14T10:51:51.813Z",
      "sent_at":    "2026-05-14T10:51:52.012Z",
      "signed_at":  null,
      "cancelled_at": null,
      "expires_at": "2026-06-13T10:51:51.813Z",
      "is_expired": false
    }
  ],
  "has_more": true,
  "next_cursor": "eyJjIjoiMjAyNi0wNS0xNFQxMDo1MTo1MS44MTNaIiwiaSI6IjZkYzE4OTExLi4uIn0"
}
POST/api/v1/signatures/{id}/cancel

Signaturanfrage stornieren

Storniert eine ausstehende Anfrage, invalidiert alle verbleibenden Unterzeichner-Links und löst den signature_request.cancelled-Webhook aus.

FeldTypErforderlichBeschreibung
reasonstringneinOptionaler Grund, gespeichert im Audit-Trail (max. 500 Zeichen).

Request-Body

curl -X POST https://signeur.eu/api/v1/signatures/<id>/cancel \
  -H "Authorization: Bearer sgn_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Sent to wrong recipient" }'

Antwort

{
  "id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
  "status": "cancelled",
  "cancelled_at": "2026-05-17T08:14:02.913Z"
}

Wirkung: Status wird 'cancelled', alle unsignierten Unterzeichner-Links werden invalidiert und der signature_request.cancelled-Webhook wird ausgelöst. Das Original-PDF wird aufbewahrt, ist aber über /document nicht mehr herunterladbar.

GET/api/v1/signatures/{id}/signers

Unterzeichner einer Anfrage auflisten

Gibt alle Unterzeichner einer Signaturanfrage mit Status, Zeitstempeln und Audit-Trail zurück. Für das Rendern von Multi-Signer-Fortschrittsanzeigen.

Request-Body

curl "https://signeur.eu/api/v1/signatures/<id>/signers" \
  -H "Authorization: Bearer sgn_live_..."

Antwort

{
  "data": [
    {
      "id": "9c0aa5ec-…",
      "email": "buyer@example.com",
      "name":  "Anna Buyer",
      "name_as_invited": "Anna Buyer",
      "name_as_signed":  "Anna H. Buyer",
      "access_token": "29ErQSUr8Ov…",
      "sign_url": "https://signeur.eu/sign/29ErQSUr8Ov…",
      "status": "signed",
      "position": 0,
      "sent_at":   "2026-05-14T10:51:52.012Z",
      "opened_at": "2026-05-14T10:52:00.481Z",
      "signed_at": "2026-05-14T10:52:24.374Z",
      "declined_at": null,
      "decline_reason": null,
      "invalidated_at": null,
      "ip_address": "87.92.91.57",
      "user_agent": "Mozilla/5.0 (Macintosh; …) Safari/605.1.15",
      "locale": "en",
      "representing_as_invited": null,
      "representing_as_signed":  null,
      "representing_role":       null,
      "representing_entity_id":  null,
      "audit_trail": { "events": [ … ] }
    },
    {
      "id": "f12d8b3c-…",
      "email": "seller@example.com",
      "status": "pending",
      "position": 1,
      "...": "..."
    }
  ]
}
POST/api/v1/signatures/{id}/signers/{signer_id}/resend

Einladung an einen Unterzeichner erneut senden

Sendet die Einladungs-E-Mail an einen Unterzeichner erneut mit einem frisch rotierten Zugangscode. Der alte Code funktioniert sofort nicht mehr.

FeldTypErforderlichBeschreibung
localestringneinOptional. Überschreibt die E-Mail-Locale des Unterzeichners für diesen Versand und persistiert die Änderung in der Unterzeichner-Zeile. Erlaubt: 'en' | 'fi' | 'fr' | 'de'.

Request-Body

curl -X POST https://signeur.eu/api/v1/signatures/<id>/signers/<signer_id>/resend \
  -H "Authorization: Bearer sgn_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "locale": "fi" }'

Antwort

{
  "ok": true,
  "signer_id": "9c0aa5ec-…",
  "email_sent": true,
  "email_error": null,
  "access_code_rotated_at": "2026-05-17T10:14:33.872Z"
}

Wirkung: Ein neuer 6-stelliger Zugangscode wird generiert, als bcrypt-Hash gespeichert und per E-Mail an den Unterzeichner gesendet. Der zuvor gesendete Code authentifiziert das Access-Code-Gate nicht mehr. Versuchszähler und temporäre Sperren werden zurückgesetzt.

GET/api/v1/signatures/{id}/audit-trail.pdf

Audit-Trail-PDF herunterladen

Gibt ein eigenständiges PDF mit dem vollständigen Audit-Datensatz zurück: Anfrage-Metadaten, Unterzeichner-Details mit IPs und User Agents, chronologische Ereignis-Timeline und PAdES-Signatur-Informationen, wenn die Anfrage versiegelt ist. Dieses PDF ist informativ und NICHT kryptografisch signiert — das versiegelte Dokument selbst ist der rechtliche Nachweis.

Request-Body

curl https://signeur.eu/api/v1/signatures/<id>/audit-trail.pdf \
  -H "Authorization: Bearer sgn_live_..." \
  -o audit-trail.pdf

Content-Type: application/pdf · Das PDF wird bei Bedarf aus dem aktuellen Zustand der Anfrage und des Audit-Trails generiert. Unabhängig vom Anfragestatus verfügbar.

GET/api/v1/webhook-endpoints

Webhook-Endpunkte auflisten

Gibt alle für Ihre Organisation konfigurierten Webhook-Endpunkte zurück. Secrets sind in der Auflistung nicht enthalten — sie werden nur einmal bei der Erstellung angezeigt.

Request-Body

curl https://signeur.eu/api/v1/webhook-endpoints \
  -H "Authorization: Bearer sgn_live_..."

Antwort

{
  "data": [
    {
      "id": "ep_a1b2c3d4-…",
      "url": "https://example.com/hooks/signeur",
      "event_types": ["signature_request.completed", "signer.signed"],
      "description": "Production sync",
      "disabled_at": null,
      "created_at": "2026-05-17T10:00:00.000Z",
      "updated_at": "2026-05-17T10:00:00.000Z"
    }
  ]
}
POST/api/v1/webhook-endpoints

Webhook-Endpunkt erstellen

Registriert eine neue URL zum Empfangen von Webhook-Ereignissen. Die Antwort enthält ein neu generiertes `secret`, das nur dieses eine Mal angezeigt wird und zur Verifizierung von HMAC-Signaturen eingehender Webhooks dient.

FeldTypErforderlichBeschreibung
urlstringjaZiel-URL (muss in Produktion https:// verwenden, http://localhost ist für die Entwicklung erlaubt).
event_typesstring[]neinArray der zu empfangenden Ereignistypen. Leeres Array (oder weggelassen) bedeutet, alle Ereignisse empfangen.
descriptionstringneinOptionale kurze, menschenlesbare Bezeichnung für den Endpunkt (max. 200 Zeichen).

Request-Body

curl -X POST https://signeur.eu/api/v1/webhook-endpoints \
  -H "Authorization: Bearer sgn_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/signeur",
    "event_types": ["signature_request.completed", "signer.signed"],
    "description": "Production sync"
  }'

Antwort

{
  "id": "ep_a1b2c3d4-…",
  "url": "https://example.com/hooks/signeur",
  "secret": "whsec_7f3a9c…",
  "event_types": ["signature_request.completed", "signer.signed"],
  "description": "Production sync",
  "disabled_at": null,
  "created_at": "2026-05-17T10:00:00.000Z",
  "updated_at": "2026-05-17T10:00:00.000Z"
}

Wichtig: Das Secret wird NUR in dieser Antwort angezeigt. Signeur behält keine Klartext-Kopie. Wenn Sie es verlieren, löschen Sie diesen Endpunkt und erstellen Sie einen neuen.

PATCH/api/v1/webhook-endpoints/{id}

Webhook-Endpunkt aktualisieren

Aktualisiert URL, event_types, description oder disabled-Status eines Endpunkts. Alle Body-Felder sind optional — nur die angegebenen werden geändert.

FeldTypErforderlichBeschreibung
urlstringneinZiel-URL (muss in Produktion https:// verwenden, http://localhost ist für die Entwicklung erlaubt).
event_typesstring[]neinArray der zu empfangenden Ereignistypen. Leeres Array (oder weggelassen) bedeutet, alle Ereignisse empfangen.
descriptionstringneinOptionale kurze, menschenlesbare Bezeichnung für den Endpunkt (max. 200 Zeichen).
disabledbooleanneintrue = Zustellung pausieren ohne den Endpunkt zu löschen, false = fortsetzen.
DELETE/api/v1/webhook-endpoints/{id}

Webhook-Endpunkt löschen

Entfernt den Endpunkt dauerhaft. Die Zustellung von Ereignissen stoppt sofort. Das Secret ist nach dem Löschen nicht wiederherstellbar.

curl -X DELETE https://signeur.eu/api/v1/webhook-endpoints/<id> \
  -H "Authorization: Bearer sgn_live_..."

Webhooks

Signeur sendet Echtzeit-Ereignisse an eine oder mehrere für Ihre Organisation konfigurierte URLs, wenn sich der Status einer Signaturanfrage ändert. Jedes Ereignis wird mit HMAC-SHA256 signiert und parallel an alle passenden Endpunkte zugestellt. Dies ist effizienter als das Pollen des GET-Endpunkts.

Unterstützte Ereignisse

signature_request.createdEine neue Signaturanfrage wurde erstellt. Wird einmal pro Anfrage ausgelöst, enthält die vollständige Unterzeichnerliste.
signature_request.sentDer Einladungs-E-Mail-Batch wurde für alle Unterzeichner versucht. Enthält pro Unterzeichner den email_sent-Status.
signature_request.openedEin Unterzeichner hat den Link zum ersten Mal geöffnet. Wird einmal pro Anfrage ausgelöst, wenn der erste Unterzeichner sie öffnet.
signer.signedEin Unterzeichner hat sein OTP erfolgreich verifiziert und unterschrieben. Wird N-mal bei einer N-Unterzeichner-Anfrage ausgelöst.
signature_request.completedAlle Unterzeichner haben unterzeichnet und das Dokument ist versiegelt. Enthält document_hash und download_url.
signature_request.signedVeralteter Alias für signature_request.completed — wird zum gleichen Zeitpunkt ausgelöst. Verwenden Sie signature_request.completed für neue Integrationen.
signature_request.declinedEin Unterzeichner hat abgelehnt; die Anfrage wurde in den Status 'declined' verschoben und die übrigen Unterzeichner wurden invalidiert.
signature_request.cancelledDie Anfrage wurde über das Dashboard oder POST /signatures/{id}/cancel storniert.
signature_request.expiredDie Anfrage hat expires_at erreicht, bevor alle Unterzeichner unterschrieben haben. Wird einmal pro Anfrage gesendet, wenn der tägliche Expire-Cron den Status auf 'expired' setzt.

Payload-Format

// signer.signed — fires once per signer that finishes signing
{
  "id": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "type": "signer.signed",
  "created_at": "2026-05-14T10:52:24.374Z",
  "data": {
    "signature_request_id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
    "signer_id": "9c0aa5ec-…",
    "signer_email": "buyer@example.com",
    "signer_name":  "Anna Buyer",
    "signed_at": "2026-05-14T10:52:24.374Z",
    "remaining_pending_signers": 1
  }
}

// signature_request.completed — fires once when all signers are done
// and the PDF is sealed. signature_request.signed is a deprecated alias
// that fires at the same moment with the same payload.
{
  "id": "evt_b2c3d4e5-f6a7-8901-bcde-f23456789012",
  "type": "signature_request.completed",
  "created_at": "2026-05-14T10:55:11.812Z",
  "data": {
    "signature_request_id": "6dc18911-f66b-43d6-9810-8de0b07bab04",
    "status": "signed",
    "signed_at": "2026-05-14T10:55:11.812Z",
    "document_hash": "e5132c2fe36dfa…",
    "download_url": "https://signeur.eu/api/v1/signatures/6dc18911-…/document"
  }
}

Signaturprüfung

Jeder Webhook wird mit HMAC-SHA256 im Header X-Signeur-Signature signiert. Verifizieren Sie ihn, um sicherzustellen, dass die Anfrage tatsächlich von Signeur stammt.

Header-Format:

X-Signeur-Signature: t=1747212744,v1=abc123def456...

Signierte Daten:

<timestamp>.<raw json body>

Verifizierungsbeispiel (Node.js):

import { createHmac } from "crypto";

// Verify webhook signature
const sig = req.headers["x-signeur-signature"];
const [t, v1] = sig.split(",").map(s => s.split("=")[1]);
const expected = createHmac("sha256", YOUR_WEBHOOK_SECRET)
  .update(`${t}.${rawBody}`).digest("hex");
if (v1 !== expected) throw new Error("Invalid signature");

Konfiguration

Endpunkte können auf zwei Arten konfiguriert werden: (a) Dashboard → Webhooks bietet eine UI zum Hinzufügen, Bearbeiten, Pausieren oder Löschen von Endpunkten und zur Auswahl der Ereignistypen pro Endpunkt. (b) Die REST-API /api/v1/webhook-endpoints ermöglicht die programmatische Verwaltung. Jeder Endpunkt erhält sein eigenes HMAC-Secret, das nur bei der Erstellung angezeigt wird — bewahren Sie es sicher auf. Ein veralteter Single-URL-Webhook auf der Organisation wird weiterhin als Fallback berücksichtigt, wenn in der neuen Tabelle keine Einträge existieren.

Zustellung

Wenn ein Ereignis ausgelöst wird, sucht Signeur alle aktiven Endpunkte, die diesen Ereignistyp abonnieren, und liefert die Payload parallel aus (5 Sekunden Timeout pro Endpunkt). Jeder Versuch wird separat im Audit-Trail der Signaturanfrage mit der Endpunkt-ID, dem HTTP-Status und einem etwaigen Fehler protokolliert. Eine Retry-Queue steht auf der Roadmap.

Bald verfügbar

Folgende Funktionen sind geplant:

  • Automatische Ablauferkennung, die signature_request.expired auslöst (derzeit bleibt der Status 'sent'/'opened' auch nach expires_at)
  • Webhook-Retry-Queue — aktuell ist jede Zustellung ein einzelner Versuch; fehlgeschlagene Ereignisse werden nicht erneut versucht
  • Idempotency-Key-Unterstützung für cancel- und resend-Endpunkte (derzeit nur POST /signatures)
  • Webhook-Zustellungshistorie im Dashboard