AssignContactUserActionAdds a user to the contact's responsible users (the "Verantwortliche" on the contact).
Meant for rules like "whoever enters the potential becomes responsible for the customer": run it after an edit-contact trigger and a compare on the field that changed. Without configuration it adds the user whose save ran the workflow.
Configuration:
user_id — who to add. Defaults to ###current_user###, the signed-in user. A run without a signed-in user (a time schedule, a queued step) adds nobody.Returns the contact id, the user id and whether a new assignment was made.
{}
Add a fixed user instead of the one who saved:
{"user_id": 4400}
"Whoever enters the potential becomes responsible" — the potential lives in field i_1 of each franchise partner's contact group, so one condition covers all of them:
edit-contactcompare — [{"action": "changed", "property": "custom_fields_*.i_1"}]assign-contact-user — {}ChangeDataActionThis action extracts a specific property from the input data object and sets it as the new return value.
Useful when you want to isolate and pass on a nested value instead of the full data object.
Returns only the value of data->{target}.
[
'target' => 'propertyName'
]
CompareActionThis workflow action evaluates one or more conditions against a model's properties.
Each condition can check for equality, inequality, string prefixes, or field changes.
You can also use dot-notation to access related model properties (e.g., user.name).
Useful for branching logic within workflows based on the current model state.
Supported condition actions: equals, notEquals, startsWith, changed.
changed checks the trigger's changes rather than the record. On edit-contact these include the contact's custom fields, keyed custom_fields_<contact group>.<column>; a * in the property matches any run of characters, so custom_fields_*.i_1 is field i_1 in any contact group.
[
[
'property' => 'status',
'action' => 'equals',
'value' => 'open'
],
[
'property' => 'user.name',
'action' => 'startsWith',
'value' => 'Jack'
]
];
CreateActionThis workflow action creates a new record using the configured key-value pairs.
The target model class must be provided when initializing this action.
Each configuration value is processed through the placeholder system for dynamic replacements.
This allows template values like ###user_email### to be resolved at runtime.
Returns true if the object was successfully created, and tracks all saved attributes as changes.
[
'name' => 'Example Name',
'email' => 'newuser@example.com',
'role' => 'member'
];
CreateBsapiCustomerActionOpens a debtor account for the contact in KFV's Sage accounting (through BSAPI) and stores its number as the contact's customer number (bNR). The number is the next free one of KFV's debtor range in Sage (D000900364 and up).
Meant to run right after a new-contact trigger. Sends the person's name (or the company's, when there is no person), the e-mail and the birthday.
Needs BSAPI_BASE_URL and BSAPI_TOKEN in the environment; without them the step fails.
Returns the contact id and the customer number. Follows the error branch when Sage hands out no number, or when BSAPI rejects the address or cannot be reached.
{}
new-contactcreate-bsapi-customer — {}NotifyVehicleInspectionActionSends the feedback on a vehicle inspection (WUMS): the inspection photos and the recorded damages, mailed to the contact that raised the ticket, the workshop it is addressed to, and the raising contact's main contact if it has one.
Meant to run a step or two after a new task trigger, behind a sleep step: the app creates the ticket first and uploads the photos in the background, so the mail has to wait for them.
Takes no configuration. Returns the ticket id, the notified contact ids and the number of photos and damages.
{}
A typical workflow for a fleet tenant:
new-taskcompare — [{"action": "equals", "property": "task_category_id", "value": 3}]sleep — {"sleep_duration": 120, "queue_timeout": 300}notify-vehicle-inspection — {}SendEmailActionThis action sends an email using 1tool-style placeholders (starting with three hashes: ###). It uses the currently logged-in user's email address as the sender.
to, subject, text) are missing,
the email will be skipped and not sent.
Attachments:
Set attachments_key to a relationship name or dotted data path on the workflow's context model; the file(s) found there are attached to the email. In a proposal context, attachments_key: "files" attaches the proposal's files (Proposal::files). The resolved value must be a File / Attachable (or a collection/array of them). Note the key is attachments_key, not attachments. Similarly, to, cc, and bcc are resolved against the context model when their value matches a property/path, otherwise used verbatim.
Returns:
A boolean: true if the email was sent successfully, false otherwise.
[
'to' => 'Recipient email address',
'subject' => 'Email subject line',
'text' => 'Main content/body of the email',
'cc' => 'Optional CC address (or data path on the context model)',
'bcc' => 'Optional BCC address (or data path on the context model)',
'attachments_key' => 'files', // Optional: relationship/data path on the context model; its File(s) are attached
'email_setting_id' => 'Optional EmailSetting id to send through',
];
SendHttpRequestActionThis action sends an HTTP request using the provided configuration options.
Useful when you want to trigger external APIs or webhooks as part of a workflow step, passing in custom headers, body content, and query parameters.
The HTTP response (status, headers, and body) will be stored in $this->returnValue for downstream use.
Supports:
GET)headers)body)query)[
'url' => 'https://api.example.com/send',
'method' => 'POST',
'headers' => [
'Authorization' => 'Bearer secret_token',
'Content-Type' => 'application/json',
],
'body' => [
'id' => 'data.id',
'email' => 'data.email',
],
'query' => [
'debug' => 'true'
]
]
SendInvoiceActionThis workflow action dispatches an invoice generation job for the specified user.
It uses the given userId and the current data->id (usually the invoice ID) to trigger the process.
The job runs asynchronously using Laravel's job queue system.
Returns a boolean: true if the job was successfully dispatched, false if the config was invalid.
[
'userId' => 'ID of the user for whom the invoice should be dispatched',
];
SleepActionThis workflow action delays execution for a number of seconds specified in the configuration.
It is useful for debugging, simulating delays, or testing time-based behavior in workflows.
Returns the original data unchanged after the sleep duration.
[
'sleep_duration' => 5
]
TranslateProposalActionTranslateProposalPlaceholdersActionUpdateActionThis workflow action updates fields on the given model using key-value pairs from the configuration.
Nested relationships can be updated by using dot notation (e.g., profile.bio).
Each value is processed through the configuration replacement system to support dynamic inputs.
Returns the updated model and tracks changed values internally.
[
'name' => 'New name value',
'email' => 'new@email.com',
'profile.bio' => 'Updated biography text'
]
UseChatGptActionThis action sends a message to OpenAI's ChatGPT API and returns the AI-generated response.
Useful when you want to automate replies, transform content, or generate text using AI within a workflow.
The action includes a preset system instruction to ensure ChatGPT behaves like a task executor:
"You're an assistant. Your role is to execute tasks exactly as requested, returning only the pure result without any suggestions, explanations, or additional help. Strip everything down to just what is asked—nothing more, nothing less."
The raw response is stored in $this->returnValue['content'].
[
'api_key' => 'sk-xxxx',
'query' => 'Translate this text to German: Hello, how are you?',
'model' => 'gpt-4o' // Optional, defaults to 'gpt-4o'
]