Anfragen
Formular und Request in einem Aufruf erstellen
Ein Agent erfährt im Telefonat mit einer Kundin, dass sie noch zwei Gehaltsabrechnungen hochladen, eine Gebühr von 40 EUR bezahlen und ein Gespräch buchen muss. Er sendet Formular und Request im selben Aufruf, und Formstep übernimmt den Rest.
Wann Sie es nutzen
Ein Request verweist normalerweise auf ein Formular, das jemand im Editor gebaut und veröffentlicht hat. Hängen die Fragen vom Einzelfall
ab, schickt der Aufrufer sie stattdessen mit: requests.create nimmt form anstelle von formId.
Formstep baut aus den Blöcken ein gewöhnliches Formular, veröffentlicht es und erstellt den Request in einem Schritt, sodass entweder
beides existiert oder keines von beiden. Wir nennen das ein Inline-Formular.
Nutzen Sie weiterhin formId für ein Formular, das Sie vielen Personen in derselben Form senden und von Hand im Editor
gestalten möchten. Nutzen Sie form, wenn eine Automation entscheidet, was gefragt wird.
Der Aufruf
curl -X POST https://api.formstep.io/api/v1 \
-H "Authorization: Bearer $FORMSTEP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"method":"requests.create","params":{
"form":{
"name":"Documents and fee for your mortgage application",
"logo":{"type":"image","url":"https://acme.example/logo.png"},
"cover":{"type":"color","color":"#0f4c81"},
"emoji":"🏦",
"blocks":[
{"type":"paragraph","content":"Upload the two documents and pay the processing fee."},
{"type":"file","key":"payslips","title":"Your last two payslips","maxFiles":2},
{"type":"payment","key":"fee","title":"Processing fee","amount":40,"currency":"EUR"},
{"type":"scheduleAppointment","key":"call","title":"Pick a time for our call","eventType":"15 min call"}]},
"recipient":{"email":"ada@example.com","name":"Ada"},
"delivery":"email",
"idempotencyKey":"call-8841"}}'Alles andere am Request behält seine Bedeutung: recipient, prefill, context, readonly,
delivery, Erinnerungen, Ablauf, callbackUrl, test und idempotencyKey werden gegen das
neue Formular genauso geprüft wie gegen eines, das von Hand gebaut wurde. Die Antwort enthält zusätzlich das Formular, mit den Schlüsseln,
unter denen seine Antworten zurückkommen:
{
"id": "kd7...",
"status": "pending",
"url": "https://form.formstep.io/r/rq_...",
"form": {
"id": "j58...",
"name": "Documents and fee for your mortgage application",
"reused": false,
"fields": [
{ "key": "payslips", "type": "file" },
{ "key": "fee", "type": "payment" },
{ "key": "call", "type": "schedule-appointment" }
]
}
}Um eine Auswahlfrage im selben Aufruf vorauszufüllen, senden Sie Optionsschlüssel, wie bei jedem Formular. Der Schlüssel einer Option wird
aus ihrem Label abgeleitet, aus Self-employed wird also self_employed. Ein Label statt eines Schlüssels schlägt
mit INVALID_PREFILL_VALUE fehl, und der Fehler listet die gültigen Schlüssel.
Das Formularobjekt
| Feld | Was es tut |
|---|---|
| name | Erforderlich, 1 bis 100 Zeichen. Der Name im Dashboard und im Browser-Tab, für jede empfangende Person gleich. Personalisieren Sie über prefill und context, nie über den Namen. |
| blocks | Erforderlich, 1 bis 200 Blöcke, in der Reihenfolge, in der das Formular sie zeigt. Die Blöcke in den Spalten einer Zeile und die Felder einer wiederholenden Gruppe zählen mit. |
| language | Die Oberflächensprache des Formulars. Standard: Englisch. |
| logo, cover, emoji | Ihre Marke, mit jedem Request gesendet. logo: { "type": "icon", "name": "HeartIcon" } oder { "type": "image", "url": "https://…" }. cover: { "type": "color", "color": "#0f4c81" } oder { "type": "image", "url": "https://…", "offsetY": 50 }. emoji: ein Emoji neben dem Namen. Siehe unten. |
| theme | Ein Aussehen pro Farbmodus: { "light": "solarized-light", "dark": "dracula" }. Jeder Modus nimmt eine Preset-ID, in jedem Plan kostenlos, oder ein ganzes Theme-Objekt, wie es das MCP-Tool formTheme_set nimmt; das braucht den Pro-Plan. |
| settings | Das Formularverhalten, das die Einstellungsseite festlegt: Branding, eine verifizierte E-Mail-Domain (emailDomainId), E-Mails an die Inhaber und an die antwortende Person samt Text, der Erinnerungsplan, die Einladungs-E-Mail, die Weiterleitung und die Aufbewahrung. Felder per Schlüssel: respondentNotificationTo ist der Schlüssel einer E-Mail-Frage, redirectQueryParams ordnet einem Parameter einen Feldschlüssel zu. E-Mail-Text ist reiner Text mit {{key}}-Platzhaltern. Keine Sperre per Passwort oder Anmeldung und keine Einstellung des Freigabelinks wie Bot-Schutz oder Bearbeiten nach dem Absenden: Eine Anfrage bringt ihren eigenen Link mit. Jeder andere Schlüssel wird abgelehnt. |
| translations | Das Formular in weiteren Sprachen, mit einer Sprachauswahl für die empfangende Person: { "de": { "Your name": "Ihr Name" } }, jeder Text des Formulars unter dem Text, wie die Blöcke ihn geschrieben haben. Siehe unten. |
Blöcke
Ein Block nimmt die Parameter des passenden editor_insert*-Tools auf dem MCP-Server,
ohne formId und after, plus einen optionalen key. Ohne ihn wird der Schlüssel aus dem Titel
abgeleitet, aus „Full name” wird also full_name. Einen Parameter, den der Block nicht kennt, lehnt Formstep ab, statt ihn
stillschweigend zu verwerfen.
| Art | Typen |
|---|---|
| Fragen | text, contact, number, date, time, radio, checkbox, select, switch, rating, linearScale, matrix, ranking, pictureChoice, file, signature, decision |
| Dokumente | documents, um Dateien zu zeigen, die die empfangende Person liest oder unterschreibt |
| Zahlungen und Buchungen | payment, scheduleAppointment |
| Inhalt | header, paragraph, image (src-URL), embedded, table (cells füllt sie), list, row (columns: die Blöcke jeder Spalte, 2 bis 6 Spalten, und widths in Prozent). Mit einem optionalen key kann Logik den Block ein- oder ausblenden. |
| Struktur | pageDivider, repeatingGroup (fields: die zugehörigen Fragen als Blöcke, jede mit ihrem key), hiddenField (key erforderlich: er ist der context-Schlüssel), calculatedField (sein name ist sein Schlüssel), logic |
Text in header und paragraph, Listenpunkte und Tabellenzellen verstehen bold, italic,
, struck<u>underlined</u>, , code$$equation$$,
text, <span color=“red” background=“yellow” font=“font-georgia” size=“1.25”>…</span>
mit den Farben, Schriften und Größen der Editor-Werkzeugleiste, und {{key}}, das den Wert des Felds mit diesem Schlüssel
zeigt. Auszeichnungen lassen sich verschachteln; ein Zeichen ohne Gegenstück bleibt Text. Eine Spalte einer Zeile nimmt jeden Block außer
pageDivider, logic, hiddenField, calculatedField, repeatingGroup, row und scheduleAppointment. Ein decision-Block nimmt
seinen title und seine labels für Zustimmen, Ablehnen und Änderungen in der Sprache des Formulars.
Blöcke verweisen über den Schlüssel aufeinander, nie über die Element-ID: Ein logic-Block nimmt seine rule so
wie editor_insertLogic, mit Feldschlüsseln dort, wo IDs erwartet werden, Optionslabels als Bedingungswerten und Seitennamen
für setNextPage.
Zahlungen
Ein payment-Block nimmt amount und currency, oder amountFromField: den Schlüssel eines
versteckten Felds oder einer Zahlenfrage. Mit einem versteckten Feld übergibt jeder Request seinen eigenen Betrag in context,
sodass ein einziges Formular jeder Person ihren eigenen Betrag berechnet:
{
"form": {
"name": "Pay your invoice",
"blocks": [
{ "type": "hiddenField", "key": "invoice_total" },
{ "type": "payment", "key": "invoice", "title": "Invoice", "currency": "EUR", "amountFromField": "invoice_total" }
]
},
"recipient": { "email": "ada@example.com" },
"context": { "invoice_total": 1200 }
}Eine Zahlenfrage, die den Betrag festlegt, muss ein Pflichtfeld sein und ein min über 0 haben, damit niemand mit einem
leeren, null oder negativen Betrag in den Checkout gelangt.
Das Formular rechnet über das Standard-Stripe-Konto des Workspace ab, oder über das Konto, das connection nennt. Eine Person
verbindet Stripe einmal für den Workspace; eine Automation kann das
nicht. Ohne nutzbares Konto schlägt der Aufruf fehl und sagt Ihnen, wo Sie es verbinden.
Buchungen
Ein scheduleAppointment-Block nimmt eventType, den Titel oder die ID eines Ereignistyps der
Cal.com-Verbindung des Workspace, und connection, wenn der Workspace mehrere hat.
Formstep sucht den Ereignistyp heraus, wenn der Request erstellt wird. prefill: { name, email } nennt die Fragen, deren
Antworten die Buchung ausfüllen.
Ihre Marke
Eine Automation kann Ihren Auftritt nicht erfinden, also geben Sie ihn ihr einmal mit, und sie sendet ihn mit jedem Request:
logo, cover und emoji neben den Blöcken, und theme für Farben und Schrift.
| Feld | Nimmt |
|---|---|
| logo | Ein Icon aus dem Builder, { "type": "icon", "name": "HeartIcon" }, oder Ihr eigenes Bild, { "type": "image", "url": "https://…/logo.png" }. |
| cover | Eine Vollfarbe, { "type": "color", "color": "#0f4c81" }, oder ein Bild, { "type": "image", "url": "https://…/cover.jpg", "offsetY": 50 }, wobei offsetY von 0 bis 100 den sichtbaren Teil eines hohen Bildes wählt. |
| emoji | Ein Emoji, angezeigt neben dem Formularnamen. |
Jedes Bild, einschließlich des src eines image-Blocks, muss ein öffentliches JPEG, PNG oder WebP sein. Formstep lädt jedes
einmal, wenn das Formular erstellt wird, und behält eine eigene Kopie, sodass das Formular und die PDFs seiner Einreichungen die Quelle
überdauern. Eine URL, die sich nicht laden lässt, lässt den Aufruf mit INLINE_FORM_IMAGE_UNREACHABLE fehlschlagen und nennt
das Feld. Ohne Marke sieht das Formular aus wie ein neues Formular aus dem Dashboard.
Übersetzungen
translations veröffentlicht das Formular sofort in weiteren Sprachen, und die empfangende Person erhält die Sprachauswahl
eines übersetzten Formulars:
{ "de": { "Your name": "Ihr Name", "Order for **{{customer}}**": "Bestellung für **{{customer}}**" } }. Jeder Text des
Formulars muss enthalten sein, unter dem Text genau so, wie die Blöcke ihn geschrieben haben: Fragetitel, Optionen, Platzhalter,
Überschriften, Absätze, Listenpunkte, Tabellenzellen, Gruppennamen und Schaltflächenbeschriftungen. Auszeichnungen und
{{key}} bleiben wie in der Quelle. Fehlt ein Text, schlägt der Aufruf mit INLINE_FORM_TRANSLATION_MISSING
fehl, das die fehlenden Texte auflistet. E-Mail-Texte werden nicht übersetzt.
Eine Definition, ein Formular
Ein späterer Aufruf mit demselben form-Objekt nutzt dasselbe Formular erneut, und die Antwort enthält
“reused”: true. Hundert Requests mit einer Definition ergeben ein Formular, mit einem Satz Antworten zum Exportieren. Ändern
Sie einen Block, den Namen, die Marke oder eine Übersetzung, entsteht ein neues Formular; bereits gesendete Requests behalten das
Formular, mit dem sie erstellt wurden. Ein Formular, das Sie für Einreichungen schließen oder zurückziehen, wird nicht erneut genutzt: Der
nächste Aufruf mit derselben Definition erstellt ein neues.
Personalisieren Sie über prefill und context
Setzen Sie den Namen der Kundin oder des Kunden, die Rechnungsnummer oder den Betrag in prefill und context,
nie in den Formularnamen, einen Titel oder einen festen Betrag. Eine Definition, die sich pro Kunde ändert, erzeugt pro Kunde ein neues
Formular. Setzen Sie key bei jeder Frage: Ein abgeleiteter Schlüssel folgt dem Titel, eine umbenannte Frage antwortet also
unter einem neuen Schlüssel. Ein Workspace erzeugt höchstens 300 neue Inline-Formulare pro Tag; danach scheitert ein Aufruf, der ein
neues Formular erzeugen würde, mit RATE_LIMITED, während Aufrufe, die ein Formular wiederverwenden, weiter funktionieren.
Erzeugt ein Aufruf ein neues Formular, obwohl ein offenes Inline-Formular dieselben Blocktypen in derselben Reihenfolge hat, nennt das
Ergebnis des Aufrufs dieses Formular in form.similarForm. Meist war ein geänderter Name oder Titel der Grund. Um alle
Antworten auf ein Inline-Formular zu lesen, listen Sie seine Einreichungen auf, statt jede Anfrage einzeln zu lesen.
Im Dashboard
Ein Inline-Formular gehört zu seiner Anfrage, deshalb steht es auf der Seite der Anfrage statt in der Formularliste. Die Seite listet die
Antworten nach Feldschlüssel, und Vorschau öffnet das Formular so, wie die empfangende Person es gesehen hat, ausgefüllt
mit ihren Antworten. Ein Link zum Editor oder zu den Einreichungen eines Inline-Formulars öffnet stattdessen die Anfragen-Seite, gefiltert
auf dieses Formular. Agenten sehen Inline-Formulare weiterhin in form_list, und die API lehnt Änderungen an ihnen ab.
Ein Inline-Formular hat keinen Freigabelink, und Sie können keinen hinzufügen: Seine Requests sind der einzige Zugang, und der Callback trägt jede Antwort. Integrationen hat es ebenfalls keine.
Da es keine eigene Seite hat, wird ein Inline-Formular nie von Hand gelöscht. Es geht mit seinem letzten Request: Wenn Sie einen Request löschen oder der Aufbewahrungszeitraum des Formulars ihn entfernt und kein anderer Request das Formular noch verwendet, wird auch das Formular gelöscht.
Wenn der Aufruf abgelehnt wird
Jede Ablehnung ist ein VALIDATION_ERROR, auf dessen details.reason Ihre Automation verzweigen kann. Es wird
nichts erstellt.
| Grund | Was zu tun ist |
|---|---|
| FORM_SOURCE_MISSING / FORM_SOURCE_AMBIGUOUS | Senden Sie genau eines von formId und form. |
| INLINE_FORM_INVALID | Ein Block oder ein Feld von form verletzt sein Schema. details.issues nennt jedes davon. |
| INLINE_FORM_DUPLICATE_KEY | Zwei Blöcke ergeben denselben Schlüssel. Geben Sie einem davon einen eigenen key. |
| INLINE_FORM_UNKNOWN_KEY | Eine Logikregel, amountFromField oder ein Buchungs-prefill nennt einen Schlüssel, den kein Block hat. |
| INLINE_FORM_AMOUNT_MISSING | Übergeben Sie in context eine positive Zahl für das Betragsfeld. |
| INLINE_FORM_CONNECTION_MISSING | Stripe oder Cal.com ist nicht verbunden. details.connectUrl ist die Seite, die eine Person einmal öffnet, um es zu verbinden. |
| INLINE_FORM_EVENT_TYPE_NOT_FOUND | Kein Cal.com-Ereignistyp passt. Der Fehler listet die vorhandenen auf. |
| INLINE_FORM_IMAGE_UNREACHABLE | Eine Bild-URL ist kein öffentliches JPEG, PNG oder WebP. details.field nennt sie. Nutzen Sie eine URL, die jeder öffnen kann, oder lassen Sie das Bild weg. |
| INLINE_FORM_TRANSLATION_MISSING | Einer Übersetzung fehlen Texte, die das Formular hat. details.missing listet sie auf, so wie sie in den Blöcken stehen. |
| INLINE_FORM_PUBLISH_ISSUES | Die Veröffentlichung hat das Formular abgelehnt, zum Beispiel wegen eines Ereignistyps, der sich nicht aus einem Formular buchen lässt. |
Aus einem Agenten
Auf dem MCP-Server nimmt request_create dasselbe form. Bevor ein Agent ein Formular mit einer Zahlung oder einer
Buchung baut, liest er workspaceConnection_list: Es zeigt die verbundenen Stripe- und Cal.com-Konten und, wenn eines fehlt,
den Link, den eine Person einmal öffnen muss. scheduler_listEventTypes listet die Ereignistypen, die eine Buchung nennen
kann, und paymentConnection_setDefault ändert das Standard-Stripe-Konto. Über die REST-API heißen dieselben drei
connections.list, scheduler.listEventTypes und paymentConnections.setDefault.