Submit-Endpunkt.
Ein POST pro Einsendung, und es ist der einzige Endpunkt, den deine Besucher je berühren. Er nimmt urlencoded, multipart und JSON entgegen, speichert alles, was du sendest, mailt es an die Empfänger des Formulars und übergibt den Rest der Queue — Webhooks, Integrationen, Autoresponder.
Die zwei Routen
Im Verhalten identisch — nimm, was besser passt. Mit dem Key im Pfad bleibt das Formular-Markup schlank; mit dem Key im Body kann ein einziger Endpunkt mehrere Formulare bedienen.
Body-Formate
Alle drei werden akzeptiert. Nimm multipart nur, wenn Dateien dabei sind — es ist größer, und ohne Upload bringt es nichts.
| Content-Type | Wann |
|---|---|
application/json |
Programme, fetch, Server-zu-Server. |
application/x-www-form-urlencoded |
Klassischer HTML-Formular-Post und AJAX ohne Dateien. |
multipart/form-data |
Sobald eine Datei mitgeschickt wird. |
Was zurückkommt, hängt vom Accept-Header ab. Eine Anfrage, die text/html verlangt — ein Browser, der ein Formular abschickt —, wird mit einem 303 zur Danke-Seite oder zu deinem Weiterleitungsziel beantwortet. Alles andere bekommt JSON. Mit Accept: application/json oder dem Header X-Requested-With erzwingst du immer JSON.
Deine eigenen Felder
Jedes Feld, das nicht auf der reservierten Liste steht, wird so gespeichert, wie du es sendest, und erscheint in der Benachrichtigungsmail, im Dashboard und in der Lese-API. Es gibt kein Schema, das du vorher anmelden musst — benenne deine Felder, wie du willst.
Eine Konvention lohnt sich: Ein Feld namens email wird als Antwortadresse der Benachrichtigungsmail und als Empfänger des Autoresponders verwendet.
Reservierte Feldnamen
Diese Namen steuern die Verarbeitung, statt gespeichert zu werden. Sie tauchen weder in den gespeicherten Daten noch im Mailtext noch in der Lese-API auf.
| Feld | Wirkung |
|---|---|
access_key / accessKey |
Der Access-Key des Formulars, wenn er nicht in der URL steht. |
subject |
Betreff der Benachrichtigungsmail. Einzeilig, max. 200 Zeichen. |
from_name |
Absendername der Benachrichtigungsmail. Max. 100 Zeichen. |
replyto / reply_to |
Antwortadresse. Muss eine einzelne gültige Adresse sein. |
ccemail |
Kommagetrennte CC-Adressen, höchstens fünf. |
redirect |
Ziel des 303 nach einer erfolgreichen Einsendung. |
botcheck / _gotcha |
Honeypot. Alles, was hier steht, markiert die Einsendung als Spam. |
altcha |
Die gelöste ALTCHA-Challenge. |
h-captcha-response |
hCaptcha-Token, wenn dieser Anbieter aktiv ist. |
cf-turnstile-response |
Cloudflare-Turnstile-Token. |
g-recaptcha-response |
Google-reCAPTCHA-Token. |
mcaptcha__token |
mCaptcha-Token. |
Werte, die der Absender kontrolliert, werden geprüft: Adressen müssen gültig sein, Freitext wird von Zeilenumbrüchen befreit und gekürzt. Ein ungültiger Wert fällt auf die Einstellung des Formulars zurück, statt verwendet zu werden. Eine Routing-Regel gewinnt immer gegen diese Felder — eine Regel ist eine serverseitige Entscheidung, das Feld reist in einer Anfrage, die jeder bauen kann.
Datei-Uploads
Schick die Anfrage als multipart/form-data — dann wird jeder Datei-Teil gespeichert, an die Benachrichtigungsmail gehängt und ist im Dashboard herunterladbar. Den Feldnamen wählst du; mehrere Dateien dürfen sich einen Namen teilen.
| Limit | Vorgabe | Umgebungsvariable |
|---|---|---|
| Größe je Datei | 10 MB |
UPLOAD_MAX_FILE_SIZE_MB |
| Dateien je Einsendung | 5 |
UPLOAD_MAX_FILES |
Die Limits greifen schon beim Lesen der Anfrage: Ein zu großer Teil wird mitten im Datenstrom abgebrochen und mit 413 beantwortet, statt erst gepuffert zu werden. Prüf Größe und Anzahl zusätzlich im Browser — das macht aus einer fehlgeschlagenen Anfrage eine hilfreiche Meldung.
Captcha
ALTCHA ist ein Proof-of-Work-Captcha: keine Cookies, kein Drittanbieter, kein Rätsel für den Besucher — der Browser investiert kurz Rechenzeit, und genau das macht Massenversand für einen Bot teuer. Challenge holen, lösen, die Lösung im Feld altcha zurückschicken.
Die Reihenfolge zählt: erst das Token liefern, dann die Pflicht in den Formular-Einstellungen einschalten. Andersherum wird jede Einsendung mit 403 abgelehnt. Das Client-Script erledigt den ganzen Ablauf für dich — siehe seine eigene Seite.
Selbst gehostet? In der Instanz muss ALTCHA_HMAC_KEY gesetzt sein, sonst antwortet der Challenge-Endpunkt mit 404 und die Formular-Einstellung bleibt wirkungslos.
Nach der Einsendung
Bei einem Browser-Formular-Post antwortet der Server mit 303 und schickt den Besucher weiter. Vier Kandidaten werden in dieser Reihenfolge geprüft: eine Routing-Regel, das Feld redirect, die im Formular hinterlegte URL und zuletzt unsere gehostete Danke-Seite.
Jedes Ziel wird vor der Verwendung gegen die erlaubten Domains des Formulars geprüft. Ein abgelehntes Ziel wird protokolliert, und der nächste Kandidat übernimmt — ohne diese Prüfung wäre der Endpunkt ein offener Redirect auf unserer eigenen Domain.
Fehler dieses Endpunkts
| Code | Ursache |
|---|---|
404 Missing access key |
Weder in der URL noch im Body vorhanden. |
404 Unknown access key |
Kein Formular hat diesen Key. |
403 This form is blocked |
Das Formular wurde deaktiviert — siehe Dashboard. |
403 Origin not permitted |
Die Anfrage kam von einer nicht erlaubten Domain. |
403 Captcha verification failed |
Token fehlt, ist falsch oder wurde schon verwendet. |
429 |
Limit je Formular, je IP oder für den Monat erreicht. |
413 |
Ein Upload war größer als das eingestellte Maximum. |
Eine Einsendung, die in einen Timeout gelaufen ist, kann trotzdem gespeichert worden sein. Wiederhol sie nie blind — du legst sonst ein Duplikat an. Lesende Anfragen darfst du gefahrlos wiederholen.