Take over a schedule
const url = 'https://example.com/v1/schedules/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/owner';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"runAsServiceAccountId":"example","runAsProject":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/schedules/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/owner \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "runAsServiceAccountId": "example", "runAsProject": true }'The caller becomes the schedule’s owner, so its runs act as the caller from the next run that starts. Needs admin on the schedule’s project (without an authorization store, a tenant-admin key) and execute on what it runs. For a schedule whose owner left or lost access, or to make one shared or personal. It’s the one way a schedule’s owner changes, audited as trigger-owner-set, naming the schedule’s version after it; a person it’s taken from is told, where the server tells owners. Name runAsServiceAccountId instead to make a service account the owner: that needs act_as on the account (a tenant admin’s), and the account must itself hold the access the schedule’s target needs. With an authorization store, that’s checked when the account is named: an account that can’t is refused (409 trigger-owner-cannot-run-target). Or name runAsProject: true to make the project’s own service account the owner, made the first time with the editor role on the project, so the schedule is shared and runs as the project. It runs only what the project’s editors can, and is checked the same way. The schedule keeps its toolsAllowedUnattended, now for the new owner’s runs; a body naming it is refused (change it with PATCH).
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 workspace 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 Body
Section titled “Request Body”Who the trigger’s runs act as from now: for a trigger whose owner left, or to make one shared or personal. Absent, or an empty body: the caller takes it over (today’s behaviour). With runAsServiceAccountId: that service account becomes the owner. With runAsProject: the project’s own account does. A take-over keeps the trigger’s toolsAllowedUnattended: change that with PATCH.
object
A service account the trigger’s runs act as (its owner), named by id, instead of the caller. Needs act_as on that account — a tenant admin holds it — and the account must itself hold what the trigger runs. With an authorization store, that’s checked when the account is named: an account that can’t is refused (409 trigger-owner-cannot-run-target). Not a project’s own account (409 service-account-project-owned: name it with runAsProject).
true: the trigger’s runs act as its project’s own service account, made the first time with the editor role on the project, so it’s shared. It runs only what the project’s editors can. With an authorization store, that’s checked when it’s named: if it can’t run what the trigger runs, the request is refused (409 trigger-owner-cannot-run-target). Takes admin on the trigger’s project (without an authorization store, a tenant-admin key), not act_as. Not with runAsServiceAccountId, and not without a project (400). A runtime that can’t make the account answers 501 trigger-operation-unsupported. false or absent: as runAsServiceAccountId says.
Examplegenerated
{ "runAsServiceAccountId": "example", "runAsProject": true}Responses
Section titled “Responses”The schedule, with its new owner.
A schedule: what it runs (a flow at a version, or an agent), when (a cron expression in a timezone), as whom (its owner), and what it does after a gap or while a run is still going.
object
Domain-friendly alias for triggerId — the trigger id (a UUID). Use interchangeably in admin URLs.
A schedule that runs a flow: the flow, at flowVersion.
A schedule that runs an agent: the agent, at agentVersion, else its version pinned for the schedule’s project (else the latest), as a run that names none.
A schedule that starts Improve runs: on this agent, in this project (the schedule’s), when the project has enough new corrections sorted to improve since its last Improve run (input: how many, whose, and what a run and the month may cost). An agent and project have one at most.
object
The schedule’s own project. Absent from older servers, and on a schedule registered for a workspace or an org before Improve schedules worked in a project: its fires are refused until its target is saved with the schedule’s project.
The schedule’s project: its runs are this project’s.
Who its runs act as. A person: a personal trigger, which only they or a project admin change. A service account: a shared trigger. Only a take-over (POST …/owner) changes it. Checked again at every fire.
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.
5- or 6-field cron expression (croner-compatible). 6-field enables second precision.
IANA timezone (e.g. UTC, America/New_York). Absent → UTC.
Static input handed to the run on every fire. Absent → {}.
After a gap (the runtime was down, or a fire is later than startingDeadlineSeconds): latest runs once, for the latest missed occurrence, and its fire says how many it missed; skip drops the missed occurrences. Never a run per missed occurrence. A workspace’s suspension isn’t caught up either way: once the workspace is restored, a schedule that’s on fires next at its first occurrence after the restore.
When an occurrence comes while the previous run of this schedule is still running: skip records the fire as skipped; allow starts another run.
How late a fire may start and still count as on time; past it, catchUp applies.
Lifecycle status. Only active triggers fire. Tombstoned rows are excluded from every read path.
Why the runtime paused it: repeated fires that were refused (the owner lost access) or failed. Skipped fires (an overlap, an erasure in progress) never count. For an Improve schedule, owner-lost-publish pauses it at once: its owner no longer has publish on the agent. Saving it with a new owner resumes it.
For an Improve schedule whose month’s Improve runs have reached its monthly cap (input.monthCapUsd): when it starts again by itself, the 1st of next month (UTC). It stays active, and its fires until then are skipped. Absent otherwise.
Why it waits until pausedUntil: its month’s cap.
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 tools whose calls in this schedule’s runs don’t wait for a person’s yes, though a tool asks for one in a run no person started (needsApprovalWhenUnattended). 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 workspace’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.
Wall-clock time of the next scheduled fire. null on paused rows if the cron scheduler never re-armed.
The next occurrences, when the request asked for them (?upcoming=N).
Example
{ "owner": { "kind": "user", "isProjectAccount": true }, "catchUp": "latest", "overlap": "skip", "status": "active", "pausedReason": "month-cap"}A malformed body, or runAsProject with runAsServiceAccountId, or a body naming toolsAllowedUnattended (bad-input).
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" }}permission-denied: not an admin of the schedule’s project, or no execute on what it runs, or no act_as on the account named.
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 cron trigger with that id, or no such service account.
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" }}runAsServiceAccountId names an unregistered account (service-account-unregistered), a project’s own account (service-account-project-owned: name it with runAsProject), or one that can’t run what the schedule runs (trigger-owner-cannot-run-target). Or, with runAsProject, the project’s own account can’t run what the schedule runs either (trigger-owner-cannot-run-target; the account stays, for the next runAsProject), or an active account someone made already has the project account’s name, project-<projectId> (service-account-name-taken: a tenant admin can unregister it). Or an idempotency conflict.
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" }}trigger-operation-unsupported: this deployment can’t change a schedule’s owner, or can’t make a project’s own account (runAsProject).
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/schedules/{triggerId}: Fetch a cron schedulePATCH /v1/schedules/{triggerId}: Update a cron schedulePOST /v1/schedules/{triggerId}/pause: Pause a cron schedulePOST /v1/schedules/{triggerId}/resume: Resume a cron schedule- Error code
bad-input - Error code
idempotency-store-unavailable - Error code
permission-denied - Error code
request-too-large - Error code
service-account-name-taken - Error code
service-account-project-owned - Error code
service-account-unregistered - Error code
trigger-operation-unsupported - Error code
trigger-owner-cannot-run-target - Every error code