Aller au contenu
FFormhook

Documentation Formhook

Collez votre clé API dans l'action d'un formulaire, recevez les soumissions dans votre tableau de bord, et obtenez une notification push système pour chaque nouvelle entrée.

Démarrage rapide

1. Inscrivez-vous et vérifiez votre e-mail.
2. Créez un formulaire dans votre tableau de bord. Copiez la clé API (qui ressemble à fh_…).
3. Collez-la comme action de votre formulaire HTML. C'est tout.

Formulaire HTML (sans JavaScript)

L'intégration la plus simple. Soumission native, redirection optionnelle en cas de succès.

<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>

fetch JavaScript

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",
  }),
});

Composant React

"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 est un backend de formulaire ; n’importe quel formulaire WordPress peut donc lui envoyer des données. Choisissez l’option adaptée à votre configuration :

Formulaire HTML natif

Placez un formulaire simple dans une page ou un bloc et dirigez son action vers votre endpoint. Ajoutez l’origine de votre site aux Origines autorisées du formulaire pour accepter les soumissions du navigateur.

<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

Transférez chaque soumission Contact Form 7 depuis le functions.php de votre thème. Comme la requête provient de votre serveur (pas d’Origin de navigateur), authentifiez-la avec un 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

Utilisez le module Webhooks officiel pour envoyer vers votre endpoint, ou transférez depuis functions.php avec le même jeton côté serveur :

// 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);

Générez le jeton dans Réglages → Authentification des requêtes serveur de votre formulaire. Voir Origines et authentification pour la différence entre requêtes navigateur et serveur.

cURL (tests)

Les requêtes de serveur à serveur (curl, code backend) n'envoient pas d'en-tête Origin, elles doivent donc s'authentifier avec un en-tête X-Auth-Token. Générez un jeton dans Paramètres → Authentification des requêtes serveur de votre formulaire et transmettez-le à chaque requête - sans lui, les requêtes serveur sont rejetées.

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"}'

Champs réservés

Ces trois noms de champs sont retirés du payload stocké :

  • _gotcha - honeypot. Toute valeur non vide ici renvoie un succès 200 mais abandonne silencieusement la soumission et ne consomme pas votre quota.
  • _redirect - URL vers laquelle rediriger en cas de succès (posts form-encoded uniquement). Doit être sur une origine de la liste autorisée du formulaire ; sinon ignoré.
  • cf-turnstile-response - jeton Turnstile, validé côté serveur.

CORS

Pour les envois depuis un navigateur, ajoutez l'origine (schéma + hôte, sans chemin) aux Origines autorisées de votre formulaire dans les paramètres. Une liste vide rejette entièrement les requêtes d'origine navigateur. Les requêtes de serveur à serveur (sans en-tête Origin, comme curl ou un backend) doivent envoyer un en-tête X-Auth-Token valide généré dans les paramètres du formulaire ; sans jeton, elles sont rejetées.

Cloudflare Turnstile (optionnel)

Activez Turnstile dans les paramètres de votre formulaire, puis intégrez le widget dans votre HTML :

<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>

Téléversement de fichiers (Pro et Studio)

Les formulaires peuvent accepter des pièces jointes. Soumettez avec enctype="multipart/form-data" ; chaque champ <input type="file"> est téléversé vers le stockage objet et lié à la soumission dans votre tableau de bord. Les fichiers sont téléchargés via des URL signées à TTL court depuis le tableau de bord ; rien n'est adressable publiquement.

<!-- 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>

Plafond par fichier : 10 Mo. Stockage par compte : 1 Go sur Pro, 10 Go sur Studio. Réponses soft-fail : {ok: true, warnings: ["file_too_large"]} lorsqu'un fichier dépasse le plafond par fichier, ["storage_full"] quand le compte atteint son allocation, ["files_not_configured"] si l'opérateur n'a pas provisionné de stockage objet. Dans tous les cas, la soumission texte est enregistrée.

Studio : provisionner et transférer un formulaire client

Les comptes Studio peuvent construire un formulaire pour un client et le lui remettre. Le studio configure et teste tant qu'il possède le formulaire ; une fois transféré, le client possède le formulaire et ses soumissions, et le studio ne voit que les métadonnées.

  1. Sur Nouveau formulaire, remplissez le champ optionnel E-mail du client. Le formulaire est marqué comme formulaire client (le parrainage est enregistré) mais vous en êtes encore propriétaire.
  2. Configurez et testez le formulaire normalement - les soumissions arrivent dans votre tableau de bord pendant les tests.
  3. Quand vous êtes prêt, ouvrez Paramètres du formulaire → section Transfert client et envoyez l'invitation. Le formulaire reste actif et continue d'accepter les soumissions pendant l'attente.
  4. Votre client reçoit un lien par e-mail, s'inscrit (l'e-mail est auto-vérifié par possession du jeton), et clique sur Revendiquer. Dès cet instant, les soumissions arrivent dans son tableau de bord.

Après la revendication, vous voyez le formulaire dans votre console Clients avec statut + compteurs mensuels. Vous ne voyez plus le contenu des soumissions ni les pièces jointes - c'est la frontière RGPD qui vous tient hors de la chaîne de données de vos clients. Les soumissions comptent quand même sur votre plafond Studio (la facturation remonte) ; le client peut rester en Gratuit sans rien casser.

Importer des soumissions

Importez en masse des soumissions dans un formulaire depuis un fichier JSON - ouvrez le formulaire dans votre tableau de bord, cliquez sur Importer et téléversez un fichier de cette forme :

{
  "schemaVersion": 1,
  "submissions": [
    {
      "payload": { "email": "ada@example.com", "message": "Hello" },
      "createdAt": "2025-01-02T15:04:05Z"
    }
  ]
}

Le niveau supérieur peut être un tableau d’entrées ou un objet avec un tableau submissions. Chaque entrée doit comporter un objet payload ; createdAt (ISO-8601) est facultatif et conservé s’il est présent. Les soumissions importées sont marquées comme lues, ne déclenchent jamais de notifications ni de webhooks, et sont limitées à 5 000 par fichier (max 5 Mo).

Limites de débit et quotas

  • Par IP, tous formulaires confondus : 10 requêtes/minute → 429 avec Retry-After.
  • Par formulaire : 60 requêtes/minute → 429.
  • Taille de corps maximale : 64 Ko → 413.
  • Quota mensuel du niveau gratuit : 250 soumissions sur une fenêtre glissante de 30 jours. Le dépassement renvoie toujours 200 avec warnings: ["over_quota"] dans le corps - les soumissions ne sont jamais silencieusement abandonnées.

Réponses d'erreur

HTTPcodesignification
200oksuccès
302-redirection vers l'URL _redirect
400invalid_bodyJSON mal formé / content-type non pris en charge
403origin_not_allowedécart de la liste CORS
403turnstile_failedjeton Turnstile manquant/invalide
403account_suspendedpropriétaire du formulaire suspendu
404form_not_foundapi_key inconnue
413body_too_largecorps > 64 Ko
429rate_limitedinclut l'en-tête Retry-After
500internal_errorréessayez ou signalez

Notifications push (pour vous, propriétaire du formulaire)

Ouvrez votre tableau de bord et cliquez sur Activer les notifications - votre navigateur demandera la permission, puis chaque nouvelle soumission déclenche une notification système, même quand l'onglet est fermé. Sur iOS, installez Formhook sur votre écran d'accueil d'abord (Safari 16.4+).