Skip to Content

Automatisierungen

Was Ihr eigenes System von einer Automatisierung erhält, die API-Anfrage als Workflow-Benutzer und der Aufbau eines Flows

Zuletzt aktualisiert am

Automatisierungen lassen Tillor selbst Aktionen ausführen, etwa Aufgaben anlegen oder Ihr System aufrufen. Die Anleitung für Anwender steht unter Automatisierungen. Diese Seite beschreibt, was ein Integrator sieht: die Nachricht des Schritts Webhook senden, die API-Anfrage an eine eigene URL oder an die Tillor API, und wie ein Flow aufgebaut ist, wenn Sie ihn über die API verwalten.

Webhook senden

Der Schritt Webhook senden liefert eine eigene Nachricht an einen der Webhooks der Organisation aus. Es ist dieselbe Zustellung wie bei gewöhnlichen Webhook-Events, mit derselben Signatur.

Die Nachricht

Der Schritt sendet einen POST mit Content-Type: application/json und diesen Headern:

HeaderInhalt
X-Webhook-Event-IDEine eindeutige ID für diese Zustellung. Bei neuen Versuchen bleibt der Wert gleich, Sie können also darüber deduplizieren
X-Webhook-Signaturesha256=<hex>, der HMAC-SHA256 des Bodys mit dem Signing Secret des Webhooks

Der Body hat denselben Umschlag wie die Webhook-Payload:

{
  "event": "automation.invoice_unpaid",
  "data": {
    "invoice": "2026-0042",
    "amountOutstanding": 125.5
  },
  "timestamp": 1735689600000,
  "traceId": "0b0f7c0e-5d3c-4c1e-9b8a-7f1e2a3b4c5d",
  "triggeredBy": null
}
FeldBeschreibung
eventDer Ereignisname, den Sie im Schritt eingetragen haben. Jeder Text ist erlaubt, der Name muss nicht in der Liste der Event-Keys stehen
dataDie Payload aus dem Schritt, nachdem die Variablen eingesetzt wurden, als JSON
timestampUnix-Zeit in Millisekunden der Zustellung
traceIdEine zufällige UUID pro Zustellung. Anders als bei Events aus dem System ist dies keine Trace-ID einer Tillor-Aktion
triggeredByImmer null

Es gibt keine spanId. Der Webhook muss auf keinen Event-Key abonniert sein: Eine Nachricht aus einer Automatisierung wird immer am gewählten Endpunkt zugestellt, solange dieser existiert und aktiviert ist.

Wie Sie die Signatur prüfen, steht unter Signatur verifizieren.

Versuche und Ergebnis

Tillor macht innerhalb des Schritts bis zu 5 Versuche, mit 1, 2, 4 und 8 Sekunden Wartezeit dazwischen. Ein Versuch gilt als erfolgreich bei einem 2xx-Status. Auch ein blockiertes Ziel, zum Beispiel eine interne Adresse, zählt als fehlgeschlagener Versuch.

  • Gelingt einer der Versuche, läuft der Flow über den Ausgang Erfolgreich weiter
  • Scheitern alle fünf, läuft der Flow über Fehlgeschlagen weiter. Die Nachricht wird danach im Hintergrund noch einmal versucht, nach dem Schema unter Zustellverhalten und Retries. Gelingt ein solcher späterer Versuch, taucht das nicht mehr in der Ausführung auf, denn diese ist dann bereits weitergelaufen

Existiert der Webhook nicht mehr oder ist er deaktiviert, läuft der Schritt nicht über Fehlgeschlagen. Die Ausführung stoppt dann mit dem Status Fehlgeschlagen.

API-Anfrage an eine eigene URL

Mit API-Anfrage und Senden an auf Eigene URL sendet eine Automatisierung eine HTTP-Anfrage an Ihren Server.

BestandteilVerhalten
MethodeGET, POST, PUT, PATCH oder DELETE
URLMuss mit https:// beginnen. Variablen werden kodiert eingesetzt
BodyJSON. Wird bei GET und DELETE nicht mitgesendet. Mit Body setzt Tillor Content-Type: application/json
HeaderFrei wählbar. Die Werte dürfen Variablen enthalten. Host, Content-Length, Transfer-Encoding und Connection werden ignoriert
ZielPrivate und interne Adressen werden abgelehnt, auch wenn ein gewöhnlicher Domainname darauf verweist
WeiterleitungenWerden nicht verfolgt. Eine 3xx-Antwort gilt als fehlgeschlagen
Timeout15 Sekunden

Keine Signatur

Anders als bei Webhook senden signiert Tillor diese Anfrage nicht. Möchten Sie prüfen, dass eine Anfrage von Ihrer Automatisierung stammt, setzen Sie ein Geheimnis in einen Header und prüfen Sie es auf Ihrer Seite. Header werden verschlüsselt gespeichert, ein Schlüssel oder Token darin ist also sicher.

Eine Antwort mit einem 2xx-Status läuft über Erfolgreich weiter, jeder andere Status über Fehlgeschlagen. Ist der Server nicht erreichbar oder überschreitet er das Timeout, stoppt die Ausführung mit dem Status Fehlgeschlagen.

API-Anfrage an die Tillor API

Mit Senden an auf Tillor API ruft die Automatisierung die API der eigenen Organisation auf. Sie geben nur einen Pfad an, zum Beispiel /tasks, und Tillor setzt diesen hinter /api/orgs/{orgId}. Ihre API-Referenz finden Sie unter OpenAPI.

  • Identität: Die Anfrage wird als Workflow-Benutzer der Organisation ausgeführt. Dieser hat alle Berechtigungen innerhalb dieser Organisation und nirgendwo sonst. Änderungen stehen also auf den Namen Workflow
  • Kein Schlüssel nötig: Tillor führt den Aufruf selbst aus, ohne API-Schlüssel und ohne über das Internet zu gehen
  • Pfad: Muss mit einem einzelnen / beginnen. //, .. und \ sind nicht erlaubt. Ein Query-String ist erlaubt, zum Beispiel /tasks?terrainId=…&limit=1. Variablen im Pfad werden kodiert eingesetzt
  • Blockiert: Die Pfade /automations und /automation-runs werden abgelehnt, auch mit Query-String, Großbuchstaben, einem abschließenden / oder Prozent-Kodierung. Eine Automatisierung kann keine Automatisierungen verwalten
  • Body: JSON, für POST, PUT und PATCH. Bei GET und DELETE wird er nicht mitgesendet
  • Auswahlmenü: Im Editor steht API-Endpunkt auswählen mit den Operationen aus der OpenAPI-Spezifikation. Interne Operationen sind nicht dabei. Wählen Sie eine aus, trägt Tillor Methode, Pfad und einen Beispiel-Body ein
  • Fehlschlagen: Eine 2xx-Antwort läuft über Erfolgreich weiter. Ein Fehlerstatus, auch ein 404 für einen nicht vorhandenen Pfad, läuft über Fehlgeschlagen

Die Antwort in späteren Schritten

Nach der Anfrage stehen diese Variablen zur Verfügung:

VariableInhalt
{response.status}Der HTTP-Statuscode
{response.body}Die ersten 4000 Zeichen der Antwort als Text
{response.data}Die Antwort als JSON. null, wenn es kein JSON ist oder länger als 100.000 Zeichen. Listen sprechen Sie mit einem Index an, zum Beispiel {response.data.items.0.id}

Eine zweite API-Anfrage im selben Flow ersetzt response. Die Variablen funktionieren wie bei Variablen und Vorlagen.

Der Aufbau eines Flows

Sie können Automatisierungen auch über die API anlegen und ändern. Die Operationen stehen in OpenAPI unter dem Tag automations. Lesen erfordert die Berechtigung automations:read, Anlegen und Ändern automations:write (oder alle Berechtigungen). Der Workflow-Benutzer selbst kann sie nie aufrufen. Es kann praktischer sein, einen Flow im Editor zu bauen und ihn als Beispiel zu lesen.

Eine neue Automatisierung ist immer deaktiviert. Das Aktivieren über enabled gelingt nicht, solange der Flow offene Probleme hat, und einen aktivierten Flow können Sie nicht mit Problemen speichern.

Die definition besteht aus Schritten (nodes), Linien (edges) und optional Anmerkungen (notes). Höchstens 100 Schritte, 200 Linien und 50 Anmerkungen.

{
  "nodes": [
    {
      "id": "trigger",
      "type": "trigger",
      "label": "",
      "position": { "x": 0, "y": 0 },
      "config": { "source": "event", "eventKey": "occupation:ended" }
    },
    {
      "id": "task",
      "type": "taskCreate",
      "label": "",
      "position": { "x": 0, "y": 190 },
      "config": { "title": "Controleer {occupation.terrain.name}", "priority": "HIGH" }
    }
  ],
  "edges": [
    { "id": "trigger:out:task", "source": "trigger", "target": "task", "sourceHandle": "out" }
  ],
  "notes": [
    {
      "id": "note_1",
      "text": "Maakt na elk vertrek een controletaak.",
      "position": { "x": 340, "y": 0 },
      "width": 240,
      "height": 140
    }
  ]
}

Eine Anmerkung (notes) ist eine Erklärung auf der Arbeitsfläche. Sie wird nie ausgeführt und hat keine Linien. text hat höchstens 2000 Zeichen, width und height sind in Pixeln.

Eine Linie hat einen sourceHandle: den Ausgang des Schritts, von dem sie ausgeht.

Schritt (type)Ausgänge (sourceHandle)
trigger, delay, waitUntilOpen, waitUntilClosed, taskCreate, taskSetStatus, taskSetPriority, taskUpdate, invoiceReminderSend, invoiceSend, invoicePrint, occupationExtendInvoice, staffNotify, commentCreate, inboxReply, inboxTag, customerUpdate, accessMethodCreate, accessMethodUpdate, accessMethodSendQr, accessPointControl, meterSwitch, nfcTagUpdate, deviceCommand, deviceDisplay, deviceSlideshow, controllerRelay, controllerCommandout
customerMessageSend, reservationSetStatus, invoiceBook, paymentLinkCreate, mandateRequest, mandateCollect, consumptionInvoiceout, skipped
conditionyes, no
switchDie id jedes Zweigs, plus default
openingHoursopen, closed
throttlepass, blocked
taskFind, documentFind, recordLookupfound, notFound
forEacheach, done
waitUntilmet, timeout
waitForEventreceived, timeout
approvalapproved, rejected, timeout
webhookSend, httpRequestsuccess, failed

Jede Aktion außer webhookSend und httpRequest erhält einen zusätzlichen Ausgang error, sobald continueOnError in der config auf true steht. Ohne diese Einstellung stoppt eine fehlgeschlagene Aktion die Ausführung. Mit dieser Einstellung läuft der Flow über error weiter, mit {error.message} und {error.step} als Variablen für die folgenden Schritte. Der Ausgang skipped wird verwendet, wenn ein Schritt nichts zu tun hatte, und out ist dann der gewöhnliche Ausgang.

Bei forEach startet der Ausgang each pro Element eine eigene Ausführung für die folgenden Schritte, und der Ausgang done ist der gewöhnliche Fortsetzungsweg des Flows selbst.

Ein Ausgang darf zu mehreren Schritten führen. Die Ausführung läuft selbst mit der ersten Linie weiter und startet für jede weitere Linie eine eigene Ausführung mit denselben Daten, die parallel läuft (wie der Ausgang each von forEach). Linien, die einen Kreis bilden, werden im Editor abgelehnt. Ein Flow hat genau einen trigger.

Einstellungen pro Schritt

Die Felder unter config sind die Felder aus dem Editor. Textfelder akzeptieren Variablen in geschweiften Klammern.

SchrittFelder in config
triggersource (event, webhook, invoiceOverdue, dateReached, daily oder cron), webhookVersion (bei webhook: Text, erhöhen Sie ihn, um die Adresse zu ersetzen), eventKey, date (bei dateReached: ein Pfad record.veld zu einer DateTime-Spalte eines Modells, das ein Ereignis vollständig mitsendet, wie reservation.checkIn oder contact.birthday, oder zu einem deklarierten Datumsschlüssel in einer JSON-Spalte, wie document.userMetadata.insuranceExpiryDate; alte Namen wie reservationCheckIn funktionieren weiter), dateOffset ({ "amount", "unit" }), dateDirection (before oder after), dateTime (exact: die Uhrzeit im Datum, oder fixed: der Kalendertag des Datums in der Zeitzone der Organisation, um dateHour und dateMinute, Text wie "9" und "0"; die Verschiebung zählt auf der Uhr, also über Sommer- und Winterzeit hinweg), repeatYearly (boolean: nur Tag und Monat zählen, jedes Jahr), hour und minute (Text, zum Beispiel "8" und "0", Minute 0 bis einschließlich 59), cron (fünf Felder; der Wochentag darf 1#2 oder 1L sein, ein sechstes Feld W2:2026-10-05 wiederholt alle zwei Wochen), conditions, oncePerRecord (boolean)
conditionconditions
switchfield (ein Variablenpfad ohne geschweifte Klammern), cases: eine Liste von { "id", "key", "value" } mit key als Name des Zweigs und value als Wert, dem das Feld gleich sein muss. Höchstens 8 Zweige
delaymode (duration oder untilDate), duration und offset als { "amount", "unit" } mit unit ist seconds, minutes, hours, days oder weeks, dateField (Variablenpfad), direction (before oder after)
taskCreatetitle, description, assigneeIds, labelIds, assignActor, priority (LOW, MEDIUM, HIGH oder URGENT), viewId, laneId, subtasks (eine pro Zeile), dueIn ({ "amount", "unit" }), linkRecords
taskSetStatustaskId, status (PENDING, IN_PROGRESS, WAITING oder COMPLETED)
taskFindtitle (exakter Titel), linkedToRecords, onlyOpen, onlyTopLevel (booleans)
documentFindcustomerId (Template), documentType (INSURANCE_POLICY, INSURANCE_PAYMENT_PROOF, IDENTITY_CARD, SEPA_MANDATE, OTHER oder leer), onlyActive, onlyValid (booleans). Ergebnis unter foundDocument
documentUpdatedocumentId (Template), documentType (leer behält den Typ), status (ACTIVE, ARCHIVED oder leer)
taskSetPrioritytaskId, mode (raise, lower oder set), priority (bei set), maxPriority (bei raise)
taskUpdatetaskId, title, assigneeIds, assignActor, assigneeMode (add oder replace), labelIds, dueIn ({ "amount", "unit" } mit unit ist minutes, hours, days oder weeks)
invoiceReminderSend, invoiceSend, invoiceBookinvoiceId
invoicePrintinvoiceId, printer (a4, pos oder tablet)
paymentLinkCreateinvoiceId, method (any, BANCONTACT, IDEAL, CREDITCARD oder PAYCONIQ)
mandateRequestcustomerId, mode (request oder reminder)
mandateCollectinvoiceId, delayDays (Text, Standard "0", höchstens 7)
consumptionInvoicecustomerId, sendEmail, sendSms
occupationExtendInvoiceoccupationId, includeConsumption
customerMessageSendcustomerId, subject, body, sendEmail, sendSms, sendWhatsApp
staffNotifyuserIds, notifyActor, title, body, sendPush, sendEmail
commentCreatecontent, target (event oder task), taskId (bei task)
inboxReplythreadId, body, keepAssistant
inboxTagthreadId, tagIds, archive
customerUpdatecustomerId, status (keep, DEFAULT, PREFERRED, VIP, WARNING oder BLACKLISTED), notes
reservationSetStatusreservationId, action (checkIn, checkOut oder cancel)
accessMethodCreatecustomerId, type (QR_CODE, LPR, PIN_CODE oder NFC), value, periodFrom, periodTo (Variablen mit einem Datum, leer ist keine Grenze)
accessMethodUpdatescope (one oder customer), accessMethodId (bei one), customerId (bei customer), status (keep, ACTIVE, SOFT_BLOCKED, BLOCKED oder INACTIVE), periodTo
accessMethodSendQraccessMethodId, sendEmail, sendSms, sendWhatsApp, print (none, label oder thermal)
accessPointControlaccessPointId, action (open oder close)
meterSwitchtarget (terrain oder meter), terrainId (bei terrain), meterId (bei meter), state (on oder off)
nfcTagUpdatecustomerId, action (block, unblock, topUp oder lowBalance), amount (bei topUp, in Euro pro Tag)
deviceCommanddeviceId, command (wake, sleep, reload, identify, testSound oder playSound), url (bei playSound: der Pfad eines hochgeladenen Tons, wie der Editor ihn einträgt, oder ein https-Link zu einer mp3-, wav- oder m4a-Datei)
deviceDisplaykind (pdf oder image), url (https-Link). Erscheint auf jedem Tablet, das als Display eingerichtet ist, etwa ein Rechnungs-PDF
controllerRelaytarget (controller oder event: der Controller des Ereignisses controller:input:changed, das den Flow gestartet hat), controllerId (bei controller), relay (Text "1" bis "6"), action (pulse, on oder off), durationSeconds (bei pulse, Text, 0.001 bis 3600 mit Dezimalen wie "0.5"; das Relais fällt von selbst wieder ab)
controllerCommandtarget und controllerId wie bei controllerRelay, command (reboot, rebootExtension, otaUpdate, forceOtaUpdate, extensionOtaUpdate oder refreshSettings)
deviceSlideshowscope (displays oder device), mode (screensaver oder background), source (feed oder urls). Bei feed: itemsPath, imageField, optional Filter- und Sortierfelder
openingHours, waitUntilOpen, waitUntilClosedKeine Felder
throttlewindow ({ "amount", "unit" } mit unit ist minutes, hours, days oder weeks), key (leer ist pro Datensatz, der den Flow gestartet hat)
recordLookupmodel (Customer, Reservation, Occupation, Invoice, Payment, Terrain, Task, Document, AccessMethod, NfcTag, Meter, InboxThread oder InboxMessage), recordId. Das Ergebnis steht unter found plus dem Modell, wie foundCustomer
forEachsource (customerAccessMethods, customerNfcTags, customerOpenInvoices, customerUpcomingReservations, customerOccupations, customerDocuments (nur ACTIVE) oder terrainMeters), parentId (ID des Kunden oder des Geländes). Höchstens 100 Elemente, das Element steht unter item
waitUntilconditions, interval und timeout ({ "amount", "unit" } mit unit ist minutes, hours, days oder weeks; das Intervall beträgt mindestens 5 Minuten)
waitForEventeventKey, sameRecord (boolean), timeout ({ "amount", "unit" })
approvaltitle, description, assigneeIds, timeout ({ "amount", "unit" }). Die Aufgabe steht unter approvalTask.id
Jede Aktion außer webhookSend und httpRequestcontinueOnError (boolean)
webhookSendwebhookId, event, payload (JSON als Text)
httpRequesttarget (tillor oder custom), method, path (bei tillor), url (bei custom), headers (Liste von { "id", "key", "value" }), body (JSON als Text)

conditions hat die Form { "match": "all" oder "any", "rules": [...] }. Jede Regel ist { "id", "field", "operator", "value", "values" }. operator ist is, isNot, contains, greaterThan, lessThan, isOneOf, isEmpty oder isNotEmpty. values verwenden Sie nur bei isOneOf. Eine leere Liste von Regeln lässt alles durch.

Eine Automatisierung mit einem Webhook starten

Eine Automatisierung mit dem Trigger webhook startet bei einem POST an ihre eigene Adresse:

curl -X POST "https://tillor.eu/api/orgs/org_abc123/automation-hooks/aut_xxx/<token>?bron=website" \
  -H "Content-Type: application/json" \
  -d '{"email":"jan@voorbeeld.nl","aankomst":"2026-07-14"}'
  • Die vollständige Adresse steht im Editor beim Trigger, oder über GET /automations/{id}/webhook-url (mit automations:read). Das Token ist das Geheimnis; ein Header zur Authentifizierung ist nicht nötig
  • Der JSON-Body wird zur Variable body, der Query-String zu query und der Zeitpunkt zu receivedAt
  • Antwort 200 mit { "accepted": true }, sobald die Ausführung gestartet ist. Eine falsche, ersetzte oder deaktivierte Adresse ergibt 404, ein Body über 100 KB ergibt 400
  • Viele Aufrufe kurz hintereinander werden nicht abgelehnt: Jeder gültige Aufruf startet eine Ausführung. Verwenden Sie Wiederholungen ignorieren beim Trigger, wenn derselbe Aufruf zweimal eintreffen kann, siehe Wiederholungen ignorieren

Eine Automatisierung kann ihren eigenen Webhook nicht über eine API-Anfrage an die Tillor API aufrufen.

Eine Entscheidung über die API treffen

Die Aufgabe eines Schritts Um eine Entscheidung bitten hat eine Aktion pro Option, die Sie im Schritt eingestellt haben. Rufen Sie die Aufgabe ab, um die actions mit ihrer id zu sehen, und wählen Sie eine mit POST /tasks/{id}/actions/{actionId}/choose. Verlangt die Option eine Notiz, senden Sie diese als { "note": "..." } mit. Die Wahl ist endgültig: Sie schließt die Aufgabe ab und setzt die Automatisierung über den Ausgang dieser Option fort. Zugewiesene Kollegen (auch über eine Gruppe) und Administratoren dürfen wählen. Details finden Sie in der OpenAPI.

Weiterlesen

War diese Seite hilfreich?

Auf dieser Seite