Update a mail trigger
const url = 'https://example.com/v1/mail-triggers/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0';const options = { method: 'PATCH', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"flowId":"example","flowVersion":"example","agentId":"example","agentVersion":"example","config":{"mailbox":{"app":"google","as":"company"},"folder":"example","pollSeconds":1,"runsPerHour":1},"label":"example","toolsAllowedUnattended":["example"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://example.com/v1/mail-triggers/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0 \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "flowId": "example", "flowVersion": "example", "agentId": "example", "agentVersion": "example", "config": { "mailbox": { "app": "google", "as": "company" }, "folder": "example", "pollSeconds": 1, "runsPerHour": 1 }, "label": "example", "toolsAllowedUnattended": [ "example" ] }'Changes what it runs (which needs execute on the new target, and must be the project’s to reach), its mailbox (replaced whole), folder, pace or label (null clears it). To watch the inbox again, name it as the folder: INBOX on Gmail, inbox on Outlook. No edit moves the owner: a personal trigger’s change is its owner’s (who needs write on the project) or a project admin’s, a shared one’s is a project admin’s, and the company’s mailbox, before or after, takes a project admin. Only a personal trigger’s owner chooses what it reads from a person’s mailbox, another of their mailboxes or another folder: anyone else, a project admin included, gets a 403, and may take the trigger over to watch their own. A project admin’s other changes to a person’s trigger, such as what it runs, its pace or a move to the company’s mailbox, keep its owner, so its runs go on acting as that person, and they’re audited as trigger-changed-for-owner, naming the trigger’s version after each. Since no edit moves the owner, with an authorization store a new target (another flow or agent) must be one the owner can run, a person or a service account, else 409 trigger-owner-cannot-run-target; that’s not checked when the caller is the owner, nor for an owner that was unregistered or removed. toolsAllowedUnattended replaces the list ([] clears it; absent keeps it, a new version too), and a new target or mailbox while it lists any must name it again. Naming a list takes admin on the project; a personal trigger’s owner may name [] with their own new target or mailbox.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”TriggerId — the trigger id (a UUID).
Header Parameters
Section titled “Header Parameters”Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5). A request whose key store can’t be read before it runs is answered 503 idempotency-store-unavailable with Retry-After: nothing ran, so retry with the same key (from 0.3.0).
Request Bodyrequired
Section titled “Request Bodyrequired”Change what it runs (the target fields, as at registration, which also needs execute on the new target), its mailbox (replaced whole), folder, pace or label. A personal trigger’s change is its owner’s or a project admin’s; a shared one’s, a project admin’s; and the company’s mailbox, before or after, takes a project admin. The owner stays.
object
Run a flow (with flowVersion).
Run an agent (instead of a flow): at agentVersion, else its pinned version.
A mail trigger’s mailbox, folder or pace, to change. An absent field keeps its value.
object
The mailbox a mail trigger reads: its app (google: Gmail; microsoft: Outlook) and whose it is (company: the company’s mailbox, through the company’s connection of that app; person: the trigger owner’s own, through their connection).
object
The Gmail label id, or the Outlook folder id or well-known name, it watches from now. Absent: it keeps its folder, unless mailbox changes; then it watches the new mailbox’s inbox. To watch the inbox again, name it: INBOX in Gmail, inbox in Outlook.
How often it looks for new mail, in seconds (default 60).
The most runs its mail starts in an hour (default 60). Past it, a mail’s fire is refused (detail starts over-limit:), and that mail doesn’t run later.
Replaces the list ([] clears it; absent keeps it). Naming it takes admin on the trigger’s project. A new target (not just a version) or another mailbox while it lists any must name it again, as it is or []. Each tool by its id, with no wildcard or pattern, and only tools this trigger’s flow or agent calls. It lifts only that wait: the tenant’s approval rules, the agent’s own rules, the permission check (as the trigger’s owner) and the tool’s own limits all still apply.
Responses
Section titled “Responses”Updated mail trigger.
A mail trigger: each new mail in its mailbox’s folder starts a run of its agent or flow, with the mail as the run’s input, as its owner. In such a run, every call that changes something, or uses the run’s own mailbox, waits for a person’s yes unless the trigger lists it (toolsAllowedUnattended).
object
Run a flow (with flowVersion).
Run an agent (instead of a flow): at agentVersion, else its pinned version.
The trigger’s project: its runs are this project’s.
Who its runs act as, with their connections. A service account owns a shared trigger, on the company’s mailbox: one named with runAsServiceAccountId, or the project’s own (runAsProject, isProjectAccount). A person owns a personal one: every trigger on a person’s mailbox, and one on the company’s mailbox registered without either. No edit moves it; only a take-over (POST …/owner) does.
object
The owner’s name at the time of the response: the person’s display name, or the service account’s name. Absent when it can’t be read (no directory, a removed account) and from a runtime before Kindgi 0.1.6: show the id then.
Set when the owner is the trigger’s project’s own service account (runAsProject): the trigger is shared, and runs as the project. Show it as “This project”. Absent otherwise.
The mailbox a mail trigger reads: its app (google: Gmail; microsoft: Outlook) and whose it is (company: the company’s mailbox, through the company’s connection of that app; person: the trigger owner’s own, through their connection).
object
The Gmail label id, or the Outlook folder id or well-known name, it watches. Absent: the inbox.
How often it looks for new mail, in seconds (default 60).
The most runs its mail starts in an hour (default 60). Past it, a mail’s fire is refused (detail starts over-limit:), and that mail doesn’t run later.
Lifecycle status. Only active triggers fire. Tombstoned rows are excluded from every read path.
Why it isn’t polling as it should: connection-missing (the mailbox’s connection is gone or lapsed; polls go on, and work again once it’s back), owner-refused (its owner was removed or may no longer run the target; polls go on and read nothing until that changes or an admin takes it over), or why the runtime paused it.
The trigger’s newest version (GET …/versions): one more for each change to what it runs, when, as whom or with what. Absent until its first version.
The mailbox’s account at its last poll: the connection’s account id and its label (the address). Absent before its first poll.
object
When it last polled the mailbox and got an answer.
The tools whose calls in this trigger’s runs don’t wait for a person’s yes, though a run a mail started asks for one for every call that changes something or uses its mailbox. Absent: none. Each tool by its id, with no wildcard or pattern, and only tools this trigger’s flow or agent calls. It lifts only that wait: the tenant’s approval rules, the agent’s own rules, the permission check (as the trigger’s owner) and the tool’s own limits all still apply.
Example
{ "owner": { "kind": "user", "isProjectAccount": true }, "mailbox": { "app": "google", "as": "company" }, "status": "active"}A body that fails validation (bad-input): runAsServiceAccountId or runAsProject (the owner changes only by POST …/owner), a person’s mailbox for a shared trigger, or a new target or mailbox without the list it holds. Or reference-out-of-scope: the new target isn’t the project’s to reach. Nothing changes.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}No mail trigger with that id.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}A new target the trigger’s owner can’t run (trigger-owner-cannot-run-target), with an authorization store. Or an Idempotency-Key reused with a different body.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The request body is over the API’s limit (request-too-large; details.maxBytes says how much).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Server error (unmapped domain code or framework crash).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The Idempotency-Key store couldn’t be read before the request ran (idempotency-store-unavailable), so nothing was changed; Retry-After (whole seconds) says when to try again with the same key.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}See also
GET /v1/mail-triggers/{triggerId}: Fetch a mail triggerPOST /v1/mail-triggers/{triggerId}/pause: Pause a mail triggerPOST /v1/mail-triggers/{triggerId}/resume: Resume a mail triggerPOST /v1/mail-triggers/{triggerId}/unregister: Soft-delete a mail trigger (tombstone)- Error code
bad-input - Error code
idempotency-store-unavailable - Error code
reference-out-of-scope - Error code
request-too-large - Error code
trigger-owner-cannot-run-target - Every error code