Automatiseringen

Wat je eigen systeem ontvangt van een automatisering, het API-verzoek als Workflow-gebruiker en de opbouw van een flow

Laatst bijgewerkt op

Automatiseringen laten Tillor zelf acties uitvoeren, zoals taken aanmaken of je systeem aanroepen. De gebruikersuitleg staat bij Automatiseringen. Deze pagina beschrijft wat een integrator ziet: het bericht van de stap Webhook versturen, het API-verzoek naar een eigen URL of naar de Tillor API, en hoe een flow is opgebouwd als je hem via de API beheert.

Webhook versturen

De stap Webhook versturen levert een eigen bericht af bij een van de webhooks van de organisatie. Het is dezelfde bezorging als bij gewone webhook-events, met dezelfde handtekening.

Het bericht

De stap doet een POST met Content-Type: application/json en deze headers:

HeaderInhoud
X-Webhook-Event-IDEen unieke ID voor deze levering. Bij nieuwe pogingen blijft de waarde gelijk, dus je kunt erop ontdubbelen
X-Webhook-Signaturesha256=<hex>, de HMAC-SHA256 van de body met de signing secret van de webhook

De body heeft dezelfde envelop als de webhook-payload:

{
  "event": "automation.invoice_unpaid",
  "data": {
    "invoice": "2026-0042",
    "amountOutstanding": 125.5
  },
  "timestamp": 1735689600000,
  "traceId": "0b0f7c0e-5d3c-4c1e-9b8a-7f1e2a3b4c5d",
  "triggeredBy": null
}
VeldBeschrijving
eventDe Naam van de gebeurtenis die je in de stap hebt ingevuld. Elke tekst is toegestaan, de naam hoeft niet in de lijst met event-keys te staan
dataDe Payload uit de stap, nadat de variabelen zijn ingevuld, als JSON
timestampUnix-tijd in milliseconden van de levering
traceIdEen willekeurige UUID per levering. Anders dan bij events uit het systeem is dit geen trace-id van een Tillor-actie
triggeredByAltijd null

Er staat geen spanId in. De webhook hoeft niet op een event-key geabonneerd te zijn: een bericht uit een automatisering wordt altijd afgeleverd bij het gekozen endpoint, zolang dat bestaat en ingeschakeld is.

Hoe je de handtekening controleert, staat bij Handtekening verifiëren.

Pogingen en uitkomst

Tillor doet binnen de stap tot 5 pogingen, met 1, 2, 4 en 8 seconden wachten ertussen. Een poging telt als geslaagd bij een 2xx-status. Ook een doel dat wordt geblokkeerd, bijvoorbeeld een intern adres, telt als mislukte poging.

  • Slaagt een van de pogingen, dan gaat de flow verder via de uitgang Gelukt
  • Slagen ze alle vijf niet, dan gaat de flow verder via Mislukt. Het bericht wordt daarna nog op de achtergrond opnieuw geprobeerd volgens het schema bij Leveringsgedrag en retries. Slaagt zo'n latere poging, dan komt dat niet meer terug in de uitvoering, want die is dan al verdergegaan

Bestaat de webhook niet meer of is hij uitgeschakeld, dan loopt de stap niet via Mislukt. De uitvoering stopt dan met de status Mislukt.

API-verzoek naar een eigen URL

Met API-verzoek en Versturen naar op Eigen URL stuurt een automatisering een HTTP-verzoek naar jouw server.

OnderdeelGedrag
MethodeGET, POST, PUT, PATCH of DELETE
URLMoet met https:// beginnen. Variabelen worden gecodeerd ingevuld
BodyJSON. Wordt bij GET en DELETE niet meegestuurd. Met body zet Tillor Content-Type: application/json
HeadersVrij te kiezen. De waarden mogen variabelen bevatten. Host, Content-Length, Transfer-Encoding en Connection worden genegeerd
DoelPrivé- en interne adressen worden geweigerd, ook als een gewone domeinnaam ernaar verwijst
OmleidingenWorden niet gevolgd. Een 3xx-antwoord telt als mislukt
Time-out15 seconden

Geen handtekening

Anders dan bij Webhook versturen ondertekent Tillor dit verzoek niet. Wil je controleren dat een verzoek van jouw automatisering komt, zet dan een geheim in een header en controleer dat aan jouw kant. Headers worden versleuteld opgeslagen, dus een sleutel of token daarin is veilig.

Een antwoord met een 2xx-status gaat verder via Gelukt, elke andere status via Mislukt. Is de server niet te bereiken, of overschrijdt hij de time-out, dan stopt de uitvoering met de status Mislukt.

API-verzoek naar de Tillor API

Met Versturen naar op Tillor API roept de automatisering de API van de eigen organisatie aan. Je geeft alleen een pad op, bijvoorbeeld /tasks, en Tillor plaatst dat achter /api/orgs/{orgId}. Je API-referentie staat op OpenAPI.

  • Identiteit: het verzoek wordt uitgevoerd als de Workflow-gebruiker van de organisatie. Die heeft alle permissies binnen die organisatie en nergens anders. Wijzigingen staan dus op naam van Workflow
  • Geen sleutel nodig: Tillor voert de aanroep zelf uit, zonder API-sleutel en zonder via het internet te gaan
  • Pad: moet met één / beginnen. //, .. en \ zijn niet toegestaan. Een query-string mag, bijvoorbeeld /tasks?terrainId=…&limit=1. Variabelen in het pad worden gecodeerd ingevuld
  • Geblokkeerd: de paden /automations en /automation-runs worden geweigerd, ook met een query-string, hoofdletters, een afsluitende / of procentcodering. Een automatisering kan geen automatiseringen beheren
  • Body: JSON, voor POST, PUT en PATCH. Bij GET en DELETE wordt hij niet meegestuurd
  • Keuzemenu: in de editor staat Kies een API-endpoint met de operaties uit de OpenAPI-specificatie. Interne operaties staan er niet bij. Kies je er een, dan vult Tillor methode, pad en een voorbeeld-body in
  • Mislukken: een 2xx-antwoord gaat verder via Gelukt. Een foutstatus, ook een 404 voor een pad dat niet bestaat, gaat via Mislukt

Het antwoord in latere stappen

Na het verzoek zijn deze variabelen beschikbaar:

VariabeleInhoud
{response.status}De HTTP-statuscode
{response.body}De eerste 4000 tekens van het antwoord als tekst
{response.data}Het antwoord als JSON. null als het geen JSON is, of als het langer is dan 100.000 tekens. Lijsten adresseer je met een index, bijvoorbeeld {response.data.items.0.id}

Een tweede API-verzoek in dezelfde flow vervangt response. De variabelen werken zoals bij Variabelen en sjablonen.

De opbouw van een flow

Je kunt automatiseringen ook via de API aanmaken en wijzigen. De operaties staan in OpenAPI onder de tag automations. Lezen vraagt de permissie automations:read, aanmaken en wijzigen automations:write (of alle permissies). De Workflow-gebruiker zelf kan ze nooit aanroepen. Het kan handiger zijn een flow in de editor te bouwen en hem als voorbeeld te lezen.

Een nieuwe automatisering is altijd uitgeschakeld. Inschakelen via enabled lukt niet zolang de flow open problemen heeft, en een ingeschakelde flow kun je niet opslaan met problemen.

De definition bestaat uit stappen (nodes), lijnen (edges) en optioneel opmerkingen (notes). Maximaal 100 stappen, 200 lijnen en 50 opmerkingen.

{
  "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
    }
  ]
}

Een opmerking (notes) is uitleg op het canvas. Ze wordt nooit uitgevoerd en heeft geen lijnen. text is maximaal 2000 tekens, width en height zijn in pixels.

Een lijn heeft een sourceHandle: de uitgang van de stap waar hij vandaan komt.

Stap (type)Uitgangen (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, deviceSlideshowout
customerMessageSend, reservationSetStatus, invoiceBook, paymentLinkCreate, mandateRequest, mandateCollect, consumptionInvoiceout, skipped
conditionyes, no
switchDe id van elke tak, plus default
openingHoursopen, closed
throttlepass, blocked
taskFind, documentFind, recordLookupfound, notFound
forEacheach, done
waitUntilmet, timeout
waitForEventreceived, timeout
approvalapproved, rejected, timeout
webhookSend, httpRequestsuccess, failed

Elke actie behalve webhookSend en httpRequest krijgt er een extra uitgang error bij zodra continueOnError in de config op true staat. Zonder die instelling stopt een mislukte actie de uitvoering. Met die instelling gaat de flow verder via error, met {error.message} en {error.step} als variabelen voor de stappen erna. De uitgang skipped wordt gebruikt als een stap niets te doen had, en out is dan de gewone uitgang.

Bij forEach start de uitgang each per item een eigen uitvoering voor de stappen erna, en de uitgang done is de gewone vervolgweg van de flow zelf.

Een uitgang leidt naar maximaal één stap, en lijnen die een kring vormen worden geweigerd in de editor. Een flow heeft precies één trigger.

Instellingen per stap

De velden onder config zijn de velden uit de editor. Tekstvelden accepteren variabelen tussen accolades.

StapVelden in config
triggersource (event, webhook, invoiceOverdue, dateReached, daily of cron), webhookVersion (bij webhook: tekst, verhoog om het adres te vervangen), eventKey, date (bij dateReached: een pad record.veld naar een DateTime-kolom van een model dat een gebeurtenis volledig meestuurt, zoals reservation.checkIn of contact.birthday, of naar een gedeclareerde datumsleutel in een JSON-kolom, zoals document.userMetadata.insuranceExpiryDate; oude namen zoals reservationCheckIn blijven werken), dateOffset ({ "amount", "unit" }), dateDirection (before of after), dateTime (exact: het uur in de datum, of fixed: de kalenderdag van de datum in de tijdzone van de organisatie, om dateHour en dateMinute, tekst zoals "9" en "0"; de verschuiving telt op de klok, dus door zomer- en wintertijd heen), repeatYearly (boolean: alleen dag en maand tellen, elk jaar), hour en minute (tekst, bijvoorbeeld "8" en "0", minuut 0 tot en met 59), cron (vijf velden; weekdag mag 1#2 of 1L zijn, een zesde veld W2:2026-10-05 herhaalt om de twee weken), conditions, oncePerRecord (boolean)
conditionconditions
switchfield (een variabelepad zonder accolades), cases: een lijst van { "id", "key", "value" } met key als naam van de tak en value als waarde waaraan het veld moet gelijk zijn. Maximaal 8 takken
delaymode (duration of untilDate), duration en offset als { "amount", "unit" } met unit is seconds, minutes, hours, days of weeks, dateField (variabelepad), direction (before of after)
taskCreatetitle, description, assigneeIds, labelIds, assignActor, priority (LOW, MEDIUM, HIGH of URGENT), viewId, laneId, subtasks (één per regel), dueIn ({ "amount", "unit" }), linkRecords
taskSetStatustaskId, status (PENDING, IN_PROGRESS, WAITING of COMPLETED)
taskFindtitle (exacte titel), linkedToRecords, onlyOpen, onlyTopLevel (booleans)
documentFindcustomerId (template), documentType (INSURANCE_POLICY, INSURANCE_PAYMENT_PROOF, IDENTITY_CARD, SEPA_MANDATE, OTHER of leeg), onlyActive, onlyValid (booleans). Resultaat onder foundDocument
documentUpdatedocumentId (template), documentType (leeg houdt het type), status (ACTIVE, ARCHIVED of leeg)
taskSetPrioritytaskId, mode (raise, lower of set), priority (bij set), maxPriority (bij raise)
taskUpdatetaskId, title, assigneeIds, assignActor, assigneeMode (add of replace), labelIds, dueIn ({ "amount", "unit" } met unit is minutes, hours, days of weeks)
invoiceReminderSend, invoiceSend, invoiceBookinvoiceId
invoicePrintinvoiceId, printer (a4, pos of tablet)
paymentLinkCreateinvoiceId, method (any, BANCONTACT, IDEAL, CREDITCARD of PAYCONIQ)
mandateRequestcustomerId, mode (request of reminder)
mandateCollectinvoiceId, delayDays (tekst, standaard "0", hoogstens 7)
consumptionInvoicecustomerId, sendEmail, sendSms
occupationExtendInvoiceoccupationId, includeConsumption
customerMessageSendcustomerId, subject, body, sendEmail, sendSms, sendWhatsApp
staffNotifyuserIds, notifyActor, title, body, sendPush, sendEmail
commentCreatecontent, target (event of task), taskId (bij task)
inboxReplythreadId, body, keepAssistant
inboxTagthreadId, tagIds, archive
customerUpdatecustomerId, status (keep, DEFAULT, PREFERRED, VIP, WARNING of BLACKLISTED), notes
reservationSetStatusreservationId, action (checkIn, checkOut of cancel)
accessMethodCreatecustomerId, type (QR_CODE, LPR, PIN_CODE of NFC), value, periodFrom, periodTo (variabelen met een datum, leeg is geen limiet)
accessMethodUpdatescope (one of customer), accessMethodId (bij one), customerId (bij customer), status (keep, ACTIVE, SOFT_BLOCKED, BLOCKED of INACTIVE), periodTo
accessMethodSendQraccessMethodId, sendEmail, sendSms, sendWhatsApp, print (none, label of thermal)
accessPointControlaccessPointId, action (open of close)
meterSwitchtarget (terrain of meter), terrainId (bij terrain), meterId (bij meter), state (on of off)
nfcTagUpdatecustomerId, action (block, unblock, topUp of lowBalance), amount (bij topUp, in euro per tag)
deviceCommanddeviceId, command (wake, sleep, reload, identify of testSound)
deviceSlideshowscope (displays of device), mode (screensaver of background), source (feed of urls). Bij feed: itemsPath, imageField, optioneel filter- en sorteervelden
openingHours, waitUntilOpen, waitUntilClosedGeen velden
throttlewindow ({ "amount", "unit" } met unit is minutes, hours, days of weeks), key (leeg is per record dat de flow startte)
recordLookupmodel (Customer, Reservation, Occupation, Invoice, Payment, Terrain, Task, Document, AccessMethod, NfcTag, Meter, InboxThread of InboxMessage), recordId. Het resultaat staat onder found plus het model, zoals foundCustomer
forEachsource (customerAccessMethods, customerNfcTags, customerOpenInvoices, customerUpcomingReservations, customerOccupations, customerDocuments (alleen ACTIVE) of terrainMeters), parentId (id van de klant of het terrein). Hoogstens 100 items, het item staat onder item
waitUntilconditions, interval en timeout ({ "amount", "unit" } met unit is minutes, hours, days of weeks; het interval is minstens 5 minuten)
waitForEventeventKey, sameRecord (boolean), timeout ({ "amount", "unit" })
approvaltitle, description, assigneeIds, timeout ({ "amount", "unit" }). De taak staat onder approvalTask.id
Elke actie behalve webhookSend en httpRequestcontinueOnError (boolean)
webhookSendwebhookId, event, payload (JSON als tekst)
httpRequesttarget (tillor of custom), method, path (bij tillor), url (bij custom), headers (lijst van { "id", "key", "value" }), body (JSON als tekst)

conditions heeft de vorm { "match": "all" of "any", "rules": [...] }. Elke regel is { "id", "field", "operator", "value", "values" }. operator is is, isNot, contains, greaterThan, lessThan, isOneOf, isEmpty of isNotEmpty. values gebruik je alleen bij isOneOf. Een lege lijst met regels laat alles door.

Een automatisering starten met een webhook

Een automatisering met trigger webhook start bij een POST naar haar eigen adres:

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"}'
  • Het volledige adres staat in de editor bij de trigger, of via GET /automations/{id}/webhook-url (met automations:read). Het token is het geheim; een header voor authenticatie is niet nodig
  • De JSON-body wordt de variabele body, de querystring query, en het tijdstip receivedAt
  • Antwoord 200 met { "accepted": true } zodra de uitvoering gestart is. Een verkeerd, vervangen of uitgeschakeld adres geeft 404, een body boven 100 KB geeft 400
  • Per automatisering starten hoogstens 120 uitvoeringen per minuut; daarboven worden aanroepen genegeerd

Een automatisering kan haar eigen webhook niet aanroepen via een API-verzoek naar de Tillor API.

Goedkeuringen beslissen via de API

De taak van een stap Goedkeuring vragen beslis je met POST /automation-approvals/{taskId} en de body { "decision": "approved" } of { "decision": "rejected" }. Toegewezen collega's en beheerders mogen beslissen. Zie de OpenAPI voor de details.

Meer lezen

Was deze pagina nuttig?

Op deze pagina