Zum Inhalt springen

Webhook-Endpoint — Angebot importieren

Der Webhook-Endpoint legt ein einzelnes Angebot als Entwurf in deiner Flino-Organisation an. Er ist idempotent über die Kombination external_source + external_id, sodass derselbe Aufruf mehrfach abgesendet kein Duplikat erzeugt.

POST https://<euer-projekt>.supabase.co/functions/v1/zapier-offer-import

Den <euer-projekt>-Teil findest du in Einstellungen → Integrationen → API-Tokens in der Sektion „Zapier Webhook URL”.

Diese Supabase-Functions-URL ist die kanonische und dauerhafte Endpoint-Adresse für den Webhook. Eine eigene API-Subdomain (z. B. api.flino.io) ist aktuell nicht geplant — verwende die hier gezeigte URL als stabile Adresse.

Header:

x-flino-token: <dein-api-token>
Content-Type: application/json

Den <dein-api-token> erstellst du wie unter API-Tokens beschrieben. Pro Token ist der Scope fest auf offer_import:write gesetzt.

Nur POST wird akzeptiert. Andere Methoden geben 405 Method not allowed zurück.

Der Body muss ein JSON-Objekt sein. Listen oder Strings werden mit 400 Request body must be a JSON object abgewiesen.

FeldTypBeschreibung
titlestring, nicht leerTitel des Angebots, z. B. „Website-Redesign Mustermann GmbH”
external_idstring, nicht leerEindeutige ID aus deinem System — Schlüssel für Idempotenz
external_sourcestring, nicht leerQuell-System, z. B. zoho, pipedrive, zapier, myform — wird intern in Kleinbuchstaben gespeichert
FeldTypBeschreibung / Default
amountnumber | nullAngebotsbetrag in Hauptwährungs-Einheit (z. B. 1500.00)
currencystringEUR (Default), USD oder CHF. Andere Werte werden mit 400 abgewiesen.
contact_namestring | nullVoller Name. Flino splittet automatisch in Vor- und Nachname.
contact_emailstring | nullMuss ein valides E-Mail-Format haben. Wird in Kleinbuchstaben gespeichert.
company_namestring | nullFirmenname; Flino legt eine neue Firma an oder verwendet eine bestehende
offer_numberstring | nullEigene Angebotsnummer
valid_untilstring | nullISO-Datum, z. B. 2026-12-31. Ungültige Datumswerte werden ignoriert (Wert bleibt null).
  • Anrede und Sprache werden im Phase-1-Webhook nicht übermittelt — der Kontakt bekommt sie manuell oder beim ersten Versand-Modal nachgepflegt.
  • Adresse wird im Phase-1-Webhook nicht übermittelt.

Flino prüft pro Aufruf, ob in deiner Organisation bereits ein Angebot mit derselben Kombination external_source + external_id existiert.

  • Existiert es: kein neues Angebot, Antwort 200 mit created: false und der bestehenden offer_id.
  • Existiert es nicht: neues Angebot wird angelegt, Antwort 200 mit created: true.

Das ist nützlich, wenn dein Quell-System Retries macht — du läufst nicht in Duplikate.

Status 200 OK:

{
"success": true,
"created": true,
"offer_id": "8d3f7e09-1e0e-44e5-b6c3-49e3a7c2a131",
"status": "draft"
}

Bei Idempotenz-Treffer:

{
"success": true,
"created": false,
"offer_id": "8d3f7e09-1e0e-44e5-b6c3-49e3a7c2a131",
"status": "draft"
}
POST /functions/v1/zapier-offer-import HTTP/1.1
Host: <euer-projekt>.supabase.co
Content-Type: application/json
x-flino-token: 9a3f...c1e2
{
"title": "Website-Redesign Mustermann GmbH",
"amount": 4900,
"currency": "EUR",
"contact_name": "Anna Mustermann",
"contact_email": "anna@mustermann.de",
"company_name": "Mustermann GmbH",
"offer_number": "ANG-2026-0042",
"valid_until": "2026-06-30",
"external_id": "deal_19238",
"external_source": "zoho"
}
{
"success": true,
"created": true,
"offer_id": "8d3f7e09-1e0e-44e5-b6c3-49e3a7c2a131",
"status": "draft"
}
HTTP-StatusBody errorBedeutung
400Invalid JSON bodyBody ist kein gültiges JSON
400Request body must be a JSON objectBody ist Liste oder String
400Field 'title' is required and must be a non-empty stringtitle fehlt oder leer
400Field 'external_id' is required and must be a non-empty stringexternal_id fehlt oder leer
400Field 'external_source' is required and must be a non-empty stringexternal_source fehlt oder leer
400Field 'currency' must be one of: EUR, USD, CHFunzulässige Währung
400Field 'amount' must be a numberamount als String oder Boolean
400Field 'contact_email' is not a valid email addressMail-Format ungültig
401Missing x-flino-token headerHeader fehlt
401Invalid or unknown tokenToken nicht gefunden
401Token has been revokedToken wurde widerrufen
403Token lacks required scope: offer_import:writeScope passt nicht
405Method not allowednur POST erlaubt
500Organisation owner not foundOrg-Konfigurationsproblem — Support kontaktieren
500Failed to create offer: ...Datenbank-Problem

Alle Fehler-Antworten haben das Schema:

{
"success": false,
"error": "<Klartext-Beschreibung>"
}
  1. Token validieren — SHA-256-Lookup, Scope-Check, Revoke-Check.
  2. Idempotenz prüfen — gibt’s das Angebot schon? Wenn ja, dasselbe zurückgeben.
  3. Firma anlegen oder wiederverwenden — wenn company_name gesetzt ist, sucht Flino zuerst eine vorhandene Firma mit demselben Namen in deiner Org. Findet sie keine, wird eine neue angelegt.
  4. Kontakt anlegen oder wiederverwenden — über contact_email (wenn gesetzt) als Schlüssel; sonst über Name. Flino splittet contact_name automatisch in Vor- und Nachname.
  5. Angebot als draft anlegen — mit Versandstatus not_sent, Quelle zapier, deinen external_id und external_source für die nächste Idempotenz-Prüfung.
  • Das Angebot landet im Posteingang und in der Pipeline mit Status Neu.
  • Du öffnest es manuell, ergänzt fehlende Daten (Anrede, Mail-Adresse, Beschreibung) und versendest es wie gewohnt aus Flino.
  • Es startet keine Sequenz, es wird keine Mail verschickt — der Webhook ist reines Anlegen.

Aktuell keine Flino-spezifischen Rate-Limits. Wir behalten uns vor, bei Missbrauch limitierend einzugreifen.

Idempotenz für Wiederholungen wird per external_id + Inhalts-Hash sichergestellt — wiederholte Aufrufe mit identischen Daten erzeugen kein doppeltes Angebot.

Wenn du Massen-Importe planst (mehrere hundert Angebote auf einmal), staffel die Aufrufe und sprich kurz mit dem Support, damit deine Org nicht aus Versehen als Anomalie auffällt.