Formkurier Auf die Warteliste
Auf die Warteliste

Formulare per API anlegen, als YAML oder JSON, auch durch deinen KI-Agenten

Was du im Editor baust, kann ein Agent über die API: anlegen, ändern, veröffentlichen, Antworten abholen. Die Antworten gehen signiert an dein Backend, n8n, Make oder Zapier.

So legt dein KI-Agent ein Formular an

Gib ihm die llms.txt und einen API-Schlüssel mit passenden Scopes. Format, Endpunkte und Fehlercodes liest er selbst, dann schreibt er das Formular als YAML, legt es an und veröffentlicht es.

Claude CodeBeispiel
du

Leg ein Rückruf-Formular an: Name, Telefon, vormittags oder nachmittags. Antworten an praxis-beispiel.de/anfragen.

agent

liest die llms.txt der API

  • POST/api/v1/forms/from-yaml201
  • POST/api/v1/forms/frm_8x2k/publish200

Fertig. Das Formular ist veröffentlicht.

Ein Formular ist eine Datei

Formkurier beschreibt jedes Formular im Format FormAST: Felder, Schritte, Bedingungen, Erfolgsseiten und Zustellziel. Dieselbe Datei geht als YAML oder JSON, legt das Formular an und ändert es später.

curl
curl -X POST \
  https://app.formkurier.com/api/v1/forms/from-yaml \
  -H "Authorization: Bearer $FORMKURIER_KEY" \
  -H "Idempotency-Key: rueckruf-v1" \
  --data-binary @rueckruf.yaml

curl -X POST \
  https://app.formkurier.com/api/v1/forms/FORM_ID/publish \
  -H "Authorization: Bearer $FORMKURIER_KEY"
rueckruf.yaml
version: "1"
meta:
  id: rueckruf
  name: "Rückruf"
  createdAt: "2026-10-30T09:00:00Z"
  updatedAt: "2026-10-30T09:00:00Z"
theme: clean
fields:
  - type: text
    id: f_name
    key: name
    label: "Name"
    required: true
  - type: tel
    id: f_telefon
    key: telefon
    label: "Telefon"
    required: true
  - type: radio
    id: f_zeit
    key: zeit
    label: "Wann passt es?"
    config:
      options:
        - "Vormittags"
        - "Nachmittags"
actions:
  captcha:
    enabled: true
  webhook:
    url: "https://praxis-beispiel.de/anfragen"
    method: POST
meta
Name und Kennung des Formulars.
fields
Die Felder: Typ, Schlüssel, Beschriftung, Pflicht. Auswahlfelder bekommen ihre Optionen unter config.options.
steps
Schritte für mehrseitige Formulare, je mit den Feldern, die dort stehen.
rules
Bedingungen: Felder zeigen, ausblenden, zur Pflicht machen oder einen Wert setzen.
actions
Spam-Schutz und, beim Durchreichen, das Zustellziel mit Methode.
Idempotency-Key
Schickt dein Agent dieselbe Anfrage zweimal, legt die API das Formular nur einmal an.

Endpunkte und Rechte

Jeder API-Schlüssel bekommt nur die Scopes, die er braucht. Fehler kommen in einem festen Format mit Code, Grund und Hinweis zur Behebung.

Formulare
Auflisten, anlegen (JSON oder YAML), ändern, archivieren, als YAML abrufen. forms:read, forms:write
Veröffentlichen
Entwurf veröffentlichen oder zurückziehen. forms:publish
Versionen
Stände sichern, ansehen und wiederherstellen.
Antworten
Im Modus Speichern auflisten, einzeln abrufen, Dateien laden. submissions:read, submissions:download
Webhooks
Standard-Zustellziel des Arbeitsbereichs lesen und setzen. webhooks:read, webhooks:write
Statistik
Aufrufe, Starts und Abbrüche je Formular, ohne personenbezogene Daten. analytics:read

So kommt eine Antwort bei dir an

Als POST mit JSON, die Schlüssel sind die Feld-IDs deines Formulars. Drei Header weisen die Zustellung aus: Sendungsnummer, Zeitstempel und die Signatur über Zeitstempel.Rohdaten.

Zustellung · Beispiel
POST /anfragen HTTP/1.1
Host: praxis-beispiel.de
Content-Type: application/json
X-Awk-Event-Id: evt_7QK2-4821-7730
X-Awk-Timestamp: 1793353327
X-Awk-Signature: sha256=9f2c…e41a

{
  "f_name": "Jana Beispiel",
  "f_telefon": "06331 000000",
  "f_zeit": "Vormittags"
}

Signatur prüfen, in Node.js

signatur.js
import crypto from 'node:crypto';

// rawBody: die unveränderten Bytes (Buffer),
// nicht das geparste JSON
export function istEcht(rawBody, headers, geheimnis) {
  const zeit = headers['x-awk-timestamp'];
  const sig = headers['x-awk-signature'] ?? '';
  const alter = Math.abs(Date.now() / 1000 - Number(zeit));
  if (!zeit || alter > 300) return false;

  const soll = crypto
    .createHmac('sha256', geheimnis)
    .update(`${zeit}.`)
    .update(rawBody)
    .digest('hex');
  const ist = sig.replace(/^sha256=/, '');
  if (ist.length !== soll.length) return false;
  return crypto.timingSafeEqual(
    Buffer.from(ist, 'hex'),
    Buffer.from(soll, 'hex'),
  );
}

Mit n8n, Make und Zapier

Jedes Werkzeug mit einem Webhook-Eingang nimmt Formkurier-Antworten an. Du brauchst keine eigene Integration.

n8n
Webhook-Node als Auslöser, Signatur in einem Code-Node prüfen, dann weiter ins CRM, in eine Tabelle oder per Mail.
Make
Szenario mit „Custom webhook“ starten und die Adresse als Zustellziel eintragen.
Zapier
Zap mit „Webhooks by Zapier“ und „Catch Hook“ beginnen.

Fragen zu API und Agenten

Brauche ich einen MCP-Server, damit mein Agent Formulare anlegt?

Nein. Agenten wie Claude Code oder Codex lesen die llms.txt und rufen die API direkt auf, mit einem API-Schlüssel aus deinem Arbeitsbereich.

Wie begrenze ich, was ein Agent darf?

Über die Scopes des Schlüssels. Ein Schlüssel nur mit forms:write und forms:publish kann Formulare anlegen und veröffentlichen, aber keine Antworten lesen.

Was passiert, wenn mein Agent dieselbe Anfrage zweimal schickt?

Mit demselben Idempotency-Key legt die API das Formular nur einmal an und liefert beim zweiten Mal die erste Antwort zurück.