Business

REST-Schnittstelle

Holen Sie Übermittlungen automatisch in Ihr CRM, Ihr Ticketsystem oder eigene Skripte – mit einer schlichten JSON-Schnittstelle.

Anmeldung

Jede Anfrage braucht einen API-Schlüssel im Authorization-Header. Schlüssel legen Sie als Inhaber eines Business-Kontos im Konto unter „API“ an.

curl https://www.formpost.eu/api/v1/submissions?since=2026-10-01T00:00:00Z \
  -H "Authorization: Bearer fp_..."

Ein Schlüssel gehört zum Konto, nicht zu einer Person, und sieht alle Formulare des Kontos. Läuft der Business-Tarif aus, antwortet die Schnittstelle mit 403, bis wieder gebucht wird.

Endpunkte

GET /forms

Alle Formulare des Kontos.

GET /forms/{id}

Ein Formular. Die ID ist die Kennung aus der Formular-Adresse (/f/abc123).

GET /submissions

Übermittlungen aller Formulare, neueste zuerst.

GET /forms/{id}/submissions

Übermittlungen eines Formulars.

GET /submissions/{id}

Eine einzelne Übermittlung.

PATCH /submissions/{id}

Als Spam markieren oder freigeben.

DELETE /submissions/{id}

Übermittlung endgültig löschen.

Alle Pfade beziehen sich auf https://www.formpost.eu/api/v1. Antworten kommen als JSON.

Parameter für Listen

filter
valid (Standard), spam oder all – dieselben Filter wie im Posteingang.
since
Nur Übermittlungen ab diesem Zeitpunkt (ISO 8601). So holen Sie regelmäßig nur das Neue ab.
page
Seite, beginnend bei 1.
per_page
Einträge je Seite, 1 bis 100 (Standard 50).

Antworten

Listen stehen in data, Angaben zur Seite in meta.

{
  "data": [
    {
      "id": 4711,
      "form_id": "abc123",
      "state": "valid",
      "spam": false,
      "verified": true,
      "encrypted": false,
      "data": { "email": "anna@example.com", "message": "Hallo!" },
      "encrypted_data": null,
      "recipient_email": "info@example.com",
      "referer": "https://example.com/kontakt",
      "created_at": "2026-10-12T09:30:00Z"
    }
  ],
  "meta": { "page": 1, "per_page": 50, "total": 1, "total_pages": 1, "filter": "valid" }
}

Bei verschlüsselten Formularen ist data leer, und encrypted_data enthält den versiegelten Umschlag. Den Inhalt kennen wir auch über die Schnittstelle nicht – öffnen lässt er sich nur mit Ihrem privaten Schlüssel. Mehr dazu unter Zero-Knowledge-Verschlüsselung.

Spam markieren

Mit spam: true landet eine Übermittlung im Spam, mit spam: false wird sie wieder freigegeben.

curl -X PATCH https://www.formpost.eu/api/v1/submissions/4711 \
  -H "Authorization: Bearer fp_..." \
  -H "Content-Type: application/json" \
  -d '{"spam": true}'

Fehler

Fehler kommen mit passendem HTTP-Status und einer maschinenlesbaren Kennung.

{ "error": { "code": "unauthorized", "message": "Missing or invalid API key" } }
  • 401 – Schlüssel fehlt, ist falsch oder wurde widerrufen.
  • 403 – Das Konto hat keinen aktiven Business-Tarif.
  • 404 – Formular oder Übermittlung gibt es in diesem Konto nicht.
  • 400 – Ungültiger Parameter, z.B. ein falsches Datumsformat.
  • 429 – Zu viele Anfragen – höchstens 120 pro Minute und Schlüssel.

Webhooks

Statt regelmäßig nachzufragen, können Sie sich jede neue Übermittlung zuschicken lassen. Wir senden dann einen POST mit JSON an Ihre Adresse – sobald die Übermittlung den Spamschutz passiert hat, zur selben Zeit wie die E-Mail.

POST https://example.com/formpost-webhook
Content-Type: application/json
FormPost-Event: submission.created
FormPost-Delivery: 5f0c2c1e-8a8e-4c4a-9b7e-2d6b1d0f7a11
FormPost-Signature: t=1760261400,v1=3b1f…

{
  "id": "5f0c2c1e-8a8e-4c4a-9b7e-2d6b1d0f7a11",
  "type": "submission.created",
  "created_at": "2026-10-12T09:30:00Z",
  "data": {
    "submission": { "id": 4711, "form_id": "abc123", "state": "valid", "data": { "email": "anna@example.com" }, … },
    "form": { "id": "abc123", "name": "Kontakt", … }
  }
}
  • Ereignisse: submission.created für neue, gültige Übermittlungen und ping für die Testnachricht aus dem Konto.
  • Antwortet Ihr Server nicht innerhalb von 10 Sekunden mit einem 2xx-Status, versuchen wir es bis zu sechsmal über rund neun Stunden. Nach zehn endgültig gescheiterten Zustellungen in Folge schalten wir den Webhook ab.
  • Bei verschlüsselten Formularen enthält der Webhook nur den versiegelten Umschlag, genau wie die Schnittstelle.
  • Jede Zustellung hat eine eindeutige ID (FormPost-Delivery). Kommt dieselbe ID zweimal an, verarbeiten Sie sie nur einmal.

Signatur prüfen

Jede Nachricht ist mit dem Geheimnis des Webhooks signiert (HMAC-SHA256 über Zeitstempel, Punkt und Inhalt). Prüfen Sie die Signatur, bevor Sie etwas verarbeiten – so weiß Ihr Server, dass die Nachricht wirklich von uns kommt.

<?php
$secret = 'whsec_...';
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_FORMPOST_SIGNATURE'] ?? '';
parse_str(str_replace(',', '&', $header), $sig); // ['t' => ..., 'v1' => ...]

$expected = hash_hmac('sha256', $sig['t'] . '.' . $body, $secret);
if (!hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) $sig['t']) > 300) {
    http_response_code(400);
    exit;
}

$event = json_decode($body, true);
// $event['data']['submission'] verarbeiten …
http_response_code(200);

Loslegen

Die REST-Schnittstelle ist im Business-Tarif enthalten – zusammen mit Teamzugängen und bis zu 1.000 Formularen.

API-Schlüssel anlegen