Zum Inhalt springen
FFormhook

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.

  1. 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.
  2. Konfigurieren und testen Sie das Formular normal - Einsendungen landen während des Testens in Ihrem Dashboard.
  3. 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.
  4. 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

HTTPCodeBedeutung
200okErfolg
302-Weiterleitung zur _redirect-URL
400invalid_bodyfehlerhaftes JSON / nicht unterstützter Content-Type
403origin_not_allowedCORS-Allowlist-Mismatch
403turnstile_failedTurnstile-Token fehlt/ungültig
403account_suspendedFormular-Inhaber ist gesperrt
404form_not_foundunbekannter api_key
413body_too_largeBody > 64 KB
429rate_limitedenthält Retry-After-Header
500internal_errorerneut 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+).