Eine sichere API für digitale Signaturen

Integrieren Sie unterschreib.es in CRM-, ERP- oder Branchenlösungen – mit einer durchdachten REST-API, vollständiger OpenAPI-Spezifikation, Webhooks und Token-Authentifizierung. Deutsch gehostet, ohne US-Tracking.

Business-Feature. Token erzeugen Sie in der App unter Verwaltung → API-Tokens (nur Inhaber).

Authentifizierung

Jeder Request trägt Ihr API-Token als Bearer-Token im Authorization-Header. Tokens gehören dem Team, sind ausschließlich gehasht gespeichert (wir können sie nicht zurückgeben) und lassen sich mit optionalem Ablaufdatum ausstatten sowie jederzeit widerrufen.

Authorization: Bearer ues_...

Die vollständige, interaktive Referenz mit „Try it"-Funktion finden Sie unter https://api.unterschreib.es/docs. Die reine OpenAPI-Spezifikation liegt unter /swagger/v1/swagger.json.

Der Flow im Überblick

  1. Dokument hochladenPOST /v1/documents (PDF + Titel).
  2. Empfänger anlegenPOST /v1/documents/{id}/requests je Empfänger:in inkl. Position.
  3. Optional konfigurierenPATCH /v1/documents/{id} für Frist, Erinnerungen, Reihenfolge, Projekt/Tags.
  4. Versand startenPOST /v1/documents/{id}/send verschickt die Einladungen.
  5. Status abfragenGET /v1/documents/{id} oder per Webhook (siehe unten).
  6. Signiertes PDF abholenGET /v1/documents/{id}/file.

Beispiel: Dokument hochladen

curl -X POST https://api.unterschreib.es/v1/documents \
    -H "Authorization: Bearer ues_..." \
    -F "file=@vertrag.pdf" \
    -F "title=Kaufvertrag PKW"
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new("Bearer", "ues_...");

using var form = new MultipartFormDataContent();
form.Add(new StreamContent(File.OpenRead("vertrag.pdf")), "file", "vertrag.pdf");
form.Add(new StringContent("Kaufvertrag PKW"), "title");

var resp = await http.PostAsync("https://api.unterschreib.es/v1/documents", form);
resp.EnsureSuccessStatusCode();
var doc = await resp.Content.ReadFromJsonAsync<JsonElement>();
Console.WriteLine(doc.GetProperty("id").GetString());
const form = new FormData();
form.append("file", fileInput.files[0]);
form.append("title", "Kaufvertrag PKW");

const res = await fetch("https://api.unterschreib.es/v1/documents", {
  method: "POST",
  headers: { Authorization: "Bearer ues_..." },
  body: form,
});
const doc = await res.json();
console.log(doc.id);

Antwort: JSON mit der ID des erzeugten Dokuments. Nutzen Sie diese ID für die weiteren Aufrufe.

Endpoints

MethodePfadZweck
GET/v1/documentsDokumente auflisten (paginiert: ?status=&skip=&take=, Header X-Total-Count).
POST/v1/documentsPDF hochladen (multipart, max. 25 MB).
GET/v1/documents/{id}Dokument inkl. Signaturanforderungen abrufen.
PATCH/v1/documents/{id}Entwurf ändern: Titel, Frist, Erinnerungen, Reihenfolge, Projekt, Tags.
DELETE/v1/documents/{id}Dokument löschen (Soft-Delete).
GET/v1/documents/{id}/fileAktuelles PDF herunterladen.
POST/v1/documents/{id}/sendVersand der Einladungen starten.
GET/v1/documents/{id}/requestsSignaturanforderungen auflisten.
POST/v1/documents/{id}/requestsSignaturanforderung anlegen (Position als 0–1 normalisierte Rechteck-Koordinaten). Optional mit SMS-2FA: requiresSmsTwoFactor: true plus signerPhone (Mobilnummer aus EU/EWR, Schweiz oder UK) – beides nur gemeinsam.
DELETE/v1/documents/{id}/requests/{rid}Signaturanforderung löschen.

Alle Parameter, Schemata und Beispiele stehen in der interaktiven Referenz.

Fehler & Statuscodes

Fehler kommen einheitlich als Problem Details (application/problem+json) zurück:

{
  "type": "about:blank",
  "title": "Ungültige Anfrage",
  "status": 400,
  "detail": "Nur PDF erlaubt."
}
  • 401 – Token fehlt, ist ungültig, abgelaufen oder widerrufen.
  • 402 – Aktion durch das Tariflimit blockiert.
  • 404 – Ressource nicht gefunden (oder nicht im eigenen Team).
  • 429 – Rate-Limit erreicht (siehe rechts).

Rate-Limits

Zum Schutz vor Missbrauch ist die Anzahl der Anfragen pro Token begrenzt; das Volumen selbst ist unbegrenzt. Wird das Limit erreicht, antwortet die API mit 429 und einem Retry-After-Header (Sekunden):

HTTP/1.1 429 Too Many Requests
Retry-After: 42
Content-Type: application/problem+json

Warten Sie die angegebene Zeit ab und wiederholen Sie den Request. Für teure Aktionen (Upload, Versand) gilt ein strengeres Limit.

Webhooks

Statt zu pollen, lassen Sie sich benachrichtigen. Registrieren Sie Endpoints unter Verwaltung → Webhooks und abonnieren Sie Events:

  • signature.signed – eine Unterschrift wurde geleistet.
  • document.completed – alle Empfänger haben unterschrieben.
  • signature.rejected – ein:e Empfänger:in hat abgelehnt.
  • document.expired – die Frist wurde überschritten.

Payload

{
  "event": "document.completed",
  "occurredAt": "2026-07-28T13:00:00Z",
  "document": {
    "id": "3f2a...",
    "title": "Kaufvertrag PKW",
    "status": "Completed",
    "completedAt": "2026-07-28T13:00:00Z"
  },
  "signingRequest": null
}

Header: X-UES-Event, X-UES-Delivery, X-UES-Timestamp, X-UES-Signature. Fehlgeschlagene Zustellungen werden mit steigendem Abstand wiederholt; dauerhaft unerreichbare Endpoints werden automatisch deaktiviert.

Signatur prüfen

Die Signatur ist ein HMAC-SHA256 über timestamp + "." + rawBody mit Ihrem Endpoint-Secret:

const crypto = require("crypto");

function verify(secret, timestamp, rawBody, signature) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected), Buffer.from(signature));
}