Formhook-Dokumentation
Fügen Sie Ihren API-Schlüssel in die action eines Formulars ein, erhalten Sie Einsendungen in Ihrem Dashboard und eine System-Push-Benachrichtigung für jede neue Einsendung.
Schnellstart
1. Registrieren und E-Mail bestätigen.
2. Formular im Dashboard erstellen. API-Schlüssel kopieren (sieht aus wie fh_…).
3. Als action Ihres HTML-Formulars einfügen. Das war's.
HTML-Formular (ohne JavaScript)
Die einfachste Integration. Native Formular-Übermittlung, optionale Weiterleitung bei Erfolg.
<form action="https://formhook.app/f/YOUR_API_KEY" method="POST">
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<!-- honeypot: bots fill this, humans don't see it -->
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
style="position:absolute;left:-9999px">
<!-- where to send the user after success -->
<input type="hidden" name="_redirect" value="https://example.com/thanks">
<button type="submit">Send</button>
</form>JavaScript fetch
await fetch("https://formhook.app/f/YOUR_API_KEY", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: "user@example.com",
message: "Hello",
}),
});React-Komponente
"use client";
import { useState } from "react";
export function ContactForm() {
const [status, setStatus] = useState<"idle" | "sending" | "ok" | "error">("idle");
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus("sending");
const data = Object.fromEntries(new FormData(e.currentTarget));
const res = await fetch("https://formhook.app/f/YOUR_API_KEY", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
setStatus(res.ok ? "ok" : "error");
}
if (status === "ok") return <p>Thanks - we'll be in touch.</p>;
return (
<form onSubmit={onSubmit}>
<input name="email" type="email" required />
<textarea name="message" required />
<button disabled={status === "sending"}>Send</button>
{status === "error" && <p>Something went wrong. Try again.</p>}
</form>
);
}WordPress
Formhook ist ein Formular-Backend, daher kann jedes WordPress-Formular an Formhook senden. Wählen Sie die passende Variante:
Natives HTML-Formular
Fügen Sie ein einfaches Formular in eine Seite oder einen Block ein und richten Sie dessen action auf Ihren Endpunkt. Fügen Sie die Origin Ihrer Website zu den Erlaubten Ursprüngen des Formulars hinzu, damit Browser-Einsendungen akzeptiert werden.
<form action="https://formhook.app/f/YOUR_API_KEY" method="POST">
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<input type="hidden" name="_redirect" value="https://your-site.com/thanks">
<button type="submit">Send</button>
</form>Contact Form 7
Leiten Sie jede Contact-Form-7-Einsendung aus der functions.php Ihres Themes weiter. Da die Anfrage von Ihrem Server kommt (keine Browser-Origin), authentifizieren Sie sie mit einem X-Auth-Token:
// functions.php - forward Contact Form 7 submissions to Formhook
add_action('wpcf7_before_send_mail', function ($contact_form) {
$submission = WPCF7_Submission::get_instance();
if (!$submission) return;
$data = $submission->get_posted_data();
wp_remote_post('https://formhook.app/f/YOUR_API_KEY', [
'headers' => [
'Content-Type' => 'application/json',
'X-Auth-Token' => 'YOUR_AUTH_TOKEN',
],
'body' => wp_json_encode($data),
'timeout' => 10,
]);
});Gravity Forms
Verwenden Sie das offizielle Webhooks-Add-on, um an Ihren Endpunkt zu senden, oder leiten Sie aus der functions.php mit demselben serverseitigen Token weiter:
// functions.php - forward Gravity Forms submissions to Formhook
add_action('gform_after_submission', function ($entry, $form) {
$payload = [];
foreach ($form['fields'] as $field) {
$payload[$field->label] = rgar($entry, (string) $field->id);
}
wp_remote_post('https://formhook.app/f/YOUR_API_KEY', [
'headers' => [
'Content-Type' => 'application/json',
'X-Auth-Token' => 'YOUR_AUTH_TOKEN',
],
'body' => wp_json_encode($payload),
'timeout' => 10,
]);
}, 10, 2);Erzeugen Sie das Token unter Einstellungen → Authentifizierung von Serveranfragen Ihres Formulars. Siehe Ursprünge & Authentifizierung zum Unterschied zwischen Browser- und Serveranfragen.
cURL (zum Testen)
Server-zu-Server-Anfragen (curl, Backend-Code) senden keinen Origin-Header und müssen sich daher mit einem X-Auth-Token-Header authentifizieren. Generieren Sie einen Token unter Einstellungen → Authentifizierung von Serveranfragen Ihres Formulars und übergeben Sie ihn bei jeder Anfrage - ohne ihn werden Serveranfragen abgelehnt.
curl -X POST https://formhook.app/f/YOUR_API_KEY \
-H "Content-Type: application/json" \
-H "X-Auth-Token: YOUR_AUTH_TOKEN" \
-d '{"email":"test@example.com","message":"hi"}'Reservierte Felder
Diese drei Feldnamen werden aus dem gespeicherten Payload entfernt:
_gotcha- Honeypot. Alles, was hier nicht leer ist, gibt 200 OK zurück, verwirft die Einsendung aber stillschweigend und verbraucht kein Kontingent._redirect- URL für Weiterleitung bei Erfolg (nur form-encoded). Muss eine Origin auf der Allowlist Ihres Formulars sein; sonst ignoriert.cf-turnstile-response- Turnstile-Token, serverseitig validiert.
CORS
Fügen Sie für Browser-Übermittlungen den Ursprung (Schema + Host, ohne Pfad) zu den Erlaubten Ursprüngen Ihres Formulars in den Einstellungen hinzu. Eine leere Liste lehnt Anfragen mit Browser-Ursprung vollständig ab. Server-zu-Server-Anfragen (ohne Origin-Header, etwa curl oder ein Backend) müssen einen gültigen X-Auth-Token-Header senden, der in den Formulareinstellungen generiert wird; ohne Token werden sie abgelehnt.
Cloudflare Turnstile (optional)
Aktivieren Sie Turnstile in den Einstellungen Ihres Formulars und betten Sie das Widget in Ihr HTML ein:
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js"
async defer></script>
<form action="https://formhook.app/f/YOUR_API_KEY" method="POST">
<input name="email" type="email" required>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITEKEY"></div>
<button type="submit">Send</button>
</form>Datei-Uploads (Pro und Studio)
Formulare können Datei-Anhänge entgegennehmen. Senden Sie mit enctype="multipart/form-data"; jedes <input type="file">-Feld wird in den Objektspeicher hochgeladen und in Ihrem Dashboard mit der Einsendung verknüpft. Dateien werden per Signed URL mit kurzer TTL aus dem Dashboard heruntergeladen; nichts ist öffentlich adressierbar.
<!-- enctype is the important bit -->
<form action="https://formhook.app/f/YOUR_API_KEY" method="POST" enctype="multipart/form-data">
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<!-- one or more file inputs; same field name = multiple files -->
<input name="attachment" type="file">
<button type="submit">Send</button>
</form>Pro-Datei-Limit: 10 MB. Pro-Konto-Speicher: 1 GB auf Pro, 10 GB auf Studio. Soft-Fail-Antworten: {ok: true, warnings: ["file_too_large"]}, wenn eine einzelne Datei das Pro-Datei-Limit überschreitet, ["storage_full"], wenn das Konto sein Kontingent erreicht hat, ["files_not_configured"], wenn der Betreiber keinen Objektspeicher bereitgestellt hat. In jedem Fall wird die Text-Einsendung trotzdem gespeichert.
Studio: Kundenformulare bereitstellen und übertragen
Studio-Konten können ein Formular für einen Kunden erstellen und übergeben. Das Studio konfiguriert und testet, solange es Eigentümer ist; nach der Übertragung gehören das Formular und seine Einsendungen dem Kunden, und das Studio sieht nur Metadaten.
- Füllen Sie unter Neues Formular das optionale Feld Kunden-E-Mail aus. Das Formular wird als Kundenformular markiert (Sponsorship wird festgehalten), aber Sie sind weiterhin Eigentümer.
- Konfigurieren und testen Sie das Formular normal - Einsendungen landen während des Testens in Ihrem Dashboard.
- Wenn Sie bereit sind, öffnen Sie Formular-Einstellungen → Abschnitt Kunden-Übertragung und senden Sie die Einladung. Das Formular bleibt aktiv und nimmt während des Wartens weiter Einsendungen an.
- Ihr Kunde erhält einen Link per E-Mail, registriert sich (die E-Mail wird durch Token-Besitz automatisch verifiziert) und klickt auf Beanspruchen. Ab diesem Moment fließen Einsendungen in sein Dashboard.
Nach der Beanspruchung sehen Sie das Formular in Ihrer Kunden-Konsole mit Status + Monatszählern. Sie sehen keine Einsendungsinhalte und keine Anhänge mehr - das ist die DSGVO-Grenze, die Sie aus der Datenkette Ihrer Kunden heraushält. Einsendungen zählen weiterhin gegen Ihr Studio-Limit (Billing rollt hoch); der Kunde selbst kann auf Kostenlos bleiben, ohne dass etwas bricht.
Einsendungen importieren
Importieren Sie Einsendungen per JSON-Datei in großer Menge in ein Formular - öffnen Sie das Formular in Ihrem Dashboard, klicken Sie auf Importieren und laden Sie eine Datei in dieser Form hoch:
{
"schemaVersion": 1,
"submissions": [
{
"payload": { "email": "ada@example.com", "message": "Hello" },
"createdAt": "2025-01-02T15:04:05Z"
}
]
}Die oberste Ebene darf ein Array von Einträgen oder ein Objekt mit einem submissions-Array sein. Jeder Eintrag benötigt ein payload-Objekt; createdAt (ISO-8601) ist optional und wird bei Vorhandensein übernommen. Importierte Einsendungen werden als gelesen markiert, lösen nie Benachrichtigungen oder Webhooks aus und sind auf 5.000 pro Datei (max. 5 MB) begrenzt.
Rate-Limits und Kontingente
- Pro IP über alle Formulare: 10 Anfragen/Minute → 429 mit
Retry-After. - Pro Formular: 60 Anfragen/Minute → 429.
- Body-Größenobergrenze: 64 KB → 413.
- Monatliches Kontingent der kostenlosen Stufe: 250 Einsendungen über ein rollierendes 30-Tage-Fenster. Über dem Kontingent gibt der Endpunkt weiterhin 200 zurück, mit
warnings: ["over_quota"]im Body - Einsendungen werden nie stillschweigend verworfen.
Fehlerantworten
| HTTP | Code | Bedeutung |
|---|---|---|
| 200 | ok | Erfolg |
| 302 | - | Weiterleitung zur _redirect-URL |
| 400 | invalid_body | fehlerhaftes JSON / nicht unterstützter Content-Type |
| 403 | origin_not_allowed | CORS-Allowlist-Mismatch |
| 403 | turnstile_failed | Turnstile-Token fehlt/ungültig |
| 403 | account_suspended | Formular-Inhaber ist gesperrt |
| 404 | form_not_found | unbekannter api_key |
| 413 | body_too_large | Body > 64 KB |
| 429 | rate_limited | enthält Retry-After-Header |
| 500 | internal_error | erneut versuchen oder melden |
Push-Benachrichtigungen (für Sie als Formular-Inhaber)
Öffnen Sie Ihr Dashboard und klicken Sie auf Benachrichtigungen aktivieren - Ihr Browser fragt nach der Erlaubnis, dann löst jede neue Einsendung eine System-Benachrichtigung aus, auch bei geschlossenem Tab. Auf iOS installieren Sie Formhook zuerst auf Ihrem Homescreen (Safari 16.4+).