Skip to content

Triggers

For developers who connect a client to OpenBot or extend its server. The examples need the access stated on this page. Start with the developer manual.

A trigger gives one task with one prompt to one Bot. It fires on a schedule, from a webhook, or both. It does nothing else: the Bot decides how to do the work. It can plan first, keep a todo list, and give work to other Bots. When the task ends, its result goes to your Chat with the Bot.


Terminal window
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"prompt":"Check the open issues and sum them up.","schedule":{"cron":"0 9 * * 1-5","timeZone":"Europe/Berlin"}}' \
https://api.example.com/v1/triggers
Field What it does
prompt The task.
bot Optional. The Bot that does the work. Without it, your default Bot does it.
schedule Optional. When the trigger fires by itself.
shared Optional. true makes a shared trigger that belongs to the organization.
enabled Optional. false keeps the trigger from firing. The default is true.

The answer is 201 with the trigger. It has nextRunAt, the next time that the schedule fires, and lastFiredAt.

GET /v1/triggers lists your triggers and the shared ones. GET, PATCH and DELETE /v1/triggers/:triggerId read, change and delete one. A change needs expected, the revision that you read. An old revision returns 409 with TriggerConflict.


Each firing gives the task to the Bot as a delegation. The work runs in a new task Chat of the Bot. Its first input is the prompt, from “a trigger”. The delegation has trigger with the ID of the trigger.

When the work ends, its result goes as a notice to the direct Chat of the actor with the Bot. OpenBot makes that Chat when it does not exist yet. So the Bot reads the result there, and it can tell the actor about it or go on with the work. The audit log records trigger.fired with the ID of the delegation in details.delegation.

To find the work of a trigger, read GET /v1/chats/:chatId/delegations for that direct Chat, or list the task Chats of the Bot with GET /v1/chats?kind=task&bot=<id>.


A schedule has a cron text with five fields, such as 0 9 * * 1-5 for 9:00 on work days. timeZone is an IANA time zone, such as Europe/Berlin. Without it, the time zone is UTC. A cron text that is not valid returns 400 with TriggerInvalid. A cron text that never fires, such as 0 0 30 2 * (February 30), returns the same error.

The trigger has an executionId for its saved timer, or null without a timer. The timer survives a restart. An overdue timer starts one task, then moves to the next time. The task, audit entry and next timer commit in one transaction. Changing the trigger replaces its timer. It does not stop tasks already started. A failed timer keeps its error ID. Fix the cause and change the trigger to retry.


PUT /v1/triggers/:triggerId/webhook makes a webhook secret. OpenBot shows it only once:

{
"url": "https://api.example.com/v1/hooks/triggers/trg_4c1e...",
"secret": "otg_..."
}

Another system fires the trigger with the secret:

Terminal window
curl -H "Authorization: Bearer $WEBHOOK_SECRET" \
-H "Idempotency-Key: issue-42" \
-H "Content-Type: application/json" \
-d '{"issue": 42}' \
https://api.example.com/v1/hooks/triggers/trg_4c1e...

The answer is 202 with delegation, executionId, commandKey and sequence. Send a stable Idempotency-Key for each call. Reuse it and the same body after a lost reply. A different body with the same key returns 409 ExecutionKeyConflict. Use the execution API to read events and cancel work. The SDK Triggers.fire prepares one key; keep its returned command and retry command.send. The JSON body goes to the Bot with the task. OpenBot marks it as data from another system, not as an instruction. A wrong secret, a trigger without a webhook, or a disabled trigger returns 401 with TriggerHookDenied.

A new PUT makes a new secret, and the old one stops working. DELETE /v1/triggers/:triggerId/webhook removes the webhook.

If the actor can no longer give work to the Bot, or the Bot is archived, the webhook returns 403 ExecutionForbidden. An execution storage failure returns 503 ExecutionUnavailable with a safe error ID.


The work of a trigger is for its actor: the last member who created or changed the trigger or its webhook. So a change makes you the actor. The task Chat belongs to the actor, and the result goes to the Chat of the actor. The actor must be able to give work to the Bot. If the actor cannot do that any more, the trigger does not fire.

The saved caller includes the original user token and its limits. Each step checks current rights. A revoked token cannot start or resume work. Prompts and webhook data are encrypted in saved records. The Bot asks for new capabilities with requests. The requests go to the actor.


After a data upgrade, a trigger can have needsAuthorization: true. Its prompt, schedule, next time and enabled setting stay, but neither a timer nor a webhook can start work. Save a change with current rights to set a new caller and clear this state. The new timer uses the next time after that change. Old work stays in its saved state; it does not run again as the new caller.

Action on Trigger What it allows
read Read triggers: their schedules and webhooks.
write Create, change and delete triggers, and set their webhook secrets.

The path of your own triggers is org / <org> / user / <you> / trigger / <id>. A shared trigger has owner: { "_tag": "Organization" }. A personal trigger has owner: { "_tag": "Member", "userId": "<member id>" }. Every member can read the shared triggers. Administrators can change them. The list only has the triggers that you may read. See Permissions.