Zum Inhalt springen

API-Dokumentation

Vollständige REST-API-Referenz für staffSign – Verträge erstellen, versenden und signieren.

Version 1.0 · Stand 2026-03-31

Basis-URL

https://api.promotionbasis.de/staffsign

Endpunkt-Übersicht

MethodPfadBeschreibung
POST/staffsign/contractsVertrag erstellen
GET/staffsign/contractsVerträge auflisten
GET/staffsign/contracts/{id}Vertrag abrufen
POST/staffsign/contracts/{id}/sendVertrag versenden
POST/staffsign/contracts/{id}/cancelVertrag stornieren
DELETE/staffsign/contracts/{id}Vertrag löschen
POST/staffsign/contracts/previewVertragsvorschau
GET/staffsign/contracts/{id}/download/signedSigniertes PDF herunterladen
GET/staffsign/contracts/{id}/download/audit-trailAudit-Trail herunterladen
GET/staffsign/contracts/{id}/download/sealedVersiegeltes PDF herunterladen
POST/staffsign/contracts/{id}/deliverZustellung auslösen
POST/staffsign/contract_templatesTemplate erstellen
GET/staffsign/contract_templatesTemplates auflisten
GET/staffsign/contract_templates/{id}Template abrufen
PATCH/staffsign/contract_templates/{id}Template aktualisieren
POST/staffsign/contract_templates/{id}/activateTemplate aktivieren
DELETE/staffsign/contract_templates/{id}Template archivieren
POST/staffsign/contract_templates/validateTemplate validieren

1. Authentifizierung

1.1 API-Key erstellen

API-Keys werden über das iPM-Dashboard verwaltet:

  1. In iPM einloggen unter pm.promotionbasis.de
  2. Navigieren Sie zu staffSign > API-Zugang
  3. Klicken Sie auf API-Key erstellen
  4. Optional: Vergeben Sie einen Titel (z. B. „Production“, „Staging“)
  5. Der vollständige API-Key wird einmalig angezeigt — sicher speichern
Wichtig: Der API-Key kann nach der Erstellung nicht erneut angezeigt werden. Bei Verlust muss ein neuer Key generiert werden.

1.2 API-Key verwenden

Alle Requests müssen den API-Key im X-Api-Key-Header enthalten:

HTTP-Request
GET /staffsign/contracts
X-Api-Key: <api-key>
Accept: application/json

1.3 Key-Format

Format: {userId}.{randomPart} — UUID-Präfix + 32-Zeichen-Zufallsteil:

550e8400-e29b-41d4-a716-446655440000.aB3dE7fG9hJ2kL5mN8pQ1rS4tU6vW0xY

1.4 Datenisolation & Key-Verwaltung

Jeder API-Key ist an eine Organization gebunden. Alle Daten sind automatisch auf die eigene Organization beschränkt.

AktionBeschreibung
ErstellenNeuen Key generieren. Mehrere Keys pro Organization möglich
RegenerierenNeuen Key für bestehenden Eintrag. Alter Key wird sofort ungültig
DeaktivierenKey temporär sperren (kann reaktiviert werden)
AktivierenGesperrten Key wieder aktivieren
LöschenKey permanent entfernen

2. Allgemeine Konventionen

2.1 Content-Type & Accept

Requests: Content-Type: application/json. Mit Accept: application/json erhalten Sie schlankes JSON ohne Hydra-Metadaten. Ohne diesen Header liefern Listen-Endpunkte application/ld+json zurück.

2.2 HTTP-Statuscodes

CodeBedeutung
200Erfolg (mit Response-Body)
201Ressource erstellt (mit Response-Body)
204Erfolg ohne Response-Body (Cancel, Delete, Activate, Update, Validate)
401Ungültiger oder fehlender API-Key
403Keine Berechtigung für diese Ressource
404Ressource nicht gefunden
422Validierungsfehler
500Interner Serverfehler

2.3 Datumsformate

KontextFormatBeispiel
Datumseingabe (Request)YYYY-MM-DD2026-04-01
Zeiteingabe (Request)HH:MM09:00
Datum in ResponseYYYY-MM-DD2026-04-01
Zeitstempel in ResponseYYYY-MM-DD HH:MM:SS2026-03-31 14:30:00
Zeitstempel (signedAt, Webhook)ISO 86012026-03-31T14:30:00+00:00

2.4 Enum-Werte

Format: kategorie.wert. In Responses doppelt: fieldName (lesbarer Text) und fieldNameKey (maschinenlesbarer Wert). Für Requests immer den Key-Wert verwenden.

2.5 Pagination

ParameterBeschreibungDefaultMax
pageSeitennummer1—
itemsPerPageEinträge pro Seite30100

Mit Accept: application/ld+json enthält die Response Hydra-Metadaten mit hydra:totalItems für Pagination-Metadaten.

3. Endpunkte: Contracts

POST/staffsign/contracts

Erstellt einen neuen Vertrag auf Basis einer Vorlage. Mindestens 2 Teilnehmer mit unterschiedlichen Rollen erforderlich.

Request Body
{
  "contractTemplateId": "550e8400-e29b-41d4-a716-446655440000",
  "signatureLevel": "signature_level.qes",
  "contractType": "contract_type.employment",
  "participants": [
    {
      "role": "contract_participant_role.employer",
      "signingMethod": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      }
    },
    {
      "role": "contract_participant_role.employee",
      "signingMethod": "signing_method.digital",
      "participantData": {
        "email": "max.mustermann@example.com",
        "firstName": "Max",
        "lastName": "Mustermann",
        "dateOfBirth": "1990-05-15"
      }
    }
  ],
  "terms": {
    "startDate": "2026-04-01",
    "endDate": "2026-09-30",
    "compensationType": "compensation_type.hourly",
    "compensationAmount": 18.50,
    "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
    "location": "Berlin, verschiedene Einsatzorte"
  },
  "employment": {
    "employmentType": "employment_type.temporary",
    "workDescription": "Promotion- und Messeeinsaetze",
    "probationPeriod": "6 Monate",
    "cancellationPeriod": "2 Wochen zum Monatsende"
  },
  "workingTime": {
    "scheduleType": "schedule_type.flexible",
    "description": "Ca. 20-40 Stunden pro Woche",
    "dailySchedule": [
      {
        "date": "2026-04-01",
        "startTime": "09:00",
        "endTime": "17:00",
        "breakMinutes": 30
      }
    ]
  },
  "usePbCoinContingent": false,
  "sendImmediately": false,
  "autoDeliverSignedDocument": true
}

Top-Level-Felder

FeldTypPflichtBeschreibung
contractTemplateIdUUIDJaID der zu verwendenden Vertragsvorlage
signatureLevelstringJaSignatur-Stufe (→ Enum 9.1)
contractTypestringNeinVertragstyp, Default: contract_type.employment
participantsarrayJaMindestens 2 Teilnehmer (siehe participants[])
termsobjectJaVertragsbedingungen (siehe terms)
employmentobjectNeinBeschäftigungsdetails (siehe employment)
workingTimeobjectNeinArbeitszeitregelung (siehe workingTime)
additionalTermsobjectNeinZusätzliche Felder (freie Struktur)
usePbCoinContingentbooleanNeinpbCoins für Signaturkosten verwenden (Default: false)
sendImmediatelybooleanNeinVertrag sofort versenden (Default: true)
autoDeliverSignedDocumentbooleanNeinSigniertes Dokument automatisch per E-Mail zustellen, sobald alle signiert haben (Default: true). Bei false muss die Zustellung manuell über POST /deliver ausgelöst werden.

participants[] — Teilnehmer

FeldTypPflichtBeschreibung
rolestringJaTeilnehmerrolle (→ Enum 9.3)
signingMethodstringJaSignaturmethode (→ Enum 9.2)
participantIdstringNeinOptionale externe Referenz-ID
participantDataobjectJaTeilnehmerdaten (→ Abschnitt 8.3)

terms — Vertragsbedingungen

FeldTypPflichtBeschreibung
startDatestringJaVertragsbeginn (YYYY-MM-DD)
endDatestringNeinVertragsende (YYYY-MM-DD)
compensationTypestringJaVergütungsart (→ Enum 9.5)
compensationAmountnumberJaVergütungsbetrag (>= 0)
compensationDescriptionstringNeinBeschreibung der Vergütung (max. 500 Zeichen)
locationstringNeinArbeitsort (max. 500 Zeichen)

employment — Beschäftigungsdetails (optional)

FeldTypPflichtBeschreibung
employmentTypestringJa*Beschäftigungsart (→ Enum 9.6)
workDescriptionstringNeinTätigkeitsbeschreibung (max. 2000 Zeichen)
probationPeriodstringNeinProbezeit (max. 255 Zeichen)
cancellationPeriodstringNeinKündigungsfrist (max. 255 Zeichen)

* Pflicht wenn das employment-Objekt mitgesendet wird.

workingTime — Arbeitszeitregelung (optional)

FeldTypPflichtBeschreibung
scheduleTypestringJa*Arbeitszeitmodell (→ Enum 9.7)
descriptionstringJa*Beschreibung der Arbeitszeit (max. 2000 Zeichen)
dailySchedulearrayNeinTagesplan-Einträge (siehe dailySchedule[])

dailySchedule[] — Tagesplan-Einträge

FeldTypPflichtBeschreibung
datestringJaDatum (YYYY-MM-DD)
startTimestringJaStartzeit (HH:MM)
endTimestringJaEndzeit (HH:MM)
breakMinutesintegerNeinPausendauer in Minuten (>= 0)
sendImmediately: true (Default): Direkt versendet. Status: contract_status.sent
sendImmediately: false: Als Draft erstellt. Separat über POST /contracts/{id}/send versenden.

Response: 201 Created — vollständige Contract-Struktur. E-Mail-Adressen müssen über alle Teilnehmer eindeutig sein.

Response 201 Created
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "org-uuid",
  "jobPostingId": null,
  "contractTemplateId": "template-uuid",
  "contractTemplateName": "Arbeitsvertrag Standard",
  "contractType": "Arbeitsvertrag",
  "contractTypeKey": "contract_type.employment",
  "status": "Entwurf",
  "statusKey": "contract_status.draft",
  "signatureLevel": "Qualifizierte elektronische Signatur",
  "signatureLevelKey": "signature_level.qes",
  "participants": [
    {
      "id": "participant-uuid-1",
      "role": "Arbeitgeber",
      "roleKey": "contract_participant_role.employer",
      "signingMethod": "Digitale Signatur",
      "signingMethodKey": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "dateOfBirth": null,
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "phone": "+49 30 123456",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      },
      "signedAt": null,
      "qesVerifiedAt": null
    }
  ],
  "startDate": "2026-04-01",
  "endDate": "2026-09-30",
  "compensationType": "Stuendlich",
  "compensationTypeKey": "compensation_type.hourly",
  "compensationAmount": "18.5",
  "sentAt": null,
  "createdAt": "2026-03-31 14:30:00",
  "autoDeliverSignedDocument": true,
  "signedDocumentDeliveredAt": null,
  // Nur beim Einzelabruf (GET /contracts/{id}):
  "expiresAt": null,
  "renderedContent": "<h1>Arbeitsvertrag</h1>...",
  "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
  "location": "Berlin, verschiedene Einsatzorte",
  "employmentType": "Befristet",
  "employmentTypeKey": "employment_type.temporary",
  "workDescription": "Promotion- und Messeeinsaetze",
  "probationPeriod": "6 Monate",
  "cancellationPeriod": "2 Wochen zum Monatsende",
  "scheduleType": "Flexibel",
  "scheduleTypeKey": "schedule_type.flexible",
  "workingTimeDescription": "Ca. 20-40 Stunden pro Woche",
  "externalDocumentId": null,
  "signedDocumentUrl": null,
  "auditTrailPdfUrl": null,
  "sealedPdfUrl": null
}
GET/staffsign/contracts

Listet alle Verträge der Organization auf. Unterstützt Pagination via ?page= und ?itemsPerPage=.

Request Body: Kein Body erforderlich.

Response 200 OK — Array
[
  {
    "id": "contract-uuid-1",
    "organizationId": "org-uuid",
    "jobPostingId": null,
    "contractTemplateId": "template-uuid",
    "contractTemplateName": "Arbeitsvertrag Standard",
    "contractType": "Arbeitsvertrag",
    "contractTypeKey": "contract_type.employment",
    "status": "Versendet",
    "statusKey": "contract_status.sent",
    "signatureLevel": "Qualifizierte elektronische Signatur",
    "signatureLevelKey": "signature_level.qes",
    "participants": [
      {
        "id": "participant-uuid-1",
        "role": "Arbeitgeber",
        "roleKey": "contract_participant_role.employer",
        "signingMethod": "Digitale Signatur",
        "signingMethodKey": "signing_method.digital",
        "participantId": null,
        "participantData": {
          "email": "hr@acme-staffing.de",
          "firstName": "Anna",
          "lastName": "Schmidt",
          "dateOfBirth": null,
          "company": "ACME Staffing GmbH",
          "gender": "gender.female",
          "phone": "+49 30 123456",
          "street": "Musterstrasse 123",
          "zipcode": "10115",
          "city": "Berlin",
          "country": "country.de"
        },
        "signedAt": null,
        "qesVerifiedAt": null
      }
    ],
    "startDate": "2026-04-01",
    "endDate": "2026-09-30",
    "compensationType": "Stuendlich",
    "compensationTypeKey": "compensation_type.hourly",
    "compensationAmount": "18.5",
    "sentAt": "2026-03-31 14:35:00",
    "createdAt": "2026-03-31 14:30:00",
    "autoDeliverSignedDocument": true
  }
]
Listenansicht vs. Einzelabruf: Folgende Felder sind nur beim Einzelabruf (GET /contracts/{id}) verfügbar:renderedContent, compensationDescription, location, employmentType/Key, workDescription, probationPeriod, cancellationPeriod, scheduleType/Key, workingTimeDescription, externalDocumentId, signedDocumentUrl, auditTrailPdfUrl, sealedPdfUrl, expiresAt, signedDocumentDeliveredAt.
GET/staffsign/contracts/{id}

Gibt die vollständige Contract-Struktur zurück — inkl. renderedContent, signedDocumentUrl und aller Detail-Felder (nur beim Einzelabruf verfügbar).

Request Body: Kein Body erforderlich.

Response 200 OK — vollständige Contract-Struktur
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "org-uuid",
  "jobPostingId": null,
  "contractTemplateId": "template-uuid",
  "contractTemplateName": "Arbeitsvertrag Standard",
  "contractType": "Arbeitsvertrag",
  "contractTypeKey": "contract_type.employment",
  "status": "Entwurf",
  "statusKey": "contract_status.draft",
  "signatureLevel": "Qualifizierte elektronische Signatur",
  "signatureLevelKey": "signature_level.qes",
  "participants": [
    {
      "id": "participant-uuid-1",
      "role": "Arbeitgeber",
      "roleKey": "contract_participant_role.employer",
      "signingMethod": "Digitale Signatur",
      "signingMethodKey": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "dateOfBirth": null,
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "phone": "+49 30 123456",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      },
      "signedAt": null,
      "qesVerifiedAt": null
    }
  ],
  "startDate": "2026-04-01",
  "endDate": "2026-09-30",
  "compensationType": "Stuendlich",
  "compensationTypeKey": "compensation_type.hourly",
  "compensationAmount": "18.5",
  "sentAt": null,
  "createdAt": "2026-03-31 14:30:00",
  "autoDeliverSignedDocument": true,
  "signedDocumentDeliveredAt": null,
  // Nur beim Einzelabruf (GET /contracts/{id}):
  "expiresAt": null,
  "renderedContent": "<h1>Arbeitsvertrag</h1>...",
  "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
  "location": "Berlin, verschiedene Einsatzorte",
  "employmentType": "Befristet",
  "employmentTypeKey": "employment_type.temporary",
  "workDescription": "Promotion- und Messeeinsaetze",
  "probationPeriod": "6 Monate",
  "cancellationPeriod": "2 Wochen zum Monatsende",
  "scheduleType": "Flexibel",
  "scheduleTypeKey": "schedule_type.flexible",
  "workingTimeDescription": "Ca. 20-40 Stunden pro Woche",
  "externalDocumentId": null,
  "signedDocumentUrl": null,
  "auditTrailPdfUrl": null,
  "sealedPdfUrl": null
}
POST/staffsign/contracts/{id}/send

Sendet einen Draft-Vertrag zur Signatur an alle Teilnehmer mit signing_method.digital.

Request Body
// // Kein Request-Body erforderlich — kein Response-Body
Response 200 OK — Contract-Struktur mit statusKey: contract_status.sent
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "org-uuid",
  "jobPostingId": null,
  "contractTemplateId": "template-uuid",
  "contractTemplateName": "Arbeitsvertrag Standard",
  "contractType": "Arbeitsvertrag",
  "contractTypeKey": "contract_type.employment",
  "status": "Entwurf",
  "statusKey": "contract_status.draft",
  "signatureLevel": "Qualifizierte elektronische Signatur",
  "signatureLevelKey": "signature_level.qes",
  "participants": [
    {
      "id": "participant-uuid-1",
      "role": "Arbeitgeber",
      "roleKey": "contract_participant_role.employer",
      "signingMethod": "Digitale Signatur",
      "signingMethodKey": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "dateOfBirth": null,
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "phone": "+49 30 123456",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      },
      "signedAt": null,
      "qesVerifiedAt": null
    }
  ],
  "startDate": "2026-04-01",
  "endDate": "2026-09-30",
  "compensationType": "Stuendlich",
  "compensationTypeKey": "compensation_type.hourly",
  "compensationAmount": "18.5",
  "sentAt": null,
  "createdAt": "2026-03-31 14:30:00",
  "autoDeliverSignedDocument": true,
  "signedDocumentDeliveredAt": null,
  // Nur beim Einzelabruf (GET /contracts/{id}):
  "expiresAt": null,
  "renderedContent": "<h1>Arbeitsvertrag</h1>...",
  "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
  "location": "Berlin, verschiedene Einsatzorte",
  "employmentType": "Befristet",
  "employmentTypeKey": "employment_type.temporary",
  "workDescription": "Promotion- und Messeeinsaetze",
  "probationPeriod": "6 Monate",
  "cancellationPeriod": "2 Wochen zum Monatsende",
  "scheduleType": "Flexibel",
  "scheduleTypeKey": "schedule_type.flexible",
  "workingTimeDescription": "Ca. 20-40 Stunden pro Woche",
  "externalDocumentId": null,
  "signedDocumentUrl": null,
  "auditTrailPdfUrl": null,
  "sealedPdfUrl": null
}
Voraussetzung: Vertrag muss Status contract_status.draft haben.
POST/staffsign/contracts/{id}/cancel

Storniert einen versendeten Vertrag. Auch Verträge mit Teilunterschriften können storniert werden.

Request Body
// // Kein Request-Body erforderlich — kein Response-Body
Response
// 204 No Content — kein Response-Body
Voraussetzung: Status contract_status.sent.
Kosten bei Teilunterschriften: Wenn mindestens ein Teilnehmer bereits signiert hat, werden volle Signaturkosten berechnet.
DELETE/staffsign/contracts/{id}

Löscht einen Draft-Vertrag permanent. Versendete oder signierte Verträge können nicht gelöscht, aber storniert werden.

Request Body
// // Kein Request-Body erforderlich — kein Response-Body
Response
// 204 No Content — kein Response-Body
Voraussetzung: Vertrag muss Status contract_status.draft haben.
POST/staffsign/contracts/preview

Rendert eine Vorschau ohne Datenspeicherung. Ideal zum Testen von Template und Daten. Kein Datensatz wird erstellt.

Request Body: Identisch zum POST /contracts-Request.

Request Body (identisch zu POST /contracts)
{
  "contractTemplateId": "550e8400-e29b-41d4-a716-446655440000",
  "signatureLevel": "signature_level.qes",
  "contractType": "contract_type.employment",
  "participants": [
    {
      "role": "contract_participant_role.employer",
      "signingMethod": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      }
    },
    {
      "role": "contract_participant_role.employee",
      "signingMethod": "signing_method.digital",
      "participantData": {
        "email": "max.mustermann@example.com",
        "firstName": "Max",
        "lastName": "Mustermann",
        "dateOfBirth": "1990-05-15"
      }
    }
  ],
  "terms": {
    "startDate": "2026-04-01",
    "endDate": "2026-09-30",
    "compensationType": "compensation_type.hourly",
    "compensationAmount": 18.50,
    "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
    "location": "Berlin, verschiedene Einsatzorte"
  },
  "employment": {
    "employmentType": "employment_type.temporary",
    "workDescription": "Promotion- und Messeeinsaetze",
    "probationPeriod": "6 Monate",
    "cancellationPeriod": "2 Wochen zum Monatsende"
  },
  "workingTime": {
    "scheduleType": "schedule_type.flexible",
    "description": "Ca. 20-40 Stunden pro Woche",
    "dailySchedule": [
      {
        "date": "2026-04-01",
        "startTime": "09:00",
        "endTime": "17:00",
        "breakMinutes": 30
      }
    ]
  },
  "usePbCoinContingent": false,
  "sendImmediately": false,
  "autoDeliverSignedDocument": true
}
Response 200 OK
{
  "contract": {
    "id": "preview-uuid-nicht-persistiert",
    "organizationId": "org-uuid",
    "jobPostingId": null,
    "contractTemplateId": "template-uuid",
    "contractTemplateName": "Arbeitsvertrag Standard",
    "contractType": "Arbeitsvertrag",
    "contractTypeKey": "contract_type.employment",
    "status": "Entwurf",
    "statusKey": "contract_status.draft",
    "signatureLevel": "Qualifizierte elektronische Signatur",
    "signatureLevelKey": "signature_level.qes",
    "participants": [
      {
        "id": "preview-participant-uuid-1",
        "role": "Arbeitgeber",
        "roleKey": "contract_participant_role.employer",
        "signingMethod": "Digitale Signatur",
        "signingMethodKey": "signing_method.digital",
        "participantId": null,
        "participantData": {
          "email": "hr@acme-staffing.de",
          "firstName": "Anna",
          "lastName": "Schmidt",
          "dateOfBirth": null,
          "company": "ACME Staffing GmbH",
          "gender": "gender.female",
          "phone": "+49 30 123456",
          "street": "Musterstrasse 123",
          "zipcode": "10115",
          "city": "Berlin",
          "country": "country.de"
        },
        "signedAt": null,
        "qesVerifiedAt": null
      },
      {
        "id": "preview-participant-uuid-2",
        "role": "Arbeitnehmer",
        "roleKey": "contract_participant_role.employee",
        "signingMethod": "Digitale Signatur",
        "signingMethodKey": "signing_method.digital",
        "participantId": null,
        "participantData": {
          "email": "max.mustermann@example.com",
          "firstName": "Max",
          "lastName": "Mustermann",
          "dateOfBirth": "1990-05-15 00:00:00",
          "company": null,
          "gender": null,
          "phone": null,
          "street": "Beispielweg 42",
          "zipcode": "10178",
          "city": "Berlin",
          "country": "country.de"
        },
        "signedAt": null,
        "qesVerifiedAt": null
      }
    ],
    "startDate": "2026-04-01",
    "endDate": "2026-09-30",
    "compensationType": "Stuendlich",
    "compensationTypeKey": "compensation_type.hourly",
    "compensationAmount": "18.5",
    "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
    "location": "Berlin, verschiedene Einsatzorte",
    "employmentType": "Befristet",
    "employmentTypeKey": "employment_type.temporary",
    "workDescription": "Promotion- und Messeeinsaetze",
    "probationPeriod": "6 Monate",
    "cancellationPeriod": "2 Wochen zum Monatsende",
    "scheduleType": "Flexibel",
    "scheduleTypeKey": "schedule_type.flexible",
    "workingTimeDescription": "Ca. 20-40 Stunden pro Woche",
    "renderedContent": "<h1>Arbeitsvertrag</h1><p>Zwischen ACME Staffing GmbH...</p>",
    "externalDocumentId": null,
    "signedDocumentUrl": null,
    "auditTrailPdfUrl": null,
    "sealedPdfUrl": null,
    "expiresAt": null,
    "sentAt": null,
    "createdAt": "2026-04-01 10:00:00"
  },
  "renderedContent": "<h1>Arbeitsvertrag</h1><p>Zwischen ACME Staffing GmbH...</p>",
  "canBeSent": true,
  "missingPlaceholders": [],
  "articles": [
    {
      "articleNumber": "20.20.20.00",
      "productType": "product_type.signature",
      "productCategory": "product_category.staffsign",
      "title": "QES-Signatur",
      "description": "Qualifizierte elektronische Signatur",
      "quantity": 2,
      "unitPrice": 6.0,
      "sumPrice": 12.0,
      "listUnitPrice": 6.0,
      "listSumPrice": 12.0,
      "discountInfo": null,
      "pbCoinPrice": 300,
      "pbCoinGain": 0,
      "pbCoinDiscount": 0
    }
  ],
  "requiresIdentification": true,
  "requiresOrganizationIdentification": false
}

Response-Felder

FeldTypBeschreibung
contractobjectVollständige Contract-Struktur (Vorschau, nicht gespeichert)
renderedContentstringGerenderter HTML-Inhalt des Vertrags
canBeSentbooleantrue wenn alle Platzhalter befüllt sind
missingPlaceholdersarrayListe fehlender Platzhalter-Namen
articlesarrayBerechnete Kostenartikel (Signaturprodukte mit Preis + pbCoin-Wert)
requiresIdentificationbooleanQES-Identifikation für Empfänger erforderlich
requiresOrganizationIdentificationbooleanQES-Identifikation für Organization erforderlich
GET/staffsign/contracts/{id}/download/signed

Lädt das signierte Vertrags-PDF als Datei herunter. Verfügbar, sobald alle Teilnehmer signiert haben (statusKey: contract_status.signed) und signedDocumentUrl gesetzt ist.

Request Body: Kein Body erforderlich.

Response: 200 OK – Content-Type: application/pdf, Dateiname contract_{id}_signed.pdf.

Voraussetzung: Vertrag muss vollständig signiert sein und signedDocumentUrl gesetzt haben.
GET/staffsign/contracts/{id}/download/audit-trail

Lädt den Audit-Trail als PDF herunter. Er enthält ein kryptographisch verifizierbares Protokoll aller Signaturereignisse (wer, wann, IP-Adresse, Verifizierungsmethode). Verfügbar nach vollständiger Signierung (auditTrailPdfUrl gesetzt).

Request Body: Kein Body erforderlich.

Response: 200 OK – Content-Type: application/pdf, Dateiname contract_{id}_audit_trail.pdf.

GET/staffsign/contracts/{id}/download/sealed

Lädt das versiegelte PDF mit eingebetteten digitalen Signaturen und angehängtem Audit-Trail herunter. Es ist das langzeitarchivierungsfähige Endprodukt des Signaturprozesses (sealedPdfUrl gesetzt).

Request Body: Kein Body erforderlich.

Response: 200 OK – Content-Type: application/pdf, Dateiname contract_{id}_sealed.pdf.

POST/staffsign/contracts/{id}/deliver

Löst die Zustellung des signierten Dokuments per E-Mail an alle Teilnehmer aus. Nur nötig, wenn der Vertrag mit autoDeliverSignedDocument: false erstellt wurde. Bei automatischer Zustellung (Standard) wird dieser Endpunkt nicht gebraucht.

Request Body: Kein Body erforderlich.

Response 200 OK – aktualisierter Vertrag (signedDocumentDeliveredAt gesetzt)
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "org-uuid",
  "jobPostingId": null,
  "contractTemplateId": "template-uuid",
  "contractTemplateName": "Arbeitsvertrag Standard",
  "contractType": "Arbeitsvertrag",
  "contractTypeKey": "contract_type.employment",
  "status": "Entwurf",
  "statusKey": "contract_status.draft",
  "signatureLevel": "Qualifizierte elektronische Signatur",
  "signatureLevelKey": "signature_level.qes",
  "participants": [
    {
      "id": "participant-uuid-1",
      "role": "Arbeitgeber",
      "roleKey": "contract_participant_role.employer",
      "signingMethod": "Digitale Signatur",
      "signingMethodKey": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "dateOfBirth": null,
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "phone": "+49 30 123456",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      },
      "signedAt": null,
      "qesVerifiedAt": null
    }
  ],
  "startDate": "2026-04-01",
  "endDate": "2026-09-30",
  "compensationType": "Stuendlich",
  "compensationTypeKey": "compensation_type.hourly",
  "compensationAmount": "18.5",
  "sentAt": null,
  "createdAt": "2026-03-31 14:30:00",
  "autoDeliverSignedDocument": true,
  "signedDocumentDeliveredAt": null,
  // Nur beim Einzelabruf (GET /contracts/{id}):
  "expiresAt": null,
  "renderedContent": "<h1>Arbeitsvertrag</h1>...",
  "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
  "location": "Berlin, verschiedene Einsatzorte",
  "employmentType": "Befristet",
  "employmentTypeKey": "employment_type.temporary",
  "workDescription": "Promotion- und Messeeinsaetze",
  "probationPeriod": "6 Monate",
  "cancellationPeriod": "2 Wochen zum Monatsende",
  "scheduleType": "Flexibel",
  "scheduleTypeKey": "schedule_type.flexible",
  "workingTimeDescription": "Ca. 20-40 Stunden pro Woche",
  "externalDocumentId": null,
  "signedDocumentUrl": null,
  "auditTrailPdfUrl": null,
  "sealedPdfUrl": null
}
Voraussetzung: Vertrag muss vollständig signiert sein. Ist bereits zugestellt (signedDocumentDeliveredAt gesetzt), gibt die API einen Fehler zurück.

4. Endpunkte: Contract Templates

POST/staffsign/contract_templates

Erstellt eine neue Vertragsvorlage. Neues Template hat Status contract_template_status.draft und muss separat aktiviert werden.

Request Body
{
  "name": "Arbeitsvertrag Befristet",
  "description": "Vorlage fuer befristete Arbeitsvertraege im Promotionbereich",
  "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**, vertreten durch {{ employer.fullName }},\nnachfolgend \"Arbeitgeber\",\n\nund **{{ employee.fullName }}**, geb. am {{ employee.dateOfBirth }},\nnachfolgend \"Arbeitnehmer\".\n\n## § 1 Beginn und Dauer\n\nDas Arbeitsverhaeltnis beginnt am {{ contract.startDate }}.",
  "renderLogo": true
}

Request-Felder

FeldTypPflichtBeschreibung
namestringJaName der Vorlage (2–255 Zeichen)
descriptionstringNeinBeschreibung (max. 1000 Zeichen)
contentstringJaTemplate-Inhalt in Markdown + Twig-Syntax (min. 10 Zeichen)
renderLogobooleanNeinOrganisations-Logo im PDF-Header rendern (Default: true)

Template-Syntax (Markdown + Twig)

content — Beispiel
# Arbeitsvertrag

Zwischen **{{ employer.company }}**, vertreten durch {{ employer.fullName }},
nachfolgend "Arbeitgeber",

und **{{ employee.fullName }}**, geb. am {{ employee.dateOfBirth }},
nachfolgend "Arbeitnehmer".

## § 1 Beginn und Dauer

Das Arbeitsverhaeltnis beginnt am {{ contract.startDate }}
und ist befristet bis {{ contract.endDate }}.

## § 2 Verguetung

Verguetung: {{ contract.compensationAmount }} EUR ({{ contract.compensationType }}).

Ort, Datum: {{ today }}

Verfügbare Platzhalter-Gruppen

PrefixBeschreibung
employer.*Arbeitgeber-Daten
employee.*Arbeitnehmer-Daten
contract.*Vertragsbedingungen
employment.*Beschäftigungsdetails
workingTime.*Arbeitszeitdaten
todayAktuelles Datum

Unbekannte Platzhalter werden bei der Validierung als Fehler zurückgegeben (422).

Response 201 Created
{
  "id": "template-uuid",
  "name": "Arbeitsvertrag Standard",
  "description": "Standard-Arbeitsvertrag fuer befristete Beschaeftigung",
  "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**, vertreten durch {{ employer.fullName }}...",
  "renderLogo": true,
  "isSystemTemplate": false,
  "organizationId": "org-uuid",
  "status": "Aktiv",
  "statusKey": "contract_template_status.active",
  "createdAt": "2026-03-01 10:00:00",
  "lastModified": "2026-03-15 14:30:00",
  "usedPlaceholders": [
    "employer.company",
    "employer.fullName",
    "employee.fullName",
    "employee.dateOfBirth",
    "contract.startDate",
    "contract.compensationAmount"
  ],
  "requiredFields": [
    "contract.compensationAmount",
    "contract.startDate",
    "employee.dateOfBirth",
    "employee.firstName",
    "employee.lastName",
    "employer.company",
    "employer.firstName",
    "employer.lastName"
  ]
}
GET/staffsign/contract_templates

Listet alle verfügbaren Templates auf. Unterstützt Pagination via ?page= und ?itemsPerPage=.

Request Body: Kein Body erforderlich.

Response 200 OK — Array (vollständige Struktur, kein reduzierter Listen-Modus)
[
  {
    "id": "template-uuid",
    "name": "Arbeitsvertrag Standard",
    "description": "Standard-Arbeitsvertrag fuer befristete Beschaeftigung",
    "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**...",
    "isSystemTemplate": true,
    "organizationId": null,
    "status": "Aktiv",
    "statusKey": "contract_template_status.active",
    "createdAt": "2026-03-01 10:00:00",
    "lastModified": "2026-03-15 14:30:00",
    "usedPlaceholders": ["employer.company", "employee.fullName", "contract.startDate"],
    "requiredFields": ["employer.company", "employee.firstName", "employee.lastName", "contract.startDate"]
  }
]
GET/staffsign/contract_templates/{id}

Gibt das vollständige Template zurück — identische Struktur wie in der Listenansicht.

Request Body: Kein Body erforderlich.

Response 200 OK
{
  "id": "template-uuid",
  "name": "Arbeitsvertrag Standard",
  "description": "Standard-Arbeitsvertrag fuer befristete Beschaeftigung",
  "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**, vertreten durch {{ employer.fullName }}...",
  "renderLogo": true,
  "isSystemTemplate": false,
  "organizationId": "org-uuid",
  "status": "Aktiv",
  "statusKey": "contract_template_status.active",
  "createdAt": "2026-03-01 10:00:00",
  "lastModified": "2026-03-15 14:30:00",
  "usedPlaceholders": [
    "employer.company",
    "employer.fullName",
    "employee.fullName",
    "employee.dateOfBirth",
    "contract.startDate",
    "contract.compensationAmount"
  ],
  "requiredFields": [
    "contract.compensationAmount",
    "contract.startDate",
    "employee.dateOfBirth",
    "employee.firstName",
    "employee.lastName",
    "employer.company",
    "employer.firstName",
    "employer.lastName"
  ]
}
PATCH/staffsign/contract_templates/{id}

Aktualisiert eine bestehende Vorlage. System-Templates können nicht aktualisiert werden.

Request Body
{
  "name": "Arbeitsvertrag Befristet (aktualisiert)",
  "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**...",
  "description": "Aktualisierte Vorlage",
  "renderLogo": false
}

Request-Felder

FeldTypPflichtBeschreibung
namestringJaName (2–255 Zeichen)
contentstringJaTemplate-Inhalt (min. 10 Zeichen)
descriptionstringNeinBeschreibung (max. 1000 Zeichen)
renderLogobooleanNeinOrganisations-Logo im PDF-Header rendern
Response 204 No Content
// 204 No Content — kein Response-Body
POST/staffsign/contract_templates/{id}/activate

Setzt ein Draft-Template auf aktiv, sodass es für neue Verträge verwendet werden kann.

Request Body
// // Kein Request-Body erforderlich — kein Response-Body
Response
// 204 No Content — kein Response-Body
Voraussetzung: Template muss Status contract_template_status.draft haben.
DELETE/staffsign/contract_templates/{id}

Archiviert ein Template. Archivierte Templates können nicht mehr für neue Verträge verwendet werden.

Request Body
// // Kein Request-Body erforderlich — kein Response-Body
Response
// 204 No Content — kein Response-Body
POST/staffsign/contract_templates/validate

Validiert ein Template ohne es zu speichern. Prüft Platzhalter-Syntax und unbekannte Variablen.

Request Body (identisch zu POST /contract_templates)
{
  "name": "Arbeitsvertrag Befristet",
  "description": "Vorlage fuer befristete Arbeitsvertraege im Promotionbereich",
  "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**, vertreten durch {{ employer.fullName }},\nnachfolgend \"Arbeitgeber\",\n\nund **{{ employee.fullName }}**, geb. am {{ employee.dateOfBirth }},\nnachfolgend \"Arbeitnehmer\".\n\n## § 1 Beginn und Dauer\n\nDas Arbeitsverhaeltnis beginnt am {{ contract.startDate }}.",
  "renderLogo": true
}
Response — 204 bei Erfolg, 422 bei Validierungsfehlern
// 204 No Content — kein Response-Body

5. Webhooks

Webhooks benachrichtigen Ihr System automatisch per HTTP POST bei relevanten Ereignissen. Konfiguration über iPM-Dashboard → staffSign → Webhooks. Pro Organization können mehrere Webhooks eingerichtet werden.

5.1 Events

EventBeschreibung
contract.createdVertrag wurde erstellt
contract.sentVertrag zur Signatur versendet
contract.recipient_signedEmpfänger hat signiert
contract.organization_signedOrganization hat signiert
contract.completedAlle Signaturen abgeschlossen
contract.document_readySigniertes PDF ist abrufbar
contract.cancelledVertrag wurde storniert
contract.expiredVertrag ist abgelaufen
identification.completedeID-Identifikation abgeschlossen
contract.completed vs. contract.document_ready: completed feuert wenn alle Teilnehmer signiert haben. document_ready feuert wenn das PDF tatsächlich abrufbar ist — kann zeitlich versetzt sein. Für automatisierte Dokumentenabholung ist document_ready das relevantere Event.

5.2 Payload-Format

Eingehender Webhook-Request
POST https://ihr-system.example.com/webhook
Content-Type: application/json
X-Webhook-Signature: sha256=a1b2c3d4e5f6...
X-Webhook-Event: contract.recipient_signed

{
  "event": "contract.recipient_signed",
  "timestamp": "2026-03-31T14:45:00+00:00",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "Versendet",
    "statusKey": "contract_status.sent",
    "participants": [
      { "role": "Arbeitgeber", "signedAt": null },
      { "role": "Arbeitnehmer", "signedAt": "2026-03-31T14:45:00+00:00" }
    ],
    ...
  }
}

Das data-Feld enthält die vollständige Contract-Repräsentation (ohne renderedContent und qesVerifiedAt).

5.3 Signatur-Verifizierung

Header: X-Webhook-Signature: sha256=<hex-digest>. Berechnung: HMAC-SHA256(request_body, webhook_secret).

PHP

$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$payload   = file_get_contents('php://input');
$secret    = 'ihr-webhook-secret';
$expected  = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}
$data = json_decode($payload, true);

Node.js

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Python

import hmac, hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

5.4 Retry, Timeout & Auto-Deaktivierung

Retry-Logik

VersuchWartezeit
1. Retry~10 s
2. Retry~40 s
3. Retry~160 s

Nach 3 Retries → aufgegeben.

Timeout

10 Sekunden. Aufwändige Verarbeitung asynchron ausführen, sofort HTTP 200 zurückgeben.

Auto-Deaktivierung

Nach 30 Fehlern automatisch deaktiviert. Im iPM-Dashboard reaktivierbar. Eine erfolgreiche Zustellung (HTTP 2xx) setzt den Fehlerzähler zurück.

6. MCP-Server (KI-Agent-Integration)

Nativer MCP-Server für KI-Agenten. Gleiche Authentifizierung wie die REST-API. 12 Tools + 2 Resources.

6.1 Konfiguration

MCP-Endpoint: https://www.promotionbasis.de/api/mcp

Claude Desktop

{
  "mcpServers": {
    "staffsign": {
      "type": "http",
      "url": "https://www.promotionbasis.de/api/mcp",
      "headers": {
        "X-Api-Key": "<api-key>"
      }
    }
  }
}

Cursor

{
  "mcpServers": {
    "staffsign": {
      "type": "http",
      "url": "https://www.promotionbasis.de/api/mcp",
      "headers": {
        "X-Api-Key": "<api-key>"
      }
    }
  }
}

Microsoft Copilot

{
  "mcpServers": {
    "staffsign": {
      "type": "http",
      "url": "https://www.promotionbasis.de/api/mcp",
      "headers": {
        "X-Api-Key": "<api-key>"
      }
    }
  }
}

6.2 Tools & Resources

Contract-Tools

ToolBeschreibung
search_contractsContracts auflisten mit Filter
get_contractVollständige Contract-Details
create_contractNeuen Vertrag aus Template erstellen
send_contractDraft-Vertrag versenden
cancel_contractVersendeten Vertrag stornieren
delete_contractDraft-Vertrag löschen

Template-Tools

ToolBeschreibung
search_contract_templatesTemplates suchen
get_contract_templateVollständiges Template abrufen
create_contract_templateNeues Template erstellen
update_contract_templateTemplate aktualisieren
activate_contract_templateDraft-Template aktivieren
archive_contract_templateTemplate archivieren

Resources

ResourceURIBeschreibung
contract_template_placeholderscontract-templates://placeholdersAlle verfügbaren Platzhalter, gruppiert
create_contract_schemacontracts://create-schemaSchema + Beispiel-Request + alle Enum-Werte

6.3 Empfohlener Workflow

  1. 1
    Resource lesen:contract_template_placeholders — Platzhalter verstehen
  2. 2
    Templates suchen:search_contract_templates — passende Vorlage finden
  3. 3
    Template abrufen:get_contract_template — Content und requiredFields prüfen
  4. 4
    Schema lesen:create_contract_schema — Enum-Werte und Struktur verstehen
  5. 5
    Vertrag erstellen:create_contract mit sendImmediately: false — als Draft anlegen
  6. 6
    Vertrag versenden:send_contract — zur Signatur freigeben
  7. 7
    Status prüfen:get_contract — Signatur-Status abfragen

7. Fehlerbehandlung

7.1 Validierungsfehler (422)

Response 422
{
  "violations": [
    {
      "propertyPath": "signatureLevel",
      "message": "Dieser Wert sollte nicht leer sein.",
      "code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3"
    },
    {
      "propertyPath": "participants",
      "message": "Diese Gruppe muss mindestens 2 Elemente enthalten.",
      "code": "bef8e338-6ae5-4caf-b8e2-50e7b0579e69"
    }
  ]
}

7.2 Häufige Fehlerszenarien

SzenarioCodeUrsache
Fehlender API-Key401X-Api-Key-Header nicht gesetzt
Ungültiger API-Key401Key existiert nicht oder ist deaktiviert
Falsches Format401Key hat nicht das Format {id}.{random}
Validierungsfehler422Pflichtfelder fehlen oder ungültige Werte
Vertrag nicht im Draft422Versuch, versendeten Vertrag zu löschen
Vertrag nicht stornierbar422Vertrag nicht im Status sent
Template nicht aktiv422Vertrag mit Draft- oder archiviertem Template
Doppelte E-Mail422Zwei Teilnehmer mit identischer E-Mail
Ungültige Platzhalter422Template enthält unbekannte Variablen
Nicht gefunden404ID existiert nicht oder gehört zu anderer Organization

8. Datenstrukturen

8.1 Contract

Contract — vollständige Struktur (Einzelabruf)
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "organizationId": "org-uuid",
  "jobPostingId": null,
  "contractTemplateId": "template-uuid",
  "contractTemplateName": "Arbeitsvertrag Standard",
  "contractType": "Arbeitsvertrag",
  "contractTypeKey": "contract_type.employment",
  "status": "Entwurf",
  "statusKey": "contract_status.draft",
  "signatureLevel": "Qualifizierte elektronische Signatur",
  "signatureLevelKey": "signature_level.qes",
  "participants": [
    {
      "id": "participant-uuid-1",
      "role": "Arbeitgeber",
      "roleKey": "contract_participant_role.employer",
      "signingMethod": "Digitale Signatur",
      "signingMethodKey": "signing_method.digital",
      "participantId": null,
      "participantData": {
        "email": "hr@acme-staffing.de",
        "firstName": "Anna",
        "lastName": "Schmidt",
        "dateOfBirth": null,
        "company": "ACME Staffing GmbH",
        "gender": "gender.female",
        "phone": "+49 30 123456",
        "street": "Musterstrasse 123",
        "zipcode": "10115",
        "city": "Berlin",
        "country": "country.de"
      },
      "signedAt": null,
      "qesVerifiedAt": null
    }
  ],
  "startDate": "2026-04-01",
  "endDate": "2026-09-30",
  "compensationType": "Stuendlich",
  "compensationTypeKey": "compensation_type.hourly",
  "compensationAmount": "18.5",
  "sentAt": null,
  "createdAt": "2026-03-31 14:30:00",
  "autoDeliverSignedDocument": true,
  "signedDocumentDeliveredAt": null,
  // Nur beim Einzelabruf (GET /contracts/{id}):
  "expiresAt": null,
  "renderedContent": "<h1>Arbeitsvertrag</h1>...",
  "compensationDescription": "Stundenlohn zzgl. Zuschlaege",
  "location": "Berlin, verschiedene Einsatzorte",
  "employmentType": "Befristet",
  "employmentTypeKey": "employment_type.temporary",
  "workDescription": "Promotion- und Messeeinsaetze",
  "probationPeriod": "6 Monate",
  "cancellationPeriod": "2 Wochen zum Monatsende",
  "scheduleType": "Flexibel",
  "scheduleTypeKey": "schedule_type.flexible",
  "workingTimeDescription": "Ca. 20-40 Stunden pro Woche",
  "externalDocumentId": null,
  "signedDocumentUrl": null,
  "auditTrailPdfUrl": null,
  "sealedPdfUrl": null
}
FeldTypBeschreibung
idUUIDVertrags-ID
organizationIdUUIDOrganization-ID
jobPostingIdUUID|nullZugehörige Stellenanzeige
contractTemplateIdUUIDID der verwendeten Vorlage
contractTemplateNamestringName der Vorlage
contractType / contractTypeKeystringVertragstyp (lesbar / maschinenlesbar)
status / statusKeystringStatus (lesbar / maschinenlesbar, → Enum 9.4)
signatureLevel / signatureLevelKeystringSignatur-Stufe (→ Enum 9.1)
participantsarrayTeilnehmer mit Rollen, Methoden, Daten, signedAt, qesVerifiedAt
startDatestringVertragsbeginn (YYYY-MM-DD)
endDatestring|nullVertragsende (YYYY-MM-DD)
compensationType / compensationTypeKeystringVergütungsart (→ Enum 9.5)
compensationAmountstringVergütungsbetrag
sentAtstring|nullVersandzeitpunkt
createdAtstringErstellungszeitpunkt
expiresAt *string|nullAblaufzeitpunkt der Signaturfrist
renderedContent *stringGerenderter HTML-Inhalt
compensationDescription *string|nullBeschreibung der Vergütung
location *string|nullArbeitsort
employmentType / employmentTypeKey *string|nullBeschäftigungsart (→ Enum 9.6)
workDescription *string|nullTätigkeitsbeschreibung
probationPeriod *string|nullProbezeit
cancellationPeriod *string|nullKündigungsfrist
scheduleType / scheduleTypeKey *string|nullArbeitszeitmodell (→ Enum 9.7)
workingTimeDescription *string|nullBeschreibung der Arbeitszeit
externalDocumentId *string|nullPaperless-Dokument-ID
signedDocumentUrl *string|nullURL zum signierten PDF (nach allen Signaturen)
auditTrailPdfUrl *string|nullURL zum Audit-Trail-PDF
sealedPdfUrl *string|nullURL zum versiegelten PDF

* Nur beim Einzelabruf (GET /contracts/{id}) verfügbar, nicht in der Listenansicht.

8.2 ContractTemplate

ContractTemplate — vollständige Struktur
{
  "id": "template-uuid",
  "name": "Arbeitsvertrag Standard",
  "description": "Standard-Arbeitsvertrag fuer befristete Beschaeftigung",
  "content": "# Arbeitsvertrag\n\nZwischen **{{ employer.company }}**, vertreten durch {{ employer.fullName }}...",
  "renderLogo": true,
  "isSystemTemplate": false,
  "organizationId": "org-uuid",
  "status": "Aktiv",
  "statusKey": "contract_template_status.active",
  "createdAt": "2026-03-01 10:00:00",
  "lastModified": "2026-03-15 14:30:00",
  "usedPlaceholders": [
    "employer.company",
    "employer.fullName",
    "employee.fullName",
    "employee.dateOfBirth",
    "contract.startDate",
    "contract.compensationAmount"
  ],
  "requiredFields": [
    "contract.compensationAmount",
    "contract.startDate",
    "employee.dateOfBirth",
    "employee.firstName",
    "employee.lastName",
    "employer.company",
    "employer.firstName",
    "employer.lastName"
  ]
}
FeldTypBeschreibung
idUUIDTemplate-ID
namestringName (2–255 Zeichen)
descriptionstring|nullOptionale Beschreibung
contentstringTemplate-Inhalt (Markdown + Twig-Syntax)
isSystemTemplatebooleantrue bei von staffSign bereitgestellten Systemvorlagen
organizationIdUUID|nullOrganization-ID (null bei Systemvorlagen)
status / statusKeystringStatus (lesbar / maschinenlesbar, → Enum 9.9)
createdAtstringErstellungszeitpunkt (YYYY-MM-DD HH:MM:SS)
lastModifiedstringLetzte Änderung
usedPlaceholdersstring[]Alle im Template verwendeten Platzhalter-Variablen
requiredFieldsstring[]Benötigte Eingabefelder (computed wie fullName → firstName + lastName)
Hinweis: Templates liefern in Liste und Einzelabruf die identische vollständige Struktur.

8.3 ParticipantData

FeldTypPflichtBeschreibung
emailstringJa*E-Mail-Adresse (Pflicht für signing_method.digital)
firstNamestringNeinVorname (max. 255 Zeichen)
lastNamestringNeinNachname (max. 255 Zeichen)
dateOfBirthstringNeinGeburtsdatum (YYYY-MM-DD)
companystringNeinFirmenname (max. 255 Zeichen)
genderstringNeinGeschlecht (→ Enum 9.8)
phonestringNeinTelefonnummer (max. 30 Zeichen)
streetstringNeinStraße (max. 255 Zeichen)
zipcodestringNeinPostleitzahl (max. 20 Zeichen)
citystringNeinStadt (max. 255 Zeichen)
countrystringNeinLand (→ Enum 9.10)

9. Enum-Referenz

9.1 SignatureLevel

WertBeschreibung
signature_level.aesFortgeschrittene elektronische Signatur (AES)
signature_level.qesQualifizierte elektronische Signatur (QES)

9.2 SigningMethod

WertBeschreibung
signing_method.digitalDigitale Signatur über Paperless (Online-Signatur)
signing_method.manualManuelle Signatur (Offline, z.B. auf Papier)

9.3 ContractParticipantRole

Jeder Vertrag benötigt mindestens 2 Teilnehmer mit unterschiedlichen Rollen.

WertBeschreibung
contract_participant_role.employerArbeitgeber
contract_participant_role.employeeArbeitnehmer
contract_participant_role.contract_creatorVertragsersteller (generisch)
contract_participant_role.contract_recipientVertragsempfänger (generisch)
contract_participant_role.landlordVermieter
contract_participant_role.tenantMieter

9.4 ContractStatus

WertBeschreibung
contract_status.draftEntwurf — noch nicht versendet
contract_status.sentVersendet — wartet auf Signaturen
contract_status.signedAlle Teilnehmer haben signiert
contract_status.expiredAbgelaufen — Signaturfrist überschritten
contract_status.cancelledStorniert

9.5 CompensationType

WertBeschreibung
compensation_type.hourlyStündlich
compensation_type.dailyTäglich
compensation_type.monthlyMonatlich
compensation_type.one_timeEinmalig
compensation_type.noneKeine Vergütung

9.6 EmploymentType

WertBeschreibung
employment_type.contractorFreiberuflich / Werkvertrag
employment_type.full_timeVollzeit
employment_type.part_timeTeilzeit
employment_type.temporaryBefristet
employment_type.part_time_miniMinijob
employment_type.studentWerkstudent
employment_type.trainingAusbildung

9.7 ScheduleType

WertBeschreibung
schedule_type.dailyTäglich (feste Zeiten)
schedule_type.weeklyWöchentlich
schedule_type.monthlyMonatlich
schedule_type.flexibleFlexibel

9.8 Gender

WertBeschreibung
gender.maleMännlich
gender.femaleWeiblich
gender.diverseDivers

9.9 ContractTemplateStatus

WertBeschreibung
contract_template_status.draftEntwurf
contract_template_status.activeAktiv — kann für Verträge verwendet werden
contract_template_status.archivedArchiviert — nicht mehr verwendbar

9.10 Country

Alle ISO-3166-1 Alpha-2-Codes werden unterstützt (z.B. country.us, country.gb, country.pl, ...).

WertBeschreibung
country.deDeutschland
country.atÖsterreich
country.chSchweiz
country.nlNiederlande
country.frFrankreich