# Formular → Eingang → Vorgang

Mit Formularen sammeln Sie Angaben über einen Link oder eine eingebettete Seite – etwa einen Antrag oder eine Kündigung. Jede abgesendete Antwort ist ein **Eingang** (`form_submission`). Aus einem Eingang wird auf Wunsch ein **Vorgang**, in dem die Person das Ergebnis unterschreibt.

Scopes: `forms:read` und `forms:write` für Formulare, `submissions:read` für Eingänge, `envelopes:write` für das Weiterleiten in einen Vorgang.

## 1. Formular anlegen und veröffentlichen

Die Felder eines Formulars bauen Sie am bequemsten im Dashboard im Formular-Editor. Per API geht es so:

```http
POST /v1/forms
Authorization: Bearer qgw_test_…
Idempotency-Key: 3f1c…
Content-Type: application/json

{ "name": "Antrag Anwohnerparkausweis", "slug": "anwohnerparkausweis", "externalId": "antrag-12" }
```

Ohne `schema` entsteht ein Entwurf mit einer leeren Seite; das vollständige Formular-Schema (Seiten, Eingaben, Bedingungen) beschreibt die API-Referenz bei `POST /v1/forms`. Änderungen gehen an die Entwurfsversion (`PATCH /v1/forms/{id}/versions/{versionId}`).

Veröffentlichen:

```http
POST /v1/forms/{id}/publish?dryRun=true
```

Mit `dryRun=true` sehen Sie die Prüfung (`form_publish_preview`), ohne etwas zu ändern. Im Live-Modus braucht ein Formular einen Link zu Datenschutz und Impressum (aus dem Formular, dem Markenprofil oder der Organisation). Ohne `dryRun` wird das Formular veröffentlicht (`PUBLISHED`), und das Ereignis `form.published` folgt.

Den Link und den Code zum Einbetten liefert `GET /v1/forms/{id}/embed`; vorbelegte Links erzeugt `POST /v1/forms/{id}/prefill-links` (Details im Guide „Formular einbetten und vorausfüllen“).

## 2. Eingänge empfangen

Abonnieren Sie die Ereignisse der Eingänge (Webhook-Abo mit `submission.*`, Scope `submissions:read`):

| Ereignis | Bedeutung |
| --- | --- |
| `submission.started` | Jemand hat begonnen, das Formular auszufüllen. |
| `submission.submitted` | Der Eingang wurde abgesendet. |
| `submission.completed` | Der Eingang ist fertig: PDF erzeugt, unterschrieben, wenn das Formular eine Unterschrift verlangt. |
| `submission.cancelled` | Die Unterschrift wurde abgelehnt, abgebrochen oder ist gescheitert. |
| `submission.expired` | Der Eingang ist verfallen. |

Die eingegebenen Werte stehen nicht im Ereignis. Lesen Sie den Eingang mit `GET /v1/submissions/{id}` (Feld `values`); jedes Lesen mit Werten steht im Aktivitätsprotokoll Ihrer Organisation. Listen gibt es mit `GET /v1/submissions` (alle Formulare) und `GET /v1/forms/{id}/submissions` (ein Formular, mit Filtern auf Auswahlfelder). Das Schema der Werte für Ihre Integration liefert `GET /v1/forms/{id}/schema` (`valuesJsonSchema`).

Dateien und Nachweise:

- `GET /v1/submissions/{id}/pdf` – das PDF des Eingangs,
- `GET /v1/submissions/{id}/files/{fileId}/content` – eine hochgeladene Datei,
- `GET /v1/submissions/{id}/evidence` – der Nachweis des Eingangs.

## 3. Aus dem Eingang einen Vorgang machen

Soll die Person das Ergebnis unterschreiben, gibt es zwei Wege:

1. **Automatisch:** Im Formular legen Sie eine Vorlage für die Unterschrift fest (`settings.signature`). Nach dem Absenden entsteht der Vorgang von selbst; `submission.completed` kommt, wenn unterschrieben ist.
2. **Per Aufruf:** Sie leiten einen abgesendeten Eingang selbst weiter – etwa erst nach einer Prüfung durch Ihr Team:

```http
POST /v1/submissions/{id}/envelope
Authorization: Bearer qgw_test_…
Idempotency-Key: 9a4d…
Content-Type: application/json

{
  "templateVersionId": "0192f1b0-0000-7000-8000-000000000105",
  "roles": [
    { "roleKey": "antragsteller", "source": "SUBMITTER", "emailFieldKey": "email", "nameFieldKeys": ["vorname", "nachname"] },
    { "roleKey": "sachbearbeitung", "source": "MEMBER", "memberId": "0192f1b0-0000-7000-8000-00000000010f" }
  ],
  "variables": { "kennzeichen": "kennzeichen" },
  "level": "SES"
}
```

- `templateVersionId` ist eine veröffentlichte Version einer Vorlage (Guide „Vorlage → Vorgang“).
- `roles` ordnet jede Rolle der Vorlage zu: der Person, die das Formular ausgefüllt hat (`SUBMITTER`, Name und E-Mail aus den Eingaben), einem Mitglied (`MEMBER`) oder einer festen Person (`FIXED`).
- `variables` füllt Platzhalter der Vorlage mit Eingaben des Formulars.
- Die ausfüllende Person unterschreibt mit `SES` oder `AES`; eine qualifizierte Signatur ist für sie nicht möglich (422 / 9027).
- Mit `?dryRun=true` sehen Sie Prüfung und Kosten, ohne dass etwas entsteht. Fehlt eine Zuordnung, antwortet die API mit 422 / 9035 und nennt Rollen und Platzhalter.

Der neue Vorgang ist ein ganz normaler Vorgang: Er schickt die Ereignisse `envelope.*` und `recipient.*`, und `envelopeId` steht danach im Eingang.
