{
  "openapi": "3.1.0",
  "info": {
    "title": "ratum Integrations-API",
    "description": "Öffentliche Integrations-API von ratum. Authentifizierung per `Authorization: Bearer ratum_live_…` bzw. `ratum_test_…`.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.ratum.ch"
    }
  ],
  "paths": {
    "/api/v1/documents": {
      "post": {
        "tags": [
          "documents"
        ],
        "summary": "Request Upload",
        "operationId": "request_upload_api_v1_documents_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUploadIn"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentUploadOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "documents"
        ],
        "summary": "List Documents",
        "operationId": "list_documents_api_v1_documents_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/DocumentMode"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Nur Dokumente dieses Modus. Ein API-Key sieht ausschliesslich Dokumente seines eigenen Modus (`ratum_live_` ⇒ `live`, `ratum_test_` ⇒ `test`); der Filter wirkt dort nicht. Browser-Sessions sehen beide Modi, wenn nicht gefiltert wird.",
              "title": "Mode"
            },
            "description": "Nur Dokumente dieses Modus. Ein API-Key sieht ausschliesslich Dokumente seines eigenen Modus (`ratum_live_` ⇒ `live`, `ratum_test_` ⇒ `test`); der Filter wirkt dort nicht. Browser-Sessions sehen beide Modi, wenn nicht gefiltert wird."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DocumentOut"
                  },
                  "title": "Response List Documents Api V1 Documents Get"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/create-and-send": {
      "post": {
        "tags": [
          "documents"
        ],
        "summary": "Create And Send",
        "description": "Dokument anlegen + Signer + Felder + Versand anfordern in einem Request (F13.4, TF-1037 ·\nADR-016 §3). Alles oder nichts: scheitert eine Validierung oder das Kontingent (402), bleibt\nnichts zurück. Danach PUT auf ``upload_url`` und ``/complete`` — versendet wird automatisch,\nsobald der Scan CLEAN (und ein DOCX konvertiert) ist. Per API-Key ist ``Idempotency-Key``\nPflicht (ADR-016 §7, TF-1036): ein Retry liefert die gespeicherte Antwort statt eines zweiten\nDokuments.",
        "operationId": "createAndSend",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung. **Pflicht** auf dieser Route.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung. **Pflicht** auf dieser Route."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAndSendIn"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateAndSendOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/complete": {
      "post": {
        "tags": [
          "documents"
        ],
        "summary": "Complete Upload",
        "operationId": "complete_upload_api_v1_documents__document_id__complete_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}": {
      "get": {
        "tags": [
          "documents"
        ],
        "summary": "Get Document",
        "description": "Einzelabruf mit Dokument-Status, ``failure_code`` und Signer-Status (F13.4, TF-1037 ·\nADR-016 §3, §6) — die Polling-Grundlage der Integrations-API.",
        "operationId": "get_document_api_v1_documents__document_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDetailOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "documents"
        ],
        "summary": "Delete Document",
        "operationId": "delete_document_api_v1_documents__document_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/download": {
      "get": {
        "tags": [
          "documents"
        ],
        "summary": "Download Document",
        "operationId": "download_document_api_v1_documents__document_id__download_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDownloadOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/download/sealed": {
      "get": {
        "tags": [
          "documents"
        ],
        "summary": "Download Sealed Document",
        "description": "Liefert das versiegelte PDF direkt in der Response (TF-880, owner-scoped) — R2-Fast-Path\noder Filebase-Decrypt-Fallback (s. ``_load_sealed_bytes``), anders als ``/download``\nbewusst **nicht** presigned: seit TF-880 existiert die R2-Klartext-Kopie eines archivierten\nDokuments i. d. R. nicht mehr. Kein zusätzliches Scan-Gate nötig — das versiegelte PDF ist\nein serverseitig aus einem bereits sauber gescannten Original erzeugtes Ergebnis-Artefakt,\nkein erneut hochgeladener Nutzer-Input.\n\n404, wenn das Dokument (noch) nicht lesbar ist; 500 statt 404, falls die Integritätsprüfung\ndes archivierten Filebase-Objekts fehlschlägt (KEK-Mismatch/Hash-Mismatch, TF-880 Critical\n#3) — s. ``_load_sealed_bytes``.",
        "operationId": "download_sealed_document_api_v1_documents__document_id__download_sealed_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              },
              "application/pdf": {}
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/audit": {
      "get": {
        "tags": [
          "documents"
        ],
        "summary": "Document Audit",
        "description": "Owner-scoped Audit-Trail eines Dokuments in chronologischer Reihenfolge (F7, TF-468).",
        "operationId": "document_audit_api_v1_documents__document_id__audit_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuditEntryOut"
                  },
                  "title": "Response Document Audit Api V1 Documents  Document Id  Audit Get"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/audit/report": {
      "get": {
        "tags": [
          "documents"
        ],
        "summary": "Document Audit Report",
        "description": "Downloadbarer PDF-Audit-Report (Chain of Custody, F7, TF-468, owner-scoped).\n\nAnders als ``/download``/``/verification`` (signierte S3-URL): vollständig im Speicher gerendert\nund direkt in der Response zurückgegeben — der Report wird bei jedem Aufruf frisch aus dem\naktuellen Audit-Trail gebaut (kein Objekt im Working-Store, das veralten könnte). Kein\n``require_clean_scan``-Gate nötig: der Report enthält nur Metadaten/Audit-Log, keine\nDokument-Bytes.",
        "operationId": "document_audit_report_api_v1_documents__document_id__audit_report_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              },
              "application/pdf": {}
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/send": {
      "post": {
        "tags": [
          "documents"
        ],
        "summary": "Send Document Endpoint",
        "description": "GUI (Session): sofortiger Versand, 409 solange Scan/Konvertierung laufen. API-Key: \"Senden,\nsobald bereit\" (F13.4, TF-1037 · ADR-016 §3) — synchrone Validierung, dann 202; versendet wird,\nsobald das Dokument bereit ist (``GET /documents/{id}`` zeigt den Stand). Per API-Key ist\n``Idempotency-Key`` Pflicht (ADR-016 §7, TF-1036). ``anchors`` (TF-1038) gibt es nur per\nAPI-Key: die Anker-Suche läuft im Worker, der sofortige GUI-Versand kann nicht darauf warten.",
        "operationId": "send_document_endpoint_api_v1_documents__document_id__send_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung. **Pflicht** auf dieser Route.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung. **Pflicht** auf dieser Route."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/SendDocumentIn"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Payload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "202": {
            "description": "Versand angefordert (API-Key)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentOut"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signature-fields": {
      "get": {
        "tags": [
          "signature-fields"
        ],
        "summary": "List Fields",
        "operationId": "list_fields_api_v1_documents__document_id__signature_fields_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SignatureFieldOut"
                  },
                  "title": "Response List Fields Api V1 Documents  Document Id  Signature Fields Get"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "signature-fields"
        ],
        "summary": "Create Field",
        "operationId": "create_field_api_v1_documents__document_id__signature_fields_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignatureFieldCreateIn"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureFieldOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signature-fields/{field_id}": {
      "patch": {
        "tags": [
          "signature-fields"
        ],
        "summary": "Update Field",
        "operationId": "update_field_api_v1_documents__document_id__signature_fields__field_id__patch",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Field Id"
            }
          },
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignatureFieldUpdateIn"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignatureFieldOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "signature-fields"
        ],
        "summary": "Delete Field",
        "operationId": "delete_field_api_v1_documents__document_id__signature_fields__field_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Field Id"
            }
          },
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signers": {
      "get": {
        "tags": [
          "signers"
        ],
        "summary": "List Signers",
        "operationId": "list_signers_api_v1_documents__document_id__signers_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SignerOut"
                  },
                  "title": "Response List Signers Api V1 Documents  Document Id  Signers Get"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "signers"
        ],
        "summary": "Create Signer",
        "operationId": "create_signer_api_v1_documents__document_id__signers_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignerCreateIn"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signers/order": {
      "put": {
        "tags": [
          "signers"
        ],
        "summary": "Reorder Signers",
        "operationId": "reorder_signers_api_v1_documents__document_id__signers_order_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignerReorderIn"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SignerOut"
                  },
                  "title": "Response Reorder Signers Api V1 Documents  Document Id  Signers Order Put"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signers/{signer_id}": {
      "patch": {
        "tags": [
          "signers"
        ],
        "summary": "Update Signer",
        "operationId": "update_signer_api_v1_documents__document_id__signers__signer_id__patch",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Signer Id"
            }
          },
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignerUpdateIn"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "signers"
        ],
        "summary": "Delete Signer",
        "operationId": "delete_signer_api_v1_documents__document_id__signers__signer_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Signer Id"
            }
          },
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signers/{signer_id}/resend": {
      "post": {
        "tags": [
          "signers"
        ],
        "summary": "Resend Signer Invitation",
        "description": "Manuelle Erinnerung an einen ausstehenden Signer (F8, TF-831) — Owner-only (via\n``get_owned_document``), unabhängig vom Draft-Gate der übrigen Endpunkte hier: ein\nversendetes Dokument ist per Definition nicht mehr im Draft-Status.\n\n``Retry-After`` wird auch bei **Erfolg** gesetzt (voller Cooldown, nicht nur bei 429) — die\nFE-Cooldown-Anzeige braucht dafür keinen eigenen, in ``SignerOut`` exponierten Zeitstempel.",
        "operationId": "resend_signer_invitation_api_v1_documents__document_id__signers__signer_id__resend_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Signer Id"
            }
          },
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/documents/{document_id}/signers/{signer_id}/link": {
      "post": {
        "tags": [
          "signers"
        ],
        "summary": "Get Signing Link",
        "description": "Signier-Link für den aktiven Signer bei ``delivery: none`` (F13.6, TF-1039 · ADR-016 §5).\n\nJeder Abruf liefert einen neuen Link und macht den zuvor ausgegebenen ungültig — auch bei\neinem Retry; nur den zuletzt erhaltenen Link zustellen. Die Signierfrist (``expires_at``)\nbleibt unverändert. 409, wenn das Dokument nicht ``delivery: none`` hat bzw. nicht versendet\nist, der Signer nicht der aktive ist oder seine Frist abgelaufen ist.",
        "operationId": "getSigningLink",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Signer Id"
            }
          },
          {
            "name": "document_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Document Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningLinkOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/current": {
      "get": {
        "tags": [
          "api-keys"
        ],
        "summary": "Read Current Key",
        "operationId": "read_current_key_api_v1_api_keys_current_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyPrincipalOut"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ]
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "List Endpoints",
        "operationId": "list_endpoints_api_v1_webhooks_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointListOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Create Endpoint",
        "operationId": "create_endpoint_api_v1_webhooks_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointCreateIn"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointSecretOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{endpoint_id}": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "Get Endpoint",
        "operationId": "get_endpoint_api_v1_webhooks__endpoint_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Endpoint Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "webhooks"
        ],
        "summary": "Update Endpoint",
        "operationId": "update_endpoint_api_v1_webhooks__endpoint_id__patch",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Endpoint Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointUpdateIn"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "webhooks"
        ],
        "summary": "Delete Endpoint",
        "description": "Löscht den Endpoint samt Zustell-Log; offene Retries entfallen.",
        "operationId": "delete_endpoint_api_v1_webhooks__endpoint_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Endpoint Id"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{endpoint_id}/rotate-secret": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Rotate Secret",
        "description": "Neues Secret, wirkt sofort: ab der nächsten Zustellung (auch Retries) wird nur noch damit\nsigniert.",
        "operationId": "rotate_secret_api_v1_webhooks__endpoint_id__rotate_secret_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Endpoint Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointSecretOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{endpoint_id}/test": {
      "post": {
        "tags": [
          "webhooks"
        ],
        "summary": "Send Test Event",
        "description": "\"Test-Event senden\": ein ``webhook.ping`` an diesen Endpoint, asynchron zugestellt — das\nErgebnis steht danach im Zustell-Log.",
        "operationId": "send_test_event_api_v1_webhooks__endpoint_id__test_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Endpoint Id"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung.",
              "title": "Idempotency-Key"
            },
            "description": "Frei wählbarer, eindeutiger Schlüssel (1–255 ASCII-Zeichen, z. B. eine UUID). Ein Retry mit demselben Schlüssel und Body liefert die gespeicherte Antwort (24 h, Header `Idempotent-Replayed: true`) statt einer zweiten Ausführung."
          }
        ],
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{endpoint_id}/deliveries": {
      "get": {
        "tags": [
          "webhooks"
        ],
        "summary": "List Deliveries",
        "description": "Zustell-Log des Endpoints, neueste zuerst (höchstens 100 Einträge, Aufbewahrung 30 Tage).",
        "operationId": "list_deliveries_api_v1_webhooks__endpoint_id__deliveries_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Endpoint Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryListOut"
                }
              }
            }
          },
          "4XX": {
            "description": "Client-Fehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "5XX": {
            "description": "Serverfehler. Bei API-Key-Requests als `application/problem+json`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "/document.sent": {
      "post": {
        "summary": "Event document.sent",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_document_sent",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/document.failed": {
      "post": {
        "summary": "Event document.failed",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_document_failed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/document.completed": {
      "post": {
        "summary": "Event document.completed",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_document_completed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/signer.activated": {
      "post": {
        "summary": "Event signer.activated",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_signer_activated",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/signer.signed": {
      "post": {
        "summary": "Event signer.signed",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_signer_signed",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/signer.declined": {
      "post": {
        "summary": "Event signer.declined",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_signer_declined",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/signer.expired": {
      "post": {
        "summary": "Event signer.expired",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_signer_expired",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    },
    "/webhook.ping": {
      "post": {
        "summary": "Event webhook.ping",
        "description": "Siehe Schema ``WebhookEvent``.",
        "operationId": "webhook_ping",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Zugestellt — jede 2xx-Antwort gilt als Erfolg."
          },
          "default": {
            "description": "5xx, 408, 429, Timeout, Verbindungs- oder DNS-Fehler: Retry mit Backoff über ~24 h. Andere Antworten (inkl. 3xx — Redirects werden nicht verfolgt): endgültig fehlgeschlagen."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AnchorFieldSizeIn": {
        "properties": {
          "width": {
            "type": "integer",
            "maximum": 1000.0,
            "exclusiveMinimum": 0.0,
            "title": "Width"
          },
          "height": {
            "type": "integer",
            "maximum": 1000.0,
            "exclusiveMinimum": 0.0,
            "title": "Height"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "width",
          "height"
        ],
        "title": "AnchorFieldSizeIn",
        "description": "Feldgrösse in PDF-Punkten für per Anker platzierte Felder (TF-1038)."
      },
      "AnchorOptionsIn": {
        "properties": {
          "sizes": {
            "additionalProperties": {
              "$ref": "#/components/schemas/AnchorFieldSizeIn"
            },
            "propertyNames": {
              "$ref": "#/components/schemas/SignatureFieldType"
            },
            "type": "object",
            "title": "Sizes"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "AnchorOptionsIn",
        "description": "Feldplatzierung per Anker-Platzhalter ``{{ratum:<feldtyp>:<signer-index>}}`` (F13.5,\nTF-1038 · ADR-016 §4). Ratum sucht die Platzhalter im (konvertierten) PDF und legt dort Felder\nfür den Signer mit dieser ``signing_order`` an; das Feld deckt den Platzhalter beim Stempeln ab.\nMit Koordinaten-Feldern kombinierbar. ``sizes`` überschreibt die Default-Grösse je Feldtyp\n(signature 180×50, initials 60×40, date 110×24, custom_text 160×24)."
      },
      "ApiKeyMode": {
        "type": "string",
        "enum": [
          "live",
          "test"
        ],
        "title": "ApiKeyMode",
        "description": "Modus eines persönlichen API-Keys (F13.1, TF-1034 · ADR-016 §1, §8).\n\nSteckt sichtbar im Key-Präfix (``ratum_live_…`` / ``ratum_test_…``) und wird am Request als\n``Principal.mode`` verfügbar gemacht. Ein Test-Key legt Dokumente mit :class:`DocumentMode`\n``TEST`` an (keine Mails, kein Kontingent, Wasserzeichen, Test-Zertifikat; TF-1041)."
      },
      "ApiKeyOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "prefix": {
            "type": "string",
            "title": "Prefix"
          },
          "mode": {
            "$ref": "#/components/schemas/ApiKeyMode"
          },
          "scopes": {
            "items": {
              "$ref": "#/components/schemas/ApiKeyScope"
            },
            "type": "array",
            "title": "Scopes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "revoked_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Revoked At"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "prefix",
          "mode",
          "scopes",
          "created_at",
          "last_used_at",
          "revoked_at",
          "expires_at"
        ],
        "title": "ApiKeyOut",
        "description": "Key-Metadaten fürs GUI — nie der Klartext und nie der Hash."
      },
      "ApiKeyPrincipalOut": {
        "properties": {
          "key": {
            "$ref": "#/components/schemas/ApiKeyOut"
          },
          "user_email": {
            "type": "string",
            "format": "email",
            "title": "User Email"
          }
        },
        "type": "object",
        "required": [
          "key",
          "user_email"
        ],
        "title": "ApiKeyPrincipalOut",
        "description": "``GET /api-keys/current``: wer bin ich mit diesem Key? (Credential-Check für SDKs/curl.)"
      },
      "ApiKeyScope": {
        "type": "string",
        "enum": [
          "documents:read",
          "documents:write",
          "documents:send",
          "signers:link",
          "webhooks:manage"
        ],
        "title": "ApiKeyScope",
        "description": "Berechtigungen eines API-Keys (F13.1, TF-1034 · ADR-016 §1).\n\nVollständige Liste aus ADR-016 §1; die Routen, die ``documents:send``, ``signers:link`` und\n``webhooks:manage`` verlangen, kommen mit TF-1037, TF-1039 und TF-1040. Die Scopes existieren\nschon jetzt, damit Keys von Anfang an passend eingeschränkt werden können. Gespeichert als\nJSON-Liste der Werte auf ``ApiKey.scopes``; geprüft per ``app.deps.require_scope``."
      },
      "AuditAction": {
        "type": "string",
        "enum": [
          "uploaded",
          "signed",
          "declined",
          "expired",
          "completed",
          "archived",
          "deleted",
          "invitation_failed",
          "signer_notification_failed",
          "all_signed_notification_failed",
          "telegram_signer_failed",
          "telegram_all_signed_failed",
          "reminder_sent",
          "signing_link_issued",
          "anchors_placed",
          "send_requested"
        ],
        "title": "AuditAction",
        "description": "Aktionen im Audit-Trail / der Chain of Custody (F7, F12).\n\n``SIGNED`` = ein einzelner Signer hat unterzeichnet; ``COMPLETED`` = alle Signer fertig\n(entspricht ``DocumentStatus.SIGNED`` auf Dokumentebene). ``DECLINED``/``EXPIRED`` spiegeln\ndie terminalen ``SignerStatus``-Zustände, damit jeder Workflow-Ausgang protokollierbar ist."
      },
      "AuditEntryOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "signer_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signer Id"
          },
          "action": {
            "$ref": "#/components/schemas/AuditAction"
          },
          "actor_email": {
            "type": "string",
            "title": "Actor Email"
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "user_agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Agent"
          },
          "signature_image": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signature Image"
          },
          "delivery_channel": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DeliveryChannel"
              },
              {
                "type": "null"
              }
            ],
            "description": "`integrator` bei Link-Abrufen und Signer-Aktionen unter `delivery: none` — ratum belegt dann die Postfach-Kontrolle des Signers nicht. Sonst `null` (E-Mail durch ratum bzw. kein Zustellbezug)."
          },
          "api_key_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Api Key Id",
            "description": "Per API-Key ausgelöste Aktion: ID des Keys, sonst `null` (Browser-Session, System)."
          },
          "api_key_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Api Key Label",
            "description": "«Name (Präfix)» des Keys; nach dessen Löschung nur das Präfix. Sonst `null`."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "signer_id",
          "action",
          "actor_email",
          "ip_address",
          "user_agent",
          "signature_image",
          "created_at"
        ],
        "title": "AuditEntryOut",
        "description": "Ein Audit-Trail-Eintrag für die Sender-Ansicht (F7). Enthält den forensischen Kontext\n(IP/Zeitpunkt) und — bei Signaturen — das erfasste Signaturbild."
      },
      "ConversionStatus": {
        "type": "string",
        "enum": [
          "pending",
          "done",
          "failed"
        ],
        "title": "ConversionStatus",
        "description": "DOCX→PDF-Konvertierungsstatus eines Dokuments (F2, TF-489).\n\n``None`` (Spalte NULL) = nicht anwendbar (PDF-Upload). Orthogonal zu ``DocumentStatus`` —\ndie Konvertierung ist kein Schritt im Signatur-Lebenszyklus."
      },
      "CreateAndSendFieldIn": {
        "properties": {
          "field_type": {
            "$ref": "#/components/schemas/SignatureFieldType"
          },
          "page": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Page"
          },
          "x": {
            "type": "integer",
            "minimum": 0.0,
            "title": "X"
          },
          "y": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Y"
          },
          "width": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Width"
          },
          "height": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Height"
          },
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "page_width": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Page Width"
          },
          "page_height": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Page Height"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "field_type",
          "page",
          "x",
          "y",
          "width",
          "height",
          "page_width",
          "page_height"
        ],
        "title": "CreateAndSendFieldIn",
        "description": "Signaturfeld im ``createAndSend``-Request (F13.4, TF-1037). Koordinaten und Bounds-Prüfung\nwie bei :class:`SignatureFieldCreateIn` (PDF-Punkte, Ursprung oben links; ``page_width``/\n``page_height`` nur zur Prüfung, nicht gespeichert)."
      },
      "CreateAndSendIn": {
        "properties": {
          "filename": {
            "type": "string",
            "maxLength": 512,
            "minLength": 1,
            "title": "Filename"
          },
          "content_type": {
            "type": "string",
            "title": "Content Type"
          },
          "size_bytes": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Size Bytes"
          },
          "signers": {
            "items": {
              "$ref": "#/components/schemas/CreateAndSendSignerIn"
            },
            "type": "array",
            "maxItems": 5,
            "minItems": 1,
            "title": "Signers"
          },
          "expiry_days": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 365.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Expiry Days"
          },
          "delivery": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DocumentDelivery"
              },
              {
                "type": "null"
              }
            ],
            "description": "Zustellung des Signier-Links (ADR-016 §5). `ratum` (Default): Einladung, Erinnerungen und Resend per E-Mail. `none`: keine Mails an Signer — den Link holt der Integrator über `POST /documents/{id}/signers/{sid}/link` und stellt ihn selbst zu. Ohne Angabe `ratum`; ein wiederholter Versand mit abweichendem Wert liefert 409."
          },
          "anchors": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AnchorOptionsIn"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "filename",
          "content_type",
          "size_bytes",
          "signers"
        ],
        "title": "CreateAndSendIn",
        "description": "``createAndSend`` (F13.4, TF-1037 · ADR-016 §3): Dokument anlegen, Signer + Felder setzen und\nden Versand anfordern — in einem Request. Die Bytes laufen weiterhin presigned (PUT auf die\nzurückgegebene URL, danach ``/complete``); versendet wird, sobald der Scan CLEAN und ein DOCX\nkonvertiert ist."
      },
      "CreateAndSendOut": {
        "properties": {
          "document_id": {
            "type": "string",
            "format": "uuid",
            "title": "Document Id"
          },
          "upload_url": {
            "type": "string",
            "title": "Upload Url"
          },
          "upload_headers": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Upload Headers"
          },
          "expires_in": {
            "type": "integer",
            "title": "Expires In"
          },
          "document": {
            "$ref": "#/components/schemas/DocumentDetailOut"
          }
        },
        "type": "object",
        "required": [
          "document_id",
          "upload_url",
          "upload_headers",
          "expires_in",
          "document"
        ],
        "title": "CreateAndSendOut",
        "description": "Upload-URL wie bei ``POST /documents`` plus der Dokument-Stand nach der Anforderung."
      },
      "CreateAndSendSignerIn": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "custom_message": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Message"
          },
          "fields": {
            "items": {
              "$ref": "#/components/schemas/CreateAndSendFieldIn"
            },
            "type": "array",
            "maxItems": 20,
            "title": "Fields"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "email"
        ],
        "title": "CreateAndSendSignerIn",
        "description": "Signer samt seinen Feldern; die Listenposition bestimmt die Signier-Reihenfolge. Ohne\n``anchors`` im Request braucht jeder Signer mindestens ein Feld."
      },
      "DeliveryChannel": {
        "type": "string",
        "enum": [
          "integrator"
        ],
        "title": "DeliveryChannel",
        "description": "Zustellkanal in ``AuditLogEntry.details[\"delivery_channel\"]`` (F13.6, TF-1039 · ADR-016 §5).\n\nGeschrieben nur bei ``delivery: none`` — ratum belegt dann die Postfach-Kontrolle des Signers\nnicht mehr (ADR-007). Bei ``ratum`` bleibt der Wert weg, damit sich Bestandseinträge nicht\nändern; ``null`` im Audit heisst also \"E-Mail durch ratum bzw. kein Zustellbezug\"."
      },
      "DocumentDelivery": {
        "type": "string",
        "enum": [
          "ratum",
          "none"
        ],
        "title": "DocumentDelivery",
        "description": "Wer stellt dem Signer den Signier-Link zu (F13.6, TF-1039 · ADR-016 §5)?\n\n``RATUM`` (Default): Einladung, Erinnerungen und Resend per E-Mail durch ratum. ``NONE``: ratum\nverschickt keine Signer-Mails, der Integrator holt den Link über\n``POST /documents/{id}/signers/{sid}/link`` und stellt ihn selbst zu. Owner-Benachrichtigungen\nlaufen in beiden Fällen weiter. Gesetzt beim Senden."
      },
      "DocumentDetailOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "filename": {
            "type": "string",
            "title": "Filename"
          },
          "status": {
            "$ref": "#/components/schemas/DocumentStatus"
          },
          "mime_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mime Type"
          },
          "file_size_bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "File Size Bytes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "archived_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Archived At"
          },
          "conversion_status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConversionStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "conversion_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Conversion Error"
          },
          "scan_status": {
            "$ref": "#/components/schemas/ScanStatus"
          },
          "scan_signature": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scan Signature"
          },
          "send_requested": {
            "type": "boolean",
            "title": "Send Requested",
            "description": "Versand angefordert, wartet auf Scan/Konvertierung. Nur bei status=draft."
          },
          "failure_code": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DocumentFailureCode"
              },
              {
                "type": "null"
              }
            ],
            "description": "Gesetzt genau dann, wenn status=failed."
          },
          "source": {
            "$ref": "#/components/schemas/DocumentSource"
          },
          "mode": {
            "$ref": "#/components/schemas/DocumentMode",
            "description": "`test` für Dokumente, die mit einem `ratum_test_`-Key angelegt wurden (keine Mails, kein Kontingent, Wasserzeichen «TEST»), sonst `live`."
          },
          "delivery": {
            "$ref": "#/components/schemas/DocumentDelivery",
            "description": "Zustellung des Signier-Links: `ratum` (E-Mail) oder `none` (Integrator, Link über `POST /documents/{id}/signers/{sid}/link`)."
          },
          "expiry_days": {
            "type": "integer",
            "title": "Expiry Days"
          },
          "signers": {
            "items": {
              "$ref": "#/components/schemas/SignerOut"
            },
            "type": "array",
            "title": "Signers"
          }
        },
        "type": "object",
        "required": [
          "id",
          "filename",
          "status",
          "mime_type",
          "file_size_bytes",
          "created_at",
          "archived_at",
          "conversion_status",
          "conversion_error",
          "scan_status",
          "scan_signature",
          "send_requested",
          "failure_code",
          "source",
          "mode",
          "delivery",
          "expiry_days",
          "signers"
        ],
        "title": "DocumentDetailOut",
        "description": "Einzelabruf ``GET /documents/{id}`` (F13.4, TF-1037 · ADR-016 §3, §6): Dokument-Status,\nFehlercode und Signer-Status in Signier-Reihenfolge — Grundlage fürs Polling."
      },
      "DocumentDownloadOut": {
        "properties": {
          "download_url": {
            "type": "string",
            "title": "Download Url"
          },
          "expires_in": {
            "type": "integer",
            "title": "Expires In"
          }
        },
        "type": "object",
        "required": [
          "download_url",
          "expires_in"
        ],
        "title": "DocumentDownloadOut",
        "description": "Signierte GET-URL zum direkten Download durch den Client."
      },
      "DocumentFailureCode": {
        "type": "string",
        "enum": [
          "scan_infected",
          "scan_failed",
          "conversion_failed",
          "anchor_not_found",
          "anchor_scan_failed",
          "sealing_unavailable"
        ],
        "title": "DocumentFailureCode",
        "description": "Warum ein Dokument im Status ``failed`` gelandet ist (F13.4, TF-1037 · ADR-016 §3, §7).\n\nStabile Werte — sie sind Teil des öffentlichen API-Vertrags (``GET /documents/{id}``, später\nWebhook ``document.failed``). ``anchor_not_found``/``anchor_scan_failed`` setzt die Anker-Platzierung (TF-1038)."
      },
      "DocumentMode": {
        "type": "string",
        "enum": [
          "live",
          "test"
        ],
        "title": "DocumentMode",
        "description": "Modus eines Dokuments (F13.8, TF-1041 · ADR-016 §8).\n\n``TEST`` bekommt nur, was mit einem ``ratum_test_``-Key angelegt wurde: keine Mails, kein\nKontingent, Wasserzeichen «TEST» und Test-Zertifikat beim Versiegeln, kein IPFS-Archiv,\nLöschung nach ``settings.test_document_ttl_days``. Alles andere (Browser-Session, Live-Key) ist\n``LIVE``. Werte stimmen bewusst mit :class:`ApiKeyMode` überein."
      },
      "DocumentOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "filename": {
            "type": "string",
            "title": "Filename"
          },
          "status": {
            "$ref": "#/components/schemas/DocumentStatus"
          },
          "mime_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mime Type"
          },
          "file_size_bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "File Size Bytes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "archived_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Archived At"
          },
          "conversion_status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConversionStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "conversion_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Conversion Error"
          },
          "scan_status": {
            "$ref": "#/components/schemas/ScanStatus"
          },
          "scan_signature": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scan Signature"
          },
          "send_requested": {
            "type": "boolean",
            "title": "Send Requested",
            "description": "Versand angefordert, wartet auf Scan/Konvertierung. Nur bei status=draft."
          },
          "failure_code": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DocumentFailureCode"
              },
              {
                "type": "null"
              }
            ],
            "description": "Gesetzt genau dann, wenn status=failed."
          },
          "source": {
            "$ref": "#/components/schemas/DocumentSource"
          },
          "mode": {
            "$ref": "#/components/schemas/DocumentMode",
            "description": "`test` für Dokumente, die mit einem `ratum_test_`-Key angelegt wurden (keine Mails, kein Kontingent, Wasserzeichen «TEST»), sonst `live`."
          },
          "delivery": {
            "$ref": "#/components/schemas/DocumentDelivery",
            "description": "Zustellung des Signier-Links: `ratum` (E-Mail) oder `none` (Integrator, Link über `POST /documents/{id}/signers/{sid}/link`)."
          }
        },
        "type": "object",
        "required": [
          "id",
          "filename",
          "status",
          "mime_type",
          "file_size_bytes",
          "created_at",
          "archived_at",
          "conversion_status",
          "conversion_error",
          "scan_status",
          "scan_signature",
          "send_requested",
          "failure_code",
          "source",
          "mode",
          "delivery"
        ],
        "title": "DocumentOut",
        "description": "Dokument-Metadaten für Listing/Detail (ohne Krypto-/IPFS-Felder)."
      },
      "DocumentSource": {
        "type": "string",
        "enum": [
          "gui",
          "api"
        ],
        "title": "DocumentSource",
        "description": "Über welchen Weg ein Dokument angelegt wurde (F13.4, TF-1037 · ADR-016 §3).\n\nSteuert die Entwurfs-TTL (API-Entwürfe 7 Tage statt 24 h) und das Badge \"via API\" im GUI."
      },
      "DocumentStatus": {
        "type": "string",
        "enum": [
          "draft",
          "pending",
          "signed",
          "archived",
          "declined",
          "failed"
        ],
        "title": "DocumentStatus",
        "description": "Lebenszyklus eines Dokuments (F4-Workflow)."
      },
      "DocumentUploadIn": {
        "properties": {
          "filename": {
            "type": "string",
            "maxLength": 512,
            "minLength": 1,
            "title": "Filename"
          },
          "content_type": {
            "type": "string",
            "title": "Content Type"
          },
          "size_bytes": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Size Bytes"
          }
        },
        "type": "object",
        "required": [
          "filename",
          "content_type",
          "size_bytes"
        ],
        "title": "DocumentUploadIn",
        "description": "Anforderung einer signierten Upload-URL — deklarierte Metadaten der Datei.\n\nTyp-/Endungs-Invarianten leben hier (422 bei Verstoss); die konfigurierbaren Limits\n(max. 25 MB, max. 500 Dokumente) erzwingt der Router gegen die Settings."
      },
      "DocumentUploadOut": {
        "properties": {
          "document_id": {
            "type": "string",
            "format": "uuid",
            "title": "Document Id"
          },
          "upload_url": {
            "type": "string",
            "title": "Upload Url"
          },
          "upload_headers": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Upload Headers"
          },
          "expires_in": {
            "type": "integer",
            "title": "Expires In"
          }
        },
        "type": "object",
        "required": [
          "document_id",
          "upload_url",
          "upload_headers",
          "expires_in"
        ],
        "title": "DocumentUploadOut",
        "description": "Antwort mit signierter Upload-URL + DB-Referenz. Der Client lädt direkt zu S3 hoch."
      },
      "ScanStatus": {
        "type": "string",
        "enum": [
          "pending",
          "clean",
          "infected",
          "error"
        ],
        "title": "ScanStatus",
        "description": "Malware-Scan-Status eines Uploads (F2, TF-490).\n\nGilt für **jeden** Upload (anders als ``ConversionStatus``, das nur DOCX betrifft) und ist der\nGate vor Konvertierung/Freigabe: nur ``CLEAN`` wird weiterverarbeitet. ``INFECTED`` ist ein\nQuarantäne-Tombstone (Bytes gelöscht, Zeile bleibt für Feedback + Nachweis), ``ERROR`` ist\nfail-closed (Scanner unerreichbar / permanent gescheitert) und blockiert ebenso — kein\nstiller Durchlauf. Orthogonal zu ``DocumentStatus`` und ``ConversionStatus``."
      },
      "SendDocumentIn": {
        "properties": {
          "expiry_days": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 365.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Expiry Days"
          },
          "delivery": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DocumentDelivery"
              },
              {
                "type": "null"
              }
            ],
            "description": "Zustellung des Signier-Links (ADR-016 §5). `ratum` (Default): Einladung, Erinnerungen und Resend per E-Mail. `none`: keine Mails an Signer — den Link holt der Integrator über `POST /documents/{id}/signers/{sid}/link` und stellt ihn selbst zu. Ohne Angabe `ratum`; ein wiederholter Versand mit abweichendem Wert liefert 409."
          },
          "anchors": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AnchorOptionsIn"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "title": "SendDocumentIn",
        "description": "Optionale Versandoptionen: ``expiry_days`` (1–365; ohne Wert bleibt der Dokument-Default von\n30 Tagen auf ``Document.expiry_days``), ``delivery`` (ohne Wert ``ratum``) und ``anchors`` (nur\nper API-Key: Felder per Anker-Platzhalter, TF-1038)."
      },
      "SignatureFieldCreateIn": {
        "properties": {
          "field_type": {
            "$ref": "#/components/schemas/SignatureFieldType"
          },
          "page": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Page"
          },
          "x": {
            "type": "integer",
            "minimum": 0.0,
            "title": "X"
          },
          "y": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Y"
          },
          "width": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Width"
          },
          "height": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Height"
          },
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "signer_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signer Id"
          },
          "page_width": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Page Width"
          },
          "page_height": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Page Height"
          }
        },
        "type": "object",
        "required": [
          "field_type",
          "page",
          "x",
          "y",
          "width",
          "height",
          "page_width",
          "page_height"
        ],
        "title": "SignatureFieldCreateIn",
        "description": "Neues Signaturfeld. Koordinaten sind PDF-Punkte (Ursprung oben-links). ``page_width``/\n``page_height`` dienen nur der Bounds-Prüfung und werden nicht gespeichert."
      },
      "SignatureFieldOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "document_id": {
            "type": "string",
            "format": "uuid",
            "title": "Document Id"
          },
          "field_type": {
            "$ref": "#/components/schemas/SignatureFieldType"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "x": {
            "type": "integer",
            "title": "X"
          },
          "y": {
            "type": "integer",
            "title": "Y"
          },
          "width": {
            "type": "integer",
            "title": "Width"
          },
          "height": {
            "type": "integer",
            "title": "Height"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "signer_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signer Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "document_id",
          "field_type",
          "page",
          "x",
          "y",
          "width",
          "height",
          "label",
          "signer_id",
          "created_at",
          "updated_at"
        ],
        "title": "SignatureFieldOut",
        "description": "Signaturfeld für Listing/Detail. Koordinaten sind PDF-Punkte."
      },
      "SignatureFieldType": {
        "type": "string",
        "enum": [
          "signature",
          "initials",
          "date",
          "custom_text"
        ],
        "title": "SignatureFieldType",
        "description": "Feldtypen der Drag-&-Drop-Platzierung (F3)."
      },
      "SignatureFieldUpdateIn": {
        "properties": {
          "x": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "X"
          },
          "y": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Y"
          },
          "width": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Width"
          },
          "height": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Height"
          },
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "signer_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signer Id"
          },
          "page_width": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Page Width"
          },
          "page_height": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Page Height"
          }
        },
        "type": "object",
        "title": "SignatureFieldUpdateIn",
        "description": "Teil-Update eines Feldes. Geometrie-Änderungen brauchen x, y, width, height UND\npage_width/page_height zusammen; ein reines Label-Update braucht keine Seitenmaße."
      },
      "SignerCreateIn": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "custom_message": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Message"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "SignerCreateIn",
        "description": "Neuer Signer. `signing_order` wird serverseitig ans Ende angehängt (nicht im Request)."
      },
      "SignerOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "document_id": {
            "type": "string",
            "format": "uuid",
            "title": "Document Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "signing_order": {
            "type": "integer",
            "title": "Signing Order"
          },
          "status": {
            "$ref": "#/components/schemas/SignerStatus"
          },
          "custom_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Message"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At"
          },
          "signed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "document_id",
          "email",
          "name",
          "signing_order",
          "status",
          "custom_message",
          "expires_at",
          "signed_at",
          "created_at",
          "updated_at"
        ],
        "title": "SignerOut",
        "description": "Signer für Listing/Detail. Kein `signer_token`/`ip_address`/`user_agent` im Response —\ninterne bzw. forensische Felder, kein Leak an den Sender-Client nötig."
      },
      "SignerReorderIn": {
        "properties": {
          "signer_ids": {
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "type": "array",
            "title": "Signer Ids"
          }
        },
        "type": "object",
        "required": [
          "signer_ids"
        ],
        "title": "SignerReorderIn",
        "description": "Neue Reihenfolge als komplette, geordnete ID-Liste (muss exakt die vorhandene Menge\nenthalten — Router validiert das gegen die DB, siehe `signers.py`)."
      },
      "SignerStatus": {
        "type": "string",
        "enum": [
          "pending",
          "signed",
          "expired",
          "declined"
        ],
        "title": "SignerStatus",
        "description": "Status eines einzelnen Signers im sequentiellen Workflow (F4)."
      },
      "SignerUpdateIn": {
        "properties": {
          "email": {
            "anyOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "custom_message": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Message"
          }
        },
        "type": "object",
        "title": "SignerUpdateIn",
        "description": "Teil-Update eines Signers. `signing_order` läuft ausschliesslich über `SignerReorderIn`."
      },
      "SigningLinkOut": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Login-freier Signier-Link (Bearer-Credential). Nur an den Signer zustellen; nicht loggen, nicht cachen, nicht an Dritte weitergeben."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At",
            "description": "Ablauf der Signierfrist. Ein Link-Abruf verlängert sie nicht."
          }
        },
        "type": "object",
        "required": [
          "url",
          "expires_at"
        ],
        "title": "SigningLinkOut",
        "description": "Signier-Link für den aktiven Signer bei ``delivery: none`` (F13.6, TF-1039 · ADR-016 §5).\nJeder Abruf macht den zuvor ausgegebenen Link ungültig; die Frist bleibt unverändert."
      },
      "WebhookDeliveryListOut": {
        "properties": {
          "deliveries": {
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryOut"
            },
            "type": "array",
            "title": "Deliveries"
          }
        },
        "type": "object",
        "required": [
          "deliveries"
        ],
        "title": "WebhookDeliveryListOut"
      },
      "WebhookDeliveryOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "event_id": {
            "type": "string",
            "title": "Event Id"
          },
          "event_type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "status": {
            "$ref": "#/components/schemas/WebhookDeliveryStatus"
          },
          "attempts": {
            "type": "integer",
            "title": "Attempts"
          },
          "last_response_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Response Code"
          },
          "last_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Error"
          },
          "next_attempt_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Attempt At"
          },
          "last_attempt_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Attempt At"
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Delivered At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "payload": {
            "additionalProperties": true,
            "type": "object",
            "title": "Payload"
          }
        },
        "type": "object",
        "required": [
          "id",
          "event_id",
          "event_type",
          "status",
          "attempts",
          "last_response_code",
          "last_error",
          "next_attempt_at",
          "last_attempt_at",
          "delivered_at",
          "created_at",
          "payload"
        ],
        "title": "WebhookDeliveryOut",
        "description": "Eintrag im Zustell-Log (30 Tage). ``payload`` ist der exakt zugestellte (signierte) Body."
      },
      "WebhookDeliveryStatus": {
        "type": "string",
        "enum": [
          "pending",
          "succeeded",
          "failed"
        ],
        "title": "WebhookDeliveryStatus",
        "description": "Zustand einer Webhook-Zustellung (TF-1040). ``pending`` umfasst \"noch nicht versucht\" und\n\"wartet auf Retry\" (``next_attempt_at``); ``failed`` ist endgültig (Retries erschöpft, nicht\nretrybare Antwort, SSRF-Sperre, interner Fehler oder deaktivierter Endpoint). Nur ``pending``\nhat ein ``next_attempt_at`` (CHECK-Constraint)."
      },
      "WebhookEndpointCreateIn": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048,
            "minLength": 1,
            "title": "Url"
          },
          "events": {
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "type": "array",
            "minItems": 1,
            "title": "Events"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "WebhookEndpointCreateIn",
        "description": "Neuer Webhook-Endpoint (F13.7, TF-1040 · ADR-016 §6). Ohne ``events`` werden alle Events\nabonniert. Die URL muss ``https://`` sein und öffentlich auflösen (SSRF-Schutz)."
      },
      "WebhookEndpointListOut": {
        "properties": {
          "endpoints": {
            "items": {
              "$ref": "#/components/schemas/WebhookEndpointOut"
            },
            "type": "array",
            "title": "Endpoints"
          }
        },
        "type": "object",
        "required": [
          "endpoints"
        ],
        "title": "WebhookEndpointListOut"
      },
      "WebhookEndpointOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "events": {
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "type": "array",
            "title": "Events"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "disabled_reason": {
            "anyOf": [
              {
                "type": "string",
                "const": "too_many_failures"
              },
              {
                "type": "null"
              }
            ],
            "title": "Disabled Reason"
          },
          "consecutive_failures": {
            "type": "integer",
            "title": "Consecutive Failures"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "events",
          "enabled",
          "disabled_reason",
          "consecutive_failures",
          "created_at"
        ],
        "title": "WebhookEndpointOut",
        "description": "Endpoint-Metadaten — nie das Secret. ``disabled_reason = too_many_failures``: von ratum nach\nDauerfehlern abgeschaltet."
      },
      "WebhookEndpointSecretOut": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "events": {
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "type": "array",
            "title": "Events"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "disabled_reason": {
            "anyOf": [
              {
                "type": "string",
                "const": "too_many_failures"
              },
              {
                "type": "null"
              }
            ],
            "title": "Disabled Reason"
          },
          "consecutive_failures": {
            "type": "integer",
            "title": "Consecutive Failures"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "secret": {
            "type": "string",
            "title": "Secret"
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "events",
          "enabled",
          "disabled_reason",
          "consecutive_failures",
          "created_at",
          "secret"
        ],
        "title": "WebhookEndpointSecretOut",
        "description": "Antwort auf Erzeugung und Secret-Rotation: einzige Stellen, an denen ``secret`` ausgeliefert\nwird. Damit prüft der Empfänger den ``Ratum-Signature``-Header."
      },
      "WebhookEndpointUpdateIn": {
        "properties": {
          "url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "events": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/WebhookEventType"
                },
                "type": "array",
                "minItems": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Events"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          }
        },
        "type": "object",
        "title": "WebhookEndpointUpdateIn",
        "description": "Teil-Update. ``enabled=true`` reaktiviert einen (auch automatisch) deaktivierten Endpoint\nund setzt den Fehlerzähler zurück."
      },
      "WebhookEvent": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "examples": [
              "evt_3f2a…"
            ]
          },
          "type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "livemode": {
            "type": "boolean",
            "title": "Livemode"
          },
          "data": {
            "$ref": "#/components/schemas/WebhookEventData"
          }
        },
        "type": "object",
        "required": [
          "id",
          "type",
          "created_at",
          "livemode",
          "data"
        ],
        "title": "WebhookEvent",
        "description": "Body jeder Webhook-Zustellung. Signiert per ``Ratum-Signature: t=<unix>,v1=<hex>``\n(HMAC-SHA256 über ``\"<t>.<body>\"`` mit dem Endpoint-Secret); Zeitstempel ausserhalb ±5 min\nablehnen. ``id`` ist pro Event eindeutig und bei Retries gleich — zum Deduplizieren."
      },
      "WebhookEventData": {
        "properties": {
          "document_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Document Id"
          },
          "signer_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Signer Id"
          },
          "status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DocumentStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "failure_code": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DocumentFailureCode"
              },
              {
                "type": "null"
              }
            ]
          },
          "endpoint_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Endpoint Id"
          }
        },
        "type": "object",
        "title": "WebhookEventData",
        "description": "``data`` eines Webhook-Events — \"thin\" (ADR-016 §6): nur IDs und Status, keine PII, keine\nSignier-Links. ``status`` ist der Dokument-Status zum Zeitpunkt des Events; ``signer_id`` nur\nbei ``signer.*``, ``failure_code`` nur bei ``document.failed``. ``webhook.ping`` trägt nur\n``endpoint_id`` (kein ``document_id``/``status``)."
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "document.sent",
          "document.failed",
          "document.completed",
          "signer.activated",
          "signer.signed",
          "signer.declined",
          "signer.expired",
          "webhook.ping"
        ],
        "title": "WebhookEventType",
        "description": "Webhook-Events der Integrations-API (F13.7, TF-1040 · ADR-016 §6).\n\nÖffentlicher Vertrag wie die Routen (ADR-016 §7): innerhalb von v1 nur additive Änderungen —\nein entfernter Wert würde gespeicherte Abos/Zustell-Log-Einträge beim Lesen ungültig machen.\nAuslöser stehen bei ``app.services.webhooks.emit_event``-Aufrufern; ``signer.activated`` feuert\nnur bei der **ersten** Aktivierung eines Signers (nicht bei Reminder/Link-Re-Mint)."
      },
      "ProblemDetails": {
        "additionalProperties": true,
        "description": "RFC-9457-Fehlerobjekt der Integrations-API (Content-Type ``application/problem+json``).",
        "properties": {
          "type": {
            "default": "about:blank",
            "description": "Immer `about:blank`. Die Fehlerart steht maschinenlesbar in `code`.",
            "title": "Type",
            "type": "string"
          },
          "title": {
            "description": "HTTP-Statustext, z. B. `Conflict`.",
            "title": "Title",
            "type": "string"
          },
          "status": {
            "description": "HTTP-Statuscode, identisch mit dem der Antwort.",
            "title": "Status",
            "type": "integer"
          },
          "detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Menschenlesbare Erklärung (Deutsch).",
            "title": "Detail"
          },
          "instance": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Pfad der fehlgeschlagenen Anfrage.",
            "title": "Instance"
          },
          "code": {
            "$ref": "#/components/schemas/ProblemCode",
            "description": "Stabiler Fehlercode, auf den Clients verzweigen.\n\n- `bad_request`: 400 — Anfrage fehlerhaft, ohne spezifischeren Code.\n- `validation_error`: 422 — Body, Pfad oder Query verletzt das Schema (Details in `errors`).\n- `unauthenticated`: 401 — API-Key fehlt, ist unbekannt, abgelaufen oder widerrufen.\n- `plan_required`: 403 — API-Zugang nur mit bezahltem Tarif; Keys sind suspendiert, nicht gelöscht.\n- `insufficient_scope`: 403 — dem API-Key fehlt der für die Route nötige Scope.\n- `forbidden`: 403 — Zugriff verweigert, ohne spezifischeren Code.\n- `not_found`: 404 — Ressource existiert nicht oder gehört einem anderen Konto.\n- `method_not_allowed`: 405 — HTTP-Methode auf dieser Route nicht erlaubt.\n- `conflict`: 409 — Zustand der Ressource lässt die Aktion nicht zu (z. B. kein Entwurf mehr).\n- `not_ready`: 409 — Dokument wird noch geprüft (Malware-Scan) bzw. konvertiert.\n- `scan_infected`: 409 bzw. `failure_code` am Dokument — Dokument wurde als schädlich erkannt und entfernt.\n- `scan_failed`: 409 bzw. `failure_code` am Dokument — Malware-Scan endgültig fehlgeschlagen; Datei als neues Dokument hochladen.\n- `conversion_failed`: 409 bzw. `failure_code` am Dokument — DOCX-Konvertierung nach PDF fehlgeschlagen.\n- `anchor_not_found`: 422 bzw. `failure_code` am Dokument — Anker-Platzhalter ohne passenden Signer, Signer ohne Platzhalter, zu viele (> 20 je Signer) oder zu grosse Platzhalter.\n- `anchor_scan_failed`: 422 bzw. `failure_code` am Dokument — PDF für die Anker-Suche abgelehnt (Seitenlimit, Zeit- oder Speicherlimit, zu viele Platzhalter, Platzhalter auf gedrehter Seite, unlesbar, wiederholt abgebrochen, Datei fehlt).\n- `quota_exceeded`: 402 — Dokument-Kontingent des Kontos ist ausgeschöpft.\n- `payload_too_large`: 413 — Datei oder Anfrage überschreitet die Grössengrenze.\n- `rate_limited`: 429 — Rate-Limit erreicht; `Retry-After` nennt die Wartezeit in Sekunden.\n- `idempotency_key_required`: 400 — die Route verlangt einen `Idempotency-Key`-Header.\n- `idempotency_key_invalid`: 400 — `Idempotency-Key` ist leer, zu lang (> 255) oder enthält Nicht-ASCII-Zeichen.\n- `idempotency_key_reused`: 422 — derselbe `Idempotency-Key` wurde mit einer anderen Anfrage (Route oder Body) verwendet.\n- `idempotency_key_in_use`: 409 — eine Anfrage mit diesem `Idempotency-Key` läuft noch; später erneut versuchen.\n- `webhook_url_rejected`: 422 — Webhook-URL unzulässig: nur `https://`, Host muss öffentlich auflösen (keine privaten, internen oder Link-Local-Adressen).\n- `test_mode_unavailable`: 503 — der Test-Modus ist auf dieser Umgebung nicht eingerichtet (Test-Zertifikat fehlt oder ist ungültig); später erneut versuchen.\n- `internal_error`: 500 — unerwarteter Serverfehler."
          },
          "errors": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Nur bei `validation_error`: die einzelnen Schemaverletzungen.",
            "title": "Errors"
          }
        },
        "required": [
          "title",
          "status",
          "code"
        ],
        "title": "ProblemDetails",
        "type": "object"
      },
      "ProblemCode": {
        "description": "Stabiler Fehlercode-Katalog der Integrations-API (ADR-016 §7).\n\n``scan_infected``/``scan_failed``/``conversion_failed``/``anchor_not_found``/\n``anchor_scan_failed`` erscheinen sowohl als Problem-Code (synchron) als auch als\n``failure_code`` am Dokument (TF-1037/TF-1038).",
        "enum": [
          "bad_request",
          "validation_error",
          "unauthenticated",
          "plan_required",
          "insufficient_scope",
          "forbidden",
          "not_found",
          "method_not_allowed",
          "conflict",
          "not_ready",
          "scan_infected",
          "scan_failed",
          "conversion_failed",
          "anchor_not_found",
          "anchor_scan_failed",
          "quota_exceeded",
          "payload_too_large",
          "rate_limited",
          "idempotency_key_required",
          "idempotency_key_invalid",
          "idempotency_key_reused",
          "idempotency_key_in_use",
          "webhook_url_rejected",
          "test_mode_unavailable",
          "internal_error"
        ],
        "title": "ProblemCode",
        "type": "string"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
