This is the reference for the SaaS user-facing APIs that handle projects. With an application token, you can create and configure projects, place Agents, start workflow runs, check the results of executions, and decide review requests. For the conversation, library (Agents, playbooks, and skills), and organization APIs, see User API Reference (Conversations, Library, Organizations). For how to combine the APIs to investigate and fix executions that did not go well, see the Project API Guide.
A system integration token can call only four project APIs: list projects, start a workflow run, fire a trigger, and get a workflow run (System Integration API Reference). Calling any other API on this page with a system integration token returns 403 Forbidden (forbidden).
Every API request must include a Bearer token in the Authorization header.
Authorization: Bearer <access_token>
If the token is invalid or missing, 401 Unauthorized is returned. The APIs on this page use the following scopes. If a required scope is missing, 403 Forbidden (insufficient_scope) is returned.
Scope
What it allows
project:read
Read projects and what they contain (steps, placements, executions, records (audit trail), KPIs, and so on), review requests, and connectors
project:write
Create and edit projects, and change steps and placements
APIs that read a project and what it contains (steps, placements, executions, and so on) can be called by members of the project. Except for creating a project, APIs that write (including starting a workflow run and firing a trigger) can be called only by owners of the project. Who can call the review request and connector APIs is described in their sections. A member who is not an owner gets 403 Forbidden (owner_only).
A project you are not a member of and a project that does not exist both return 404 Not Found, and the response does not tell them apart. However, you can read the structure of a shared project with Get Project (GET /v1/projects/{projectId}) even if you are not a member.
Each endpoint has one code for 404 Not Found, named after the last resource in the path (for example, placement_not_found for the placement APIs and execution_not_found for the execution APIs). Endpoints without a resource ID in the path use project_not_found. When the project is not visible, the endpoint's code is still returned.
When an ID specified in the body (an Agent, a step, a user, and so on) does not exist or is not visible, the response differs by endpoint (for example, agentId of a placement returns 400 Bad Request (agent_not_found), and stepIds of a placement returns 400 Bad Request (invalid_parameter)). See the description and error responses of each endpoint.
When a query that filters a list (placementId, stepId, or runId) specifies an ID that does not exist, an empty list is returned.
For a token of a user who does not sign in with SSO, the project and review request APIs (except list projects, start a workflow run, fire a trigger, and get a workflow run) return 403 Forbidden (sso_required).
Query parameters and body fields not in the specification are ignored. An invalid value for a query parameter in the specification, or a cursor that cannot be read, returns 400 Bad Request.
Send the body as a JSON object. A Content-Type other than application/json returns 415 Unsupported Media Type (unsupported_media_type), and malformed JSON or a body that is not a JSON object returns 400 Bad Request (invalid_body).
The body can be up to 16 KiB (3 MiB for the API that creates a project and the API that decides a review request). A larger body returns 413 Payload Too Large (body_too_large).
Fields that this API deliberately does not accept return 400 Bad Request (invalid_parameter) when sent, because silently ignoring them would make a change look applied when it is not. Each endpoint lists these fields.
Responses include an x-request-id header. The service assigns this value, and a value sent in the request is not used. When you contact support, please tell us this value.
APIs that edit take the digest returned by the get API as baseDigest. If another change was made after you got it, 409 Conflict (stale_base) is returned. Get it again and resend. Two edits that arrive at almost the same time may both succeed.
The digest in the response is the value after the edit. You can use it for the next edit.
The APIs that create projects and steps create another one when resent. If you did not receive a response, check with the project list or Get Project whether it was created before resending. The API that places an Agent returns the existing placement when resent with the same Agent and the same steps.
Resends are identified by the Idempotency-Key header (required) for starting a workflow run, by eventId in the body for firing a trigger, and by commandId in the body for deciding a review request. Resending with the same key returns the result of the first request.
User names and email addresses are returned only in the member list (members) of Get Project (GET /v1/projects/{projectId}). Other fields return only user IDs.
The owner of a resource is ownerUserId (the owner of a placed Agent is agentOwnerUserId), people in settings are approverUserIds and escalateToUserId, and the requester of a review request is requesterUserId.
Who did something is returned as a pair of …Kind (kind) and …Ref (reference). When …Kind is "human", …Ref is a user ID. Otherwise, …Ref is client:<integration ID> for a system integration, or another reference such as system:…. Even when there is no value, the field is not omitted and is returned as null. As an exception, what started a workflow run is returned only as startedByRef (there is no kind field; see Get a Workflow Run (GET /v1/projects/{projectId}/runs/{runId}) for the values).
List APIs read the next page with limit (1 to 100; 50 if omitted) and cursor (send the value from the previous response as is). cursor is returned only when hasMore is true. The number of items (total) is not returned. Lists with a different range or default for limit, lists without limit, lists that return all items, and lists whose hasMore means something different are described in each endpoint.
A project is a unit for running work by placing Agents in steps. There are two types: workflow (steps run in order) and cycle (each placement keeps running in sweeps). The type is decided when the project is created and cannot be changed later.
Retrieves the list of projects you can access. Supports cursor-based pagination. cycle projects also appear in the list, but they are not valid targets for starting a run (POST /v1/projects/{projectId}/runs).
Cursor for the next page (the cursor value from the previous response)
myRole
string
—
Either "owner" or "member". Returns only the projects where the caller has that role
Any other query parameter is ignored. A value other than "owner" / "member", or specifying myRole more than once, returns 400 Bad Request.
`cursor` represents a position, so do not change `myRole` while reusing the same cursor. Changing the criteria changes the result set and can duplicate or skip items.
An invalid value for limit, cursor, type, tag, q, or sort
403
insufficient_scope
The project:read scope is missing
403
forbidden
Called with a system integration token
403
sso_required
The user does not sign in with SSO
GET/v1/projects/organizations
Gets the organizations you can set when creating a project. Only the organization the calling user currently belongs to can be set (zero or one item). This differs from GET /v1/organizations, which returns all organizations.
The organization the user belongs to cannot be confirmed (resend the request later)
GET/v1/projects/{projectId}
Gets a project together with its steps, members, placements, triggers, notifications, and connectors. If a user who is not a member specifies a shared project, only the structure (a preview) is returned.
Array of steps (in order). See "Step Fields" for the fields of an item
stepsDigest
string
A value for the order of the steps. Send it as baseDigest when reordering steps
members
array
Array of members
members[].userId
string
User ID
members[].role
string | null
"owner" or "member"
members[].joinedAt
string | null
When the user became a member (ISO 8601)
members[].name
string | null
User name
members[].email
string | null
User email address
placements
array
Array of placements. See "Placement Fields" for the fields of an item
triggers
array
Array of triggers (time and webhook triggers only)
triggers[].triggerId
string | null
Trigger ID (UUID). Used to fire the trigger
triggers[].type
string
"cron" (time) or "webhook"
triggers[].name
string | null
Name
triggers[].enabled
boolean | null
Whether it is enabled
triggers[].lastFiredAt
string | null
When it last fired (ISO 8601)
triggers[].nextFireAt
string | null
When it is scheduled to fire next (ISO 8601)
triggers[].createdAt
string | null
Creation time (ISO 8601)
triggers[].cron
string | null
Cron expression ("cron" triggers only)
triggers[].timezone
string | null
Time zone ("cron" triggers only)
triggers[].startStepId
string | null
ID of the step to start from ("cron" triggers only)
triggers[].placementId
string | null
ID of the placement to start ("webhook" triggers only)
triggers[].stepId
string | null
ID of the step to start ("webhook" triggers only)
notifications
object
Notification settings
notifications.gateReached
boolean | null
Whether to notify when a review request arrives
notifications.gateOverdue
boolean | null
Whether to notify when a review request passes its deadline
connectors
array
Array of connectors registered to this project
connectors[].kind
string | null
"mcp" or "a2a"
connectors[].connectionId
string | null
Connector ID. Read its contents with the connector API (GET /v1/connectors/{kind}/{connectionId}). null for a connector disabled or deleted on the admin screen, and when the connector information could not be checked
connectors[].name
string | null
Connector name
connectors[].ledgerEnabled
boolean | null
Whether the connector is used as a ledger
connectors[].login
string | null
Sign-in status: "connected" (signed in), "reauth_required" (must sign in again), or "not_connected" (not signed in). null when the status cannot be confirmed. Sign in on the screen
connectors[].createdAt
string | null
Registration time (ISO 8601)
Fields of project:
Field
Type
Description
projectId
string
Project ID (UUID)
name
string | null
Project name
description
string | null
Description
tags
array
Array of tags
type
string | null
"workflow" or "cycle"
status
string | null
One of "active" (active), "paused" (paused), or "archived" (archived)
policy
object | null
Execution rules. Returned as set on the screen. Cannot be changed with this API
limits
object | null
Execution limits
limits.maxRetriesPerStep
number
Maximum number of retries when a step fails
limits.maxSendBacksPerStep
number
Maximum number of times work can be sent back to the same step
language
string | null
Language of the project
flowStructure
object | null
Lane definition (for a workflow that runs steps in parallel). See "Lane Definition" below
reportTargets
object | null
Not used at present (even if it has a value, the value is not used)
organizationCode
string | null
Organization code
organizationName
string | null
Organization name
isShared
boolean | null
Whether it is shared
copyCount
number | null
Number of times copied
ownerUserId
string | null
User ID of the owner
myRole
string | null
Role of the calling user: "owner" or "member". null in a preview
createdAt
string | null
Creation time (ISO 8601)
updatedAt
string | null
Last updated time (ISO 8601)
digest
string
The value to send as baseDigest when editing the project
Lane definition (flowStructure):
Field
Type
Description
lanes
array
Array of lanes
lanes[].id
string | null
Lane ID
lanes[].name
string | null
Lane name
lanes[].parentLaneId
string | null
ID of the lane before the split
lanes[].stepIds
array
Array of IDs of the steps in this lane. Steps that belong to no lane are in the "main" lane
forks
array
Array of splits
forks[].id
string | null
Split ID
forks[].afterStepId
string | null
The split happens after this step
forks[].laneIds
array
Array of IDs of the lanes after the split
forks[].joinId
string | null
ID of the join
joins
array
Array of joins
joins[].id
string | null
Join ID
joins[].mode
string | null
"and" (proceeds when all lanes are complete)
joins[].laneIds
array
Array of IDs of the lanes that join
joins[].nextStepId
string | null
ID of the step to proceed to after the join
When a user who is not a member reads a shared project (a preview), project (without organizationName and digest; myRole is null), steps (without the digest of each step), and placements (only placementId, agentId, name, description, goal, stepIds, and skillCount) are returned. stepsDigest, members, triggers, notifications, and connectors are not returned.
The goal, guardrail, and inputFiles (file names) of placed Agents are returned even without the assets:read scope.
The project does not exist, or it is a project that is not shared and you are not a member of
POST/v1/projects
Creates a project. The user who creates it becomes the owner and the principal that runs the project. Create Agents in the library first, and then place them with the API that places a placement (POST /v1/projects/{projectId}/placements).
Project name (up to 255 characters; cannot be only whitespace)
description
string
—
Description (up to 5000 characters)
tags
array
—
Tags (up to 10 strings of up to 30 characters each; saved in lowercase with leading and trailing whitespace and a leading # removed. Tags that become empty or the same this way cannot be sent)
type
string
—
"cycle" or "workflow". "cycle" if omitted ("workflow" in environments where cycle is not available)
organizationCode
string | null
—
Organization code (up to 255 characters). Only an organization returned by GET /v1/projects/organizations can be set. null, an empty string, or only whitespace is the same as not setting one
steps
array
—
The steps (up to 12). If omitted or empty, the project is created with the default steps (for a workflow, three steps: a step run by an Agent, a review step, and a step run by an Agent; for a cycle, two steps run by Agents)
steps[].name
string | null
—
Step name (up to 100 characters; an empty string or null means the default name; cannot be only whitespace)
steps[].description
string | null
—
Step description (an empty string or null means no description)
steps[].enabled
boolean
—
Whether it is enabled (true or false). Enabled if omitted
steps[].zone
string
—
"ai" (run by an Agent) or "gate" (review step). "ai" if omitted. Only "ai" for cycle. null cannot be sent
steps[].placementExecution
string | null
—
"parallel" runs the Agents placed in the step at the same time ("ai" steps of a workflow only). If omitted, null, or "serial", they run one at a time
trigger, policy, agents, guardrail, and templateRef are not accepted (sending them returns 400, invalid_parameter). Set triggers and execution rules on the screen. For a cycle, set the sweep interval after placing Agents, with the API that changes the sweep (PATCH /v1/projects/{projectId}/placements/{placementId}/schedule).
name is missing or only whitespace, a field has the wrong type, length, number of items, or value (including empty or duplicate tags), more than 12 steps, or trigger, policy, agents, guardrail, or templateRef was sent
400
invalid_body
The body is malformed JSON or not a JSON object
400
cycle_disabled
cycle is not available in this environment
400
cycle_gate_not_allowed
A review step ("gate") was specified for a cycle
400
parallel_workflow_only
"parallel" for placementExecution was specified for a step of a cycle
400
parallel_ai_only
"parallel" for placementExecution was specified for a step that is not "ai"
400
organization_not_member
An organization that cannot be set was specified
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
sso_required
The user does not sign in with SSO
403
license_status_unavailable
The license cannot be confirmed
409
project_limit_reached
The number of projects has reached the limit (the numbers are in error.message)
413
body_too_large
The body exceeds 3 MiB
415
unsupported_media_type
The Content-Type of the body is not application/json
503
organization_unavailable
The organization the user belongs to cannot be confirmed
PATCH/v1/projects/{projectId}
Edits a project. Only the fields you send are changed. Only owners can call this API.
Project name (up to 255 characters; cannot be empty or only whitespace)
description
string
—
Description (up to 5000 characters; cannot be an empty string, only whitespace, or null)
tags
array
—
Tags (same as when creating). Sending them replaces all tags
status
string
—
"active", "paused", or "archived"
isShared
boolean
—
Whether to share it
limits
object
—
Execution limits. Only the fields you send are overlaid on the current values
limits.maxRetriesPerStep
integer
—
0 to 10
limits.maxSendBacksPerStep
integer
—
1 to 10
flowStructure
object | null
—
Lane definition (same form as in Get Project). Sending it replaces the whole definition. null removes the lanes
organizationCode
string | null
—
Organization code (up to 255 characters). Can be set only once, on a project that has no organization yet. null changes nothing if no organization is set yet, and returns 409 (organization_locked) if one is set
Send at least one field besides baseDigest. type, policy, and connectSecret are not accepted (sending them returns 400, invalid_parameter). The type is decided when the project is created, and execution rules are changed on the screen.
Setting status to "paused" or "archived" stops new executions from starting. Sweeps and time-based starts stop, starting workflow runs and firing triggers are refused with 409 Conflict, and "Start by email" is no longer accepted (a resend of a workflow run start with the same Idempotency-Key as an accepted one returns the result of the first request). Running executions are not stopped. A running workflow run waits without starting its next step (its status stays "running" or "waiting_gate"). Fires and emails accepted before the stop may still run after it. Setting it back to "active" resumes the starts that were held while the project was stopped.
These are the rules for sending flowStructure. If they are not met, 400 (invalid_flow_structure) is returned.
Only workflow projects can have lanes. A project where a registered Agent of the Marketplace edition is placed cannot have lanes.
IDs of lanes, forks, and joins are up to 64 letters, digits, _, and -. Step IDs are UUIDs. Lane names are up to 50 characters and cannot be only whitespace. The "main" lane cannot have a name (set it to null or omit it).
The parentLaneId of the "main" lane is null, and the parentLaneId of the other lanes is "main" (a lane cannot branch further). There can be up to 12 lanes other than "main".
To use lanes, include exactly one fork and one join. The laneIds of the fork are all the lanes other than "main" (2 or more), and its joinId is the id of the join. The laneIds of the join are the same lanes as the fork, and its mode is "and".
The afterStepId of the fork is a step in "main", and it cannot be a step whose placementExecution is "parallel". The nextStepId of the join is a later step in "main". When it is null, all the steps after the fork go into lanes.
All the steps between the fork and the join go into lanes, and the other steps go into "main". A step cannot be in two lanes. lanes[].stepIds can contain only steps of this project. Each lane has at least one step.
The destinations and the send-back step of a review step, and the "goto" destinations of onDenied and onDegraded, can only be steps in the same lane. In "main", they cannot cross between before the fork and after the join.
If there are no lanes other than "main" and forks and joins are empty, it is the same as null (the lanes are removed).
projectId is not a UUID, baseDigest is missing, empty, or not a string, no fields to change, name was set empty or only whitespace, description was set to an empty string, only whitespace, or null, null was sent for name, status, tags, isShared, or limits, a field has the wrong type or value (including empty or duplicate tags), or type, policy, or connectSecret was sent
400
invalid_body
The body is malformed JSON or not a JSON object
400
invalid_flow_structure
The lane definition does not follow the rules above
400
organization_not_member
An organization that cannot be set was specified
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
project_not_found
The project does not exist, or you are not a member
409
stale_base
The project has changed since you got it
409
organization_locked
An organization is already set
403
license_status_unavailable
Tried to move the project out of "archived", but the license cannot be confirmed
409
project_limit_reached
Tried to move the project out of "archived", but the number of projects has reached the limit
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
503
organization_unavailable
The organization the user belongs to cannot be confirmed
DELETE/v1/projects/{projectId}
Deletes a project. Only owners can call this API. What is running (sweeps, running workflow runs, review requests waiting for a decision, and triggers) stops. Records of executions and reviews are not deleted. The service also tries to remove sign-ins to the project's connectors, but the deletion of the project succeeds even if they cannot be removed.
Base rule for the whole tenant: "open", "guarded", or "strict". null when it cannot be confirmed
tenantSource
string | null
Where tenantProfile comes from: "governance_policies" (set on the admin screen), "default" (no setting, so the default), or "unavailable" (cannot be confirmed)
projectProfile
string | null
Base rule of this project
effectiveProfile
string | null
The base rule actually in effect (the stricter of the tenant and this project). null when tenantProfile is null
deny
array
Operations prohibited by the execution rules
gates
array
Array of enabled review steps
gates[].stepId
string
Step ID
gates[].position
number
Position of the step
gates[].name
string
Step name
gates[].gateKind
string
Kind of review: "review" (review) or "manual" (manual work)
gates[].mode
string
Review method: "blocking" (wait for the reviewer's decision) or "notify_only" (proceed automatically after the deadline)
gates[].overdueAction
string
After the deadline: "none" (notify and keep waiting), "proceed" (proceed automatically), "send_back" (send back automatically), or "reject" (reject automatically)
A step is a unit of the project's flow. There are steps run by Agents (defaultZone is "ai") and review steps decided by people ("gate"). A project can have up to 12 steps. You cannot delete steps to leave fewer than 2.
The fields of a step in steps of Get Project and in the responses of the step APIs.
Field
Type
Description
stepId
string
Step ID (UUID)
position
number | null
Position of the step (from 1)
name
string | null
Step name. When null, the screen shows a default name (such as "Step 1")
description
string | null
Description
enabled
boolean | null
Whether it is enabled
defaultZone
string | null
"ai" (run by an Agent) or "gate" (review step)
reworkToStepId
string | null
ID of the step to go back to when work is sent back (used by review steps)
gateConfig
object | null
Settings of a review step (the table below)
gateKind
string | null
Kind of review: "review" (a person decides on the Agent's result) or "manual" (a person does the work and then proceeds)
schedule
object | null
Time of the step (workflow only): expression (cron expression) and timezone
scheduleNextFireAt
string | null
When the step is next scheduled to run by its time (ISO 8601)
onDenied
string | null
What happens "when it cannot run under the rules": "gate" (request a review), "closed_failed" (close as failed), or "goto" (proceed to the step in outcomeRoutes)
onDegraded
string | null
What happens "when the Agent reports a failure": "gate" (request a review), "proceed" (proceed as is), or "goto" (proceed to the step in outcomeRoutes)
outcomeRoutes
object | null
Where to proceed when onDenied or onDegraded is "goto"
outcomeRoutes.onDenied.stepId
string
ID of the step to proceed to "when it cannot run under the rules"
outcomeRoutes.onDegraded.stepId
string
ID of the step to proceed to "when the Agent reports a failure"
laneId
string | null
ID of the lane this step belongs to
placementExecution
string | null
"parallel" (run the Agents placed in this step at the same time). null runs them one at a time in placement order
digest
string
The value to send as baseDigest when editing the step
Settings of a review step (gateConfig):
Field
Type
Description
approverUserIds
array
Array of user IDs of the reviewers (up to 20 project members)
deadlineHours
number | null
Review deadline (hours; 1 to 720)
mode
string | null
Review method: "blocking" (wait for the reviewer's decision) or "notify_only" (proceed automatically after the deadline)
overdueAction
string | null
After the deadline: "none" (notify and keep waiting), "proceed" (proceed automatically), "send_back" (send back automatically), or "reject" (reject automatically)
escalateToUserId
string | null
User ID of the contact when the deadline passes (a project member)
destinations
array
Steps the reviewer can choose to proceed to (2 to 5 steps after this step). Not included when not set
destinations[].id
string
Destination ID (up to 64 letters, digits, _ and -)
destinations[].label
string
Name shown on the screen (up to 100 characters)
destinations[].stepId
string
ID of the step to proceed to
When a review step has no settings (gateConfig is null, or a field is missing or null), it works with mode"blocking", deadlineHours 24 hours, overdueAction"none", and no contact after the deadline. When gateKind is null, it is "review".
Depending on the type of the project, some settings cannot be set on steps.
Step setting
workflow
cycle
Review steps ("gate" for defaultZone) and their settings (gateConfig and gateKind)
Can be set
400 (cycle_gate_not_allowed)
"gate" for onDenied and onDegraded
Can be set
400 (cycle_gate_not_allowed)
"goto" for onDenied and onDegraded, and outcomeRoutes
Can be set
400 (cycle_route_not_allowed)
"parallel" for placementExecution
Can be set on "ai" steps only
400 (parallel_workflow_only)
schedule (time of the step)
Can be set
400 (invalid_parameter)
reworkToStepId (step to send back to)
Can be set
400 (invalid_parameter)
For a cycle, schedule and reworkToStepId are rejected only when a value other than null is sent (null is accepted so that a step you got can be sent back as is). For a cycle, how often an Agent runs is decided by the sweep of the placement, not by the step.
Step name (up to 100 characters; an empty string or null means the default name; cannot be only whitespace)
description
string | null
—
Description (up to 2000 characters; an empty string or null means no description)
defaultZone
string
—
"ai" or "gate". "ai" if omitted. null or an empty string cannot be sent
afterStepId
string
—
Add the step after this step (the ID of a step of this project)
beforeStepId
string
—
Add the step before this step (the ID of a step of this project). If both afterStepId and beforeStepId are specified, the step is added before this step. If both are omitted, the step is added at the end
gateConfig
object | null
—
Settings of a review step (same form as gateConfig in Step Fields; destinations are set when editing a step). null means no settings
placementExecution
string | null
—
"parallel" runs Agents at the same time. null or "serial" runs them one at a time
The added step is enabled. In a project with lanes, the step goes into the same lane as the step in beforeStepId when it is specified, or as the step in afterStepId otherwise.
projectId is not a UUID, afterStepId or beforeStepId is not a step of this project, or a field has the wrong type, length, or value (including a whitespace-only name, and null or an empty string for defaultZone)
400
invalid_body
The body is malformed JSON or not a JSON object
400
step_reference_on_create
destinations was sent in gateConfig (including null or an empty array; set destinations with the API that edits a step, after adding the step)
400
cycle_gate_not_allowed
Tried to add a review step to a cycle
400
parallel_workflow_only
"parallel" was specified for a step of a cycle
400
parallel_ai_only
"parallel" was specified for a review step
400
parallel_not_for_marketplace
"parallel" was specified in a project where a registered Agent of the Marketplace edition is placed
400
approver_not_member
A user who is not a member was specified as a reviewer
400
approvers_required
Tried to add a review step without reviewers to an active workflow
400
escalate_to_not_member
A user who is not a member was specified as the contact when the deadline passes
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
project_not_found
The project does not exist, or you are not a member
409
too_many_steps
There are already 12 steps
409
flow_structure_conflict
Conflicts with the lane definition
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
PATCH/v1/projects/{projectId}/steps/{stepId}
Edits a step. Only the fields you send are changed. Only owners can call this API.
Step name (up to 100 characters). An empty string or null resets it to the default name. Cannot be only whitespace
description
string
—
Description (up to 2000 characters; cannot be an empty string, only whitespace, or null)
defaultZone
string
—
"ai" or "gate"
enabled
boolean
—
Whether it is enabled
gateConfig
object | null
—
Settings of a review step. Only the fields you send are overlaid on the current values. null removes the settings
gateKind
string | null
—
"review" or "manual"
reworkToStepId
string | null
—
Step to send back to (a step before this step). null removes it
onDenied
string | null
—
"gate", "closed_failed", or "goto"
onDegraded
string | null
—
"gate", "proceed", or "goto"
outcomeRoutes
object | null
—
Where to proceed for "goto" (steps after this step). Sending it replaces the whole value (send onDegraded together even when changing only onDenied). null removes it. If it contains neither onDenied nor onDegraded, it is the same as not sending it
placementExecution
string | null
—
"parallel" runs Agents at the same time. null or "serial" runs them one at a time
schedule
object | null
—
Time of the step (workflow only): expression (a 5-field cron expression) and timezone (UTC if omitted). null removes it
Send at least one field besides baseDigest.
For the first step, the time of the step starts a workflow run at that time only when the project has no enabled time trigger. For other steps, the workflow run waits until that time.
Changing the reviewers (approverUserIds) or the review method (mode) is recorded in the records (audit trail).
projectId or stepId is not a UUID, baseDigest is missing, empty, or not a string, no fields to change, name was set to only whitespace, description was set to an empty string, only whitespace, or null, null was sent for defaultZone or enabled, a field has the wrong type, length, or value, or schedule or reworkToStepId was sent for a cycle
400
invalid_body
The body is malformed JSON or not a JSON object
400
cycle_gate_not_allowed
Tried to make a step of a cycle a review step, or specified "gate" for onDenied or onDegraded
400
cycle_route_not_allowed
"goto" was specified for a step of a cycle
400
parallel_workflow_only
"parallel" was specified for a step of a cycle
400
parallel_ai_only
"parallel" was specified for a review step
400
parallel_not_for_marketplace
"parallel" was specified in a project where a registered Agent of the Marketplace edition is placed
400
approver_not_member
A user who is not a member was specified as a reviewer
400
approvers_required
In an active workflow, an enabled review step would have no reviewers
400
escalate_to_not_member
A user who is not a member was specified as the contact when the deadline passes
400
invalid_send_back_step
The step to send back to is not a step before this step
400
invalid_destinations
destinations has the wrong form (not 2 to 5 items, duplicate IDs, names, or steps, and so on)
400
destinations_gate_only
Tried to set destinations on a step that is not a review step
400
destinations_notify_only
Tried to set destinations on a step whose review method is "notify_only"
400
invalid_destination_step
A step in destinations is not a step after this step
400
invalid_outcome_routes
outcomeRoutes has the wrong form
400
invalid_outcome_route
There is no destination for "goto", or it is not a step after this step
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
step_not_found
The step does not exist, or you are not a member of the project
409
stale_base
The step has changed since you got it
409
flow_structure_conflict
Conflicts with the lane definition
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
projectId is not a UUID, baseDigest is missing, empty, or not a string, or stepIds is not the order of all steps
400
invalid_body
The body is malformed JSON or not a JSON object
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
project_not_found
The project does not exist, or you are not a member
409
stale_base
The order of the steps has changed since you got it
409
flow_structure_conflict
Conflicts with the lane definition
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
DELETE/v1/projects/{projectId}/steps/{stepId}
Deletes a step. Only owners can call this API. Send-back targets, destinations, and trigger start steps that point to the step are removed, and the placements and sweeps on the step are also removed. A step used by past workflow runs or review requests is kept for the records (historyKept is true).
The step does not exist, or you are not a member of the project
409
min_steps
There are only 2 steps
409
flow_structure_conflict
Conflicts with the lane definition (to delete the step where lanes split, the step after a join, or the last step of a lane, fix the lane definition first)
A placement is a library Agent placed in steps of a project. The same Agent can be placed only once in a project, and one placement can have multiple steps (its steps). For a cycle, how often an Agent runs (its sweep) is decided per pair of placement and step.
The fields of a placement in placements of Get Project and in the responses of the placement APIs.
Field
Type
Description
placementId
string
Placement ID (UUID)
agentId
string | null
ID of the placed Agent (the ID of the library Agent)
displayOrder
number | null
Display order
name
string | null
Agent name
description
string | null
Agent description
goal
string | null
Agent goal (instructions)
guardrail
string | null
Agent guardrail
skills
array
Skills used by the Agent (skillId and name)
skillCount
number | null
Number of skills
playbookId
string | null
ID of the playbook used by the Agent
playbookName
string | null
Playbook name
inputFiles
array
Input files of the Agent (filename only)
stepIds
array
Array of IDs of the steps of the placement
sweeps
array
Sweep settings (cycle): stepId, cron, timezone, and enabled for each step
runtimeConfigs
array
Runtime settings per step (stepId and runtimeConfig). runtimeConfig is returned in the form saved
memoryOrgId
string | null
Organization of the placement memory
memoryJobId
string | null
Job type of the placement memory
agentOwnerUserId
string | null
User ID of the owner of the placed Agent
isShared
boolean | null
Whether the placed Agent is shared
runtimeKind
string | null
Kind of runtime of the Agent
marketplaceAgentId
string | null
ID of the registered Agent in the Marketplace edition. null otherwise
exclusiveToThisProject
boolean | null
Whether this project is the only project where this Agent is placed
digest
string
The value to send as baseDigest to the APIs that change a placement (steps, memory, and sweep). It is made from the steps, memory, runtime settings, and sweeps, and does not change when the Agent itself changes
The placement does not exist, it belongs to another project, or you are not a member of the project
POST/v1/projects/{projectId}/placements
Places a library Agent in steps of a project. Only owners can call this API. Only your own Agents can be placed (copy a shared Agent in the library first, and then place the copy).
Array of IDs of the steps of the placement (up to 12 steps of this project). If omitted, the Agent is placed without steps
If the same Agent is already placed, 409 Conflict (placement_already_exists) is returned. If the steps are also the same, the request is treated as a resend and the existing placement is returned. To change the steps, use the API that changes the steps of a placement.
Of the Agent's input files, only the files of the user who created the project are passed when it runs.
A newly placed placement goes to the end of the placement order (displayOrder). However, placing the same Agent as a placement removed earlier (a placement kept because past workflow runs used it) brings that placement back with its original ID and position. When the placements of a step run one at a time, they run in this order. There is no API to reorder placements.
Removes a placement. Only owners can call this API. A placement used by past workflow runs is kept for the records (historyKept is true). Past executions of a removed placement remain in the execution history with the original placement ID (placementId).
Replaces the steps of a placement with the steps you send. Only owners can call this API. The sweeps of the removed steps stop. An empty array can also be sent (the placement stays in the project, but it does not run because it has no steps).
projectId or placementId is not a UUID, baseDigest is missing, empty, or not a string, or stepIds is invalid (more than 12, not steps of this project, the same step twice, and so on)
400
invalid_body
The body is malformed JSON or not a JSON object
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
placement_not_found
The placement does not exist, it belongs to another project, or you are not a member of the project
409
stale_base
The placement has changed since you got it
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
GET/v1/projects/{projectId}/memory-candidates
Gets the organizations and job types that can be chosen for placement memory. The candidates are the organizations and job types of the project members.
Changes the memory of a placement (the organization and job type memory the Agent reads for the work). Only the fields you send are changed. Only owners can call this API.
projectId or placementId is not a UUID, baseDigest is missing, empty, or not a string, no fields to change, or orgId or jobId is neither a string nor null
400
invalid_body
The body is malformed JSON or not a JSON object
400
memory_not_candidate
A value that is not a memory candidate was specified
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
placement_not_found
The placement does not exist, it belongs to another project, or you are not a member of the project
409
stale_base
The placement has changed since you got it
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
503
memory_candidates_unavailable
The organizations and job types of the members cannot be confirmed (resend the request later)
For a cycle project, stops, resumes, or changes the interval of the sweep of a placement. Only the fields you send are changed. Only owners can call this API.
ID of the step of the sweep (a step of the placement). Can be omitted for a placement with one step
enabled
boolean
—
true resumes and false stops
cron
string
—
Interval (a 5-field cron expression; up to 100 characters)
timezone
string
—
Time zone (an IANA time zone name, up to 64 characters; for example, "Asia/Tokyo")
Send at least one of enabled, cron, and timezone. Fields you do not send keep their current values.
When the step has no sweep yet (setting it for the first time), cron is required. If enabled is omitted, the sweep stays stopped, and if timezone is omitted, UTC is used.
projectId, placementId, or stepId is not a UUID, baseDigest is missing, empty, or not a string, no fields to change, enabled, cron, or timezone has the wrong type, cron is not a valid cron expression or exceeds 100 characters, timezone is only whitespace, is not a valid time zone, or exceeds 64 characters, the project is a workflow, stepId is required but missing, or cron is missing when setting the sweep for the first time
400
invalid_body
The body is malformed JSON or not a JSON object
400
step_not_found
stepId is not a step of this placement
403
insufficient_scope
The project:write scope is missing
403
forbidden
Called with a system integration token
403
owner_only
A member who is not an owner
403
sso_required
The user does not sign in with SSO
404
placement_not_found
The placement does not exist, it belongs to another project, or you are not a member of the project
409
stale_base
The placement has changed since you got it
409
principal
The principal that runs the project (the user who created it) cannot be confirmed
413
body_too_large
The body exceeds 16 KiB
415
unsupported_media_type
The Content-Type of the body is not application/json
For a cycle project, firing a webhook trigger runs the placement tied to the trigger once, as an extra run. Trigger IDs can be read from triggers of Get Project. Add, change, and delete triggers on the screen.
Fires a webhook trigger configured on a cycle project and runs the target agent once, as an extra ad-hoc run. Calling it for a workflow project returns 404 Not Found.
The scheduled runs stay exactly as configured. A fired run is added separately from the schedule. Where an earlier fire has not started running yet, however, a later fire may be merged into that run. Where it is, jobId returns the same value as the earlier fire, so the number of fires and the number of runs do not necessarily match.
A unique ID issued by the sender. Resending the same ID is treated as a duplicate. 1-160 characters using alphanumerics and _ . : @ + - only
payload
any
—
Arbitrary JSON passed to the agent. It is serialized to a JSON string and added to the request sent to the agent; anything beyond 8,000 characters after serialization is omitted
This 202 Accepted means only that the request was recorded as accepted. The run happens afterwards, and its outcome is not part of this response. Do not treat 202 as business success.
Idempotency is decided by the combination of project, trigger, and eventId. Resending the same content returns 202 with result: "duplicate". Sending the same eventId with a different payload returns 409 Conflict (event_conflict).
The execution history (GET /v1/projects/{projectId}/executions) cannot be filtered by the jobId in the response of a fire. Find it as follows.
Filter the execution history by the placement of the trigger (placementId) and the time of the fire (from).
Compare the jobId in the results of the candidate executions (GET /v1/projects/{projectId}/executions/{executionId}) with the jobId in the response of the fire.
Fires merged into an execution that has not started yet become one execution with the same jobId.
A workflow run is one pass through the steps of a workflow project in order. Cycle projects do not create workflow runs (read cycle executions in the execution history).
Resending with the same key returns the same run even after the project has been paused, after the concurrent-run limit has been reached, or after that run has finished.
If a timeout leaves the outcome unknown, simply resend with the same key. Nothing is run twice.
The Idempotency-Key length or character set is invalid
400
invalid_parameter
projectId is not a UUID
400
invalid_body
The request body is malformed JSON or is not a JSON object
413
body_too_large
The request body exceeds 16 KiB
415
unsupported_media_type
A request body is sent with a Content-Type other than application/json
403
insufficient_scope
The project:run scope is missing
403
owner_only
The caller is a member of the project but not an owner
404
project_not_found
The project does not exist or is not accessible
400
approvers_required
An enabled review step has no reviewers configured
409
unsupported_project_type
A cycle project was specified
409
project_inactive
The project is not active (paused or archived)
409
unsupported_runtime
The project cannot run in this configuration, for example because agent runtimes are mixed
429
too_many_active_runs
The project already has the maximum number of runs (3 in total) that are running or awaiting review
GET/v1/projects/{projectId}/runs/{runId}
Retrieves the status of a run. Besides runs started through the API (POST /v1/projects/{projectId}/runs), runs started from the UI, by email, or on a schedule can also be retrieved. cycle projects do not create runs, so they are out of scope for this endpoint.
Run state. One of "running" (running), "waiting_gate" (awaiting review), "closed_done" (completed), "closed_rejected" (ended by rejection), "closed_failed" (ended by failure) or "cancelled" (cancelled). Any value other than "running" and "waiting_gate" means the run has ended
originType
string | null
How the run started. One of "manual" (started from the UI), "api" (started through the API), "mail" (started by email) or "cron" (scheduled)
originRef
string | null
A reference value that depends on how the run started. For a run started through the API, the Idempotency-Key used to start it
currentStepId
string | null
ID (UUID) of the step in progress. While the run proceeds in separate lanes, the ID of the step before the branch. null for a completed run. For a run that ended for another reason, the ID of the step at that time may remain
startedByRef
string | null
Who or what started the run. See the "Who started the run" table below
actorLabel
string | null
Display name of a starter that is not a user (the system integration name or the sender address of an email). null otherwise
startedAt
string | null
Start time (ISO 8601). null before it starts
endedAt
string | null
End time (ISO 8601). null before it ends
summary
string | null
For a completed run, the output of the last completed step that recorded an output (first 2,000 characters). null if there is no such step and for a run that has not completed
runtimeKind
string | null
Kind of runtime ("autonomous"). May be null for older runs
cancelRequestedAt
string | null
Time (ISO 8601) when cancellation was requested. null if not requested
configRevision
number | null
Revision of the case configuration (Marketplace edition runs only). null for SaaS runs
steps
array
Records of the step runs, in the order they were recorded
steps[].runStepId
string
ID of the step run (starts with "rs:")
steps[].stepId
string | null
Step ID (UUID)
steps[].placementId
string | null
ID (UUID) of the placement that handled the step. null for rows that do not run an agent (such as review steps)
steps[].executionId
string | null
ID of the agent execution. Set once the agent starts running
steps[].conversationId
string | null
ID of the conversation of the agent execution. Set once the agent starts running
steps[].status
string
One of "pending" (waiting to run), "running" (running), "waiting_gate" (awaiting review), "done" (done), "failed" (failed) or "skipped" (skipped)
steps[].attempt
number | null
Retry count within the same visit (starting at 1)
steps[].lane
string | null
ID of the lane the step belongs to. "main" for steps that are not in a separate lane
steps[].scheduledAt
string | null
When the step has a scheduled time, the time (ISO 8601) this row waits for. null once it starts
steps[].startedAt
string | null
Start time (ISO 8601)
steps[].endedAt
string | null
End time (ISO 8601)
steps[].outputSummary
string | null
Summary of the step output
steps[].outcome
string | null
Result of the agent execution. One of "completed", "incomplete", "failed", "timeout", "stopped", "denied" or "skipped". null for rows without a result
steps[].reasonCode
string | null
Reason code for the result
steps[].held
boolean
Whether the step is held because the project is paused and is waiting to resume
steps[].visit
number | null
Which visit to this step this is (increases with send-backs). null for rows without this record
steps[].reworkReason
string | null
Reason for the send-back
steps[].gateFor
string | null
For a review row, the step run (runStepId) it was raised for
steps[].routedFrom
string | null
When steps were skipped by choosing a destination, the step run (runStepId) that chose it
steps[].late
string | null
Why a result that arrived late was not used to advance the run
steps[].gate
object | null
Summary of a review step. null for rows that are not review steps
steps[].gate.decision
string | null
One of "proceed", "send_back" or "reject". null if not decided yet
steps[].gate.waitSource
string | null
What the review waits for. "human" (a person's decision) or "external" (an external condition)
plannedPlacements
array
Order of steps and placements planned to run, based on the configuration when the run started
plannedPlacements[].stepId
string | null
Step ID (UUID)
plannedPlacements[].placementId
string | null
Placement ID (UUID). null for review steps and steps without an agent
lanes
array
Status of each lane after the branch. An empty array before the branch and for runs that do not use lanes
lanes[].laneId
string
Lane ID
lanes[].name
string | null
Lane name
lanes[].position
number | null
Lane order (starting at 1)
lanes[].state
string
One of "running" (running), "waiting_gate" (awaiting review), "arrived" (waiting to join) or "closed" (ended)
lanes[].currentStepId
string | null
ID (UUID) of the step in progress in that lane. null for a lane waiting to join. For a lane that has ended, the ID of its last step may remain
lanes[].arrived
boolean
Whether the lane has reached the join point
The fields are the same regardless of the token used for the call (an application or a system integration).
The run does not exist, belongs to another project, or is not accessible
GET/v1/projects/{projectId}/runs
Lists workflow runs, newest start first. Up to the latest 100 are returned, and the next page (cursor) cannot be read. For a cycle project, the list is empty.
Array of workflow runs. The fields of an item are the same as Get a Workflow Run (GET /v1/projects/{projectId}/runs/{runId})
hasMore
boolean
When limit is 99 or less, whether there are more. When limit is 100, true when 100 items are returned (there may be no more)
Workflow runs older than the latest 100 cannot be read with this list. Find the runId in the execution history (GET /v1/projects/{projectId}/executions, which supports the next page), and read it with Get a Workflow Run (GET /v1/projects/{projectId}/runs/{runId}). Steps that have not started and steps waiting for a review do not appear in the execution history, so an old workflow run in which no step has started cannot be found.
projectId or placementId is not a UUID, or limit is not an integer between 1 and 100
403
insufficient_scope
The project:read scope is missing
403
forbidden
Called with a system integration token
403
sso_required
The user does not sign in with SSO
404
project_not_found
The project does not exist, or you are not a member
GET/v1/projects/{projectId}/runs/{runId}/config
Gets the settings at the start of a workflow run (steps, lanes, placements, and connectors). These do not change even if the project's settings are changed later (only connectionId of the connectors is resolved from the current connector information).
The steps at that time. Same fields as Step Fields (without digest; fields not in the copy are null)
lanes
array | null
The lanes at that time (id, name, parentLaneId, and stepIds). In a copy without lanes, all steps are in one "main" lane and name is null
forks
array | null
The splits at that time (id, afterStepId, laneIds, and joinId)
joins
array | null
The joins at that time (id, mode, laneIds, and nextStepId)
placements
array | null
The placements at that time (placementId, agentId, name, goal, guardrail, skills, playbookId, playbookName, runtimeConfigs, sweeps, and stepIds). goal, guardrail, skills, and playbookId are the values at the start
connectors
array | null
The connectors at that time (kind, connectionId, name, and ledgerEnabled). name is the name at the start. connectionId is resolved from the current connector information (null if disabled or deleted on the admin screen, or if it could not be checked)
sendBackLimit
number | null
Maximum number of send-backs
For a workflow run without a copy of the settings, or whose copy cannot be read, everything other than runId is null.
An execution is one run of an Agent. Each appears as one row in the execution history on the screen, and opening it shows the run record. There are executions of workflow steps (kind is "run_step"; executionId has the form rs:<number>) and executions of cycle sweeps ("sweep"; executionId is a UUID).
The values of outcome. For what the screen shows, see the Results Reference.
Value
Shown on the screen
completed
Completed
incomplete
Failed (reported by agent)
failed
Failed
timeout
Timed out
stopped
Failed (stopped)
denied
Not allowed by rules
skipped
Nothing to do
For executions that have not finished, and executions that finished without a recorded result (insufficient records), outcome is null.
GET/v1/projects/{projectId}/executions
Gets the execution history, newest start time first. Cursor-based pagination is supported. Steps that have not started and steps waiting for a review are not included.
Filter to executions that started at or after this time (ISO 8601)
to
string
—
Filter to executions that started at or before this time (ISO 8601)
placementId
string
—
Filter to executions of this placement (UUID)
stepId
string
—
Filter to executions of this step (UUID)
runId
string
—
Filter to step executions of this workflow run (UUID)
outcome
string
"all"
Filter by result. Besides the outcome values: "all" (all), "success" (completed), "problems" (incomplete, failed, timeout, stopped, and denied), "running" (running), "missing" (insufficient records), or "unmeasured" (finished in a way where completion is not measured)
q
string
—
Filter by part of the Agent name, the execution UUID, or the conversation ID (up to 200 characters). Cycle executions can be found by executionId. Workflow step executions cannot be found by rs:<number>; use steps[].executionId (a UUID) of the workflow run
limit
integer
50
Number of items per page (1-100)
cursor
string
—
Cursor for the next page (the cursor value from the previous response)
Execution ID. rs:<number> for a workflow, and a UUID for a cycle
executions[].kind
string | null
"run_step" (a workflow step) or "sweep" (a cycle sweep)
executions[].runId
string | null
ID of the workflow run. null for a cycle
executions[].stepId
string | null
Step ID
executions[].stepName
string | null
Step name
executions[].stepPosition
number | null
Position of the step
executions[].placementId
string | null
Placement ID
executions[].agentName
string | null
Agent name
executions[].attempt
number | null
Attempt number (increases when a platform failure is retried)
executions[].lane
string | null
Lane ID (workflow; "main" when there are no lanes)
executions[].outcome
string | null
Outcome (see "Outcome Values" above)
executions[].reasonCode
string | null
Reason for the outcome. For a cycle, the reason the execution ended (for example, "guardrail_blocked"); for a workflow, the reason reported by the step
executions[].resultState
string | null
"terminal" (has a result), "running" (running), "missing" (insufficient record), "unmeasured" (completion not measured), or "not_applicable" (a row that is not an Agent execution, such as a review step)
executions[].terminal
boolean | null
Whether it has finished
executions[].startedAt
string | null
Start time (ISO 8601)
executions[].endedAt
string | null
End time (ISO 8601)
executions[].summary
string | null
Final response of a workflow step (up to 2000 characters). null for a cycle (read it in the execution result)
executions[].errorMessage
string | null
Error message (cycle)
executions[].originType
string | null
How it started. For a workflow, how the workflow run started ("manual", "api", "mail", or "cron"); for a cycle, "cron" (sweep, or "Start by email") or "webhook" (trigger fire)
executions[].actorLabel
string | null
Display name of a starter that is not a user (the name of a system integration, or the sender address of an email)
executions[].gateDecision
string | null
Decision of the review step
executions[].conversationId
string | null
ID of the execution conversation (used to read the execution conversation)
hasMore
boolean
Whether there is a next page
cursor
string
Cursor for the next page. Included only when hasMore is true
You cannot filter by the reason for the outcome (reasonCode).
projectId, placementId, stepId, or runId is not a UUID, from or to is not an ISO 8601 time, outcome is not one of the values above, q exceeds 200 characters, or limit or cursor is invalid
403
insufficient_scope
The project:read scope is missing
403
forbidden
Called with a system integration token
403
sso_required
The user does not sign in with SSO
404
project_not_found
The project does not exist, or you are not a member
Gets the result of an execution (the run record). An execution of a workflow step can be read with rs:<number> from the execution history, and also with steps[].executionId (a UUID) of the workflow run. executionId in the response is rs:<number>.
In addition to the fields of an item in the execution history, the following fields are returned. summary is up to 2000 characters for a workflow, and for a cycle it is the last message of the conversation as is.
Field
Type
Description
envelope
object | null
Summary of the execution
envelope.counts
object
Numbers of tool calls (toolCalls, readCalls, mutatingSuccess, mutatingFailed, unknownCalls, opaqueCalls, workspaceWrites, mcpCalls, and mcpFailed)
envelope.completionReport
object | null
Completion report of the Agent (completed, reasonCode, fixTarget, comment, and truncated)
envelope.completionReport.fixTarget
string | null
What to fix: "goal", "skill", "handoff", "not_assigned", "connection", "rule", "guardrail", "external", or "unknown". null when there is none
envelope.completionReport.comment
string | null
Comment of the Agent (up to 2 KB; truncated is true when cut)
envelope.platformFailure
string | null
Kind of platform failure (when the outcome is failed or timeout): "cancelled", "signal_cancelled", "kill_timeout", "exception", "invalid_output", "model_refusal", "content_filter", "max_turns", or "loop_limit". null when there is none
envelope.tools
array
Names of the tools called
usedSettings
object
Settings used
usedSettings.manifest
object | null
Distributed skills (skill IDs and version IDs), the playbook, guardrails, and so on. Same as the meta of context.manifest in the execution timeline, with field names as recorded
usedSettings.mcp
object | null
MCP connections (numbers and names of configured, connected, and failed servers, and so on). Same as the meta of runtime.mcp.connected in the execution timeline. null for an execution that does not use MCP
questions
array
Questions from the Agent (eventId, at, kind, optionsCount, optionsTruncated, and answer)
questions[].answer
object | null
Answer (at, eventType, actorKind, actorRef, digest, answerKind, and optionIndex). null when there is no record of an answer
Artifacts (artifactId, name, path, format, sha256, and size; the content is not included)
files
array
Files (filename, filepath, source, isPrimary, and createdAt; mimeType and size when known). Same form as deliverables in the conversation API
configuration
object
Execution settings (policyVersion, policyDigest, policyProfile, model, and mcpConfigVersion)
request
object
Request. For a workflow, originType, originRef, triggerId, scheduledAt, runStartedAt, and reworkReason; for a cycle, cron, timezone, jobName, and originKind
jobId
string | null
Job ID. Can be compared with the jobId in the response of a trigger fire
gateFor
string | null
Which failed step execution this review was created for (rs:<number>)
routedFrom
string | null
The step execution that decided the destination (rs:<number>)
late
string | null
Why a result that arrived late was not used for progress
inputs
array
Files received from the previous step (filename only)
When …Kind in questions and gates is "human", …Ref is a user ID. Otherwise, …Ref is null.
questions includes only the questions within the newest 200 rows of the records of the execution. Read older questions in the execution timeline (rows whose section is "confirmation").
Gets the list of tool calls in an execution, page by page from the newest records to older ones. Within a page, operations are in oldest-first order. Reading to the end gives all the calls of the execution. Arguments and responses are not included.
Kind of row. "access" is the check before reading a file
operations[].resource
string | null
Tool (mcp:<server name>:<tool name> for MCP)
operations[].action
string | null
Operation
operations[].path
string | null
Path of the file read
operations[].mcpServer
string | null
Name of the MCP server
operations[].connectionId
string | null
Connector ID (connectionId of the connector API)
operations[].connectionKind
string | null
Kind of connector ("mcp" or "a2a")
operations[].attempted
boolean
Whether the call was made
operations[].effect
string | null
Result of the call
operations[].denied
string | null
Reason when it was stopped
operations[].durationMs
number | null
Time taken (milliseconds)
operations[].reason
string | null
Reason of the check (only rows whose kind is "access"; for example, "granted" or "path_not_found"). null for other rows
hasMore
boolean
Whether there are more
cursor
string
Cursor for the next page. Included only when hasMore is true
When the records of one call are split across a page boundary, rows with the same operationId appear on both pages. Treat rows with the same operationId as one call.
Gets the timeline of an execution (the records of the execution). The records of the request, evidence, actions, confirmations, and result are listed from oldest.
Summaries of the execution (items): result, settings, numbers of tool calls, and so on
timeline
object
Record rows (items)
timeline.items[].at
string
Time of the record
timeline.items[].key
number
Record ID. For "tool.access" rows, it matches operationId (row:<key>) in the list of tool calls
timeline.items[].section
string
"request", "evidence", "action", "confirmation", "result", or "other"
timeline.items[].eventType
string
Kind of record (for example, "context.manifest", "runtime.mcp.connected", "tool.invoked", or "guardrail.blocked")
timeline.items[].meta
object
Contents of each record. Field names are returned as recorded
deleted
object
Deleted conversations and resources
hasMore
boolean
Whether there are more
cursor
string
Cursor for the next page. Included only when hasMore is true
snapshotAt
string | null
When the records were read
timeline.items[] also has writer, actor, resource, action, decision, reason, ref, and available. The contents of meta differ by kind of record, and their field names are returned as recorded (snake_case). One page is up to 64 KiB.
A list of certain operations and events in a project (review decisions, changes to execution rules and members, tool records in executions, and so on). The setting changes that are kept are changes to execution rules, reviewers, the review method, members, and "Start by email" (including changes made on the screen). Changes to the library (Agents, playbooks, and skills) and other changes to steps, placements, sweeps, triggers, connectors, and notifications are not kept.
Kind of recorder: "agent", "human", "system", "human_external", "mail_external", or "unknown"
events[].actorRef
string | null
Recorder. A user ID when actorKind is "human"; otherwise a reference (client:<integration ID> for a system integration, mail:<hash> for an external email sender, and so on)
events[].decision
string | null
Decision or result
events[].reason
string | null
Reason
events[].executionId
string | null
Execution ID
events[].runId
string | null
ID of the workflow run
events[].stepName
string | null
Step name
events[].metadata
object
Contents of each record. Field names are returned as recorded. {} for a record without contents
hasMore
boolean
Whether there is a next page
cursor
string
Cursor for the next page. Included only when hasMore is true
Identify rows of system integrations by client:<integration ID> in actorRef. Read the display name of an integration from actorLabel in the execution history or the execution result.
Some records during an execution (context.manifest, runtime.*, and so on) are not included. Read them in the execution timeline.
Agent completion rate (0 to 1; completed ÷ finished). null when finished is 0
successRateStatus
string
"ok" (final), "incomplete" (provisional because a record is insufficient), or "none" (no record is insufficient and finished is 0)
succeeded
number
Number of completed executions
denominator
number
Number of finished executions (Completed plus "Failed / needs action")
executions
number
Same value as denominator
outcomes
object
Numbers per outcome (completed, incomplete, failed, timeout, stopped, denied, and skipped)
excluded
object
Numbers not counted (skipped, running, missing, and unmeasured)
durationP95Minutes
number | null
Processing time guide (p95, minutes)
runs
object
Numbers of workflow runs (total, closedDone, closedFailed, closedRejected, and cancelled) and p95Minutes
gates
array
Results per review step (stepId, position, name, mode, total, approvalRate, and sendBackRate)
human
object
Review handling (reviewsPerRun, gateWaitMedianMinutes, and interventions)
workSteps
object
Numbers counted the same way as billing steps (executions, billableExecutions, excludedExecutions, toolCalls, steps, stepsUnknown, and formulaVersion)
The Agent completion rate, runs, gates, and human count executions, workflow runs, and review requests that started in the period. workSteps counts executions that finished in the period. Because they count different executions, executions and workSteps.executions do not always match.
A review request is created when a workflow reaches a review step, or when an Agent step returns "Not allowed by rules" or "Failed (reported by agent)" and that step is set to ask for review. The reviewers decide whether to proceed, send it back, or reject it. It is the same as a review request on the screen.
Reviewers (the reviewers when the review request was created who are still members of the project) and the owners of the project can read it. Other users get 404 Not Found (workitem_not_found).
Only reviewers can decide. An owner who is not a reviewer cannot decide (403 Forbidden, not_gate_owner).
Filter by state: "assigned" (waiting for review), "done" (proceeded or sent back), or "cancelled" (rejected, or cancelled because the workflow run stopped)
projectId
string
—
Filter to the review requests of this project (UUID)
limit
integer
50
Number of items per page (1-100)
cursor
string
—
Cursor for the next page (the cursor value from the previous response)
The review request: the fields of an item in the list (workItemId, title, status, projectId, decision, requesterUserId, expiresAt, gateMode, overdue, decidedAt, createdAt, updatedAt, and canDecide) and the following fields
workitem.description
string | null
Description
workitem.runId
string | null
ID of the workflow run
workitem.runStepId
string | null
Execution ID of the step that asked for the review (rs:<number>; the same form as executionId in the execution history)
workitem.stepId
string | null
ID of the step that asked for the review (a review step, or an Agent step that asked for a review because of its outcome)
workitem.approverUserIds
array
Array of user IDs of the reviewers (the reviewers when the review request was created)
workitem.overdueAction
string | null
After the deadline: "none", "proceed", "send_back", or "reject"
workitem.evidence
object | null
Material for the review (see the table below)
workitem.decidedByKind
string | null
Kind of what decided (for example, "human"). null before a decision
workitem.decidedByRef
string | null
What decided. A user ID when decidedByKind is "human". An automatic decision after the deadline and the like is a system:… reference. null before a decision
workitem.decisionReason
string | null
Reason for the decision
workitem.sendBackToStepId
string | null
ID of the step sent back to
workitem.decisionResult
object | null
Result of the decision (decision, at, completesRun, sendBackToStepId, destinationId, and destinationStepId). completesRun is whether proceeding finished the workflow run
activities
array
History (newest first, up to 100 items)
activities[].activityId
number | null
History ID
activities[].eventType
string | null
Kind of record
activities[].decision
string | null
Decision
activities[].actorKind
string | null
Kind of recorder
activities[].actorRef
string | null
Recorder. A user ID when actorKind is "human"; otherwise a reference such as system:…
activities[].reasonCode
string | null
Reason
activities[].conversationId
string | null
Conversation ID
activities[].metadata
object
Contents of each record. Field names are returned as recorded (they may contain user IDs)
activities[].occurredAt
string | null
Time (ISO 8601)
gate
object | null
Information for the decision (see the table below)
Material for the review (workitem.evidence):
Field
Type
Description
summary
string | null
Text for the review. Usually the output of the Agents of the reviewed step; when an Agent step asked for a review because of its outcome, a summary of the outcome and its reason
conversationId
string | null
ID of the execution conversation of the reviewed step
files
array
Files of the reviewed step (same form as deliverables in the conversation API)
gateKind
string | null
Kind of review: "review" (review) or "manual" (manual work)
stepName
string | null
Name of the step that asked for the review
outcome
string | null
Outcome of the execution of the reviewed step (see "Outcome Values" of executions)
executionId
string | null
Execution ID of the reviewed step (can be read with Get the result of an execution)
reasonCode
string | null
Reason for the outcome (when an Agent step asked for a review because of its outcome)
escalateToUserId
string | null
User ID of the contact after the deadline (a person who was a member when the review request was created)
destinations
array
Steps you can choose to proceed to (destinationId, label, and stepId). An empty array when not set
Information for the decision (gate):
Field
Type
Description
projectName
string | null
Project name
projectType
string | null
Project type
stepId
string | null
ID of the step that asked for the review
stepName
string | null
Name of the step that asked for the review
stepPosition
number | null
Position of the step that asked for the review
nextStep
object | null
The next step when proceeding (stepId, name, and position). null when there is no next step
sendBackDefaultStepId
string | null
ID of the step sent back to when no send-back step is specified
sendBackCandidates
array
Steps you can specify as the send-back step (stepId, name, position, and sendBacks). sendBacks is the number of times sent back to that step
sendBackLimit
number | null
Maximum number of send-backs to one step
destinations
array
Steps you can choose to proceed to (destinationId, label, stepId, stepName, and stepPosition)
lane
object | null
Lane of the step that asked for the review (laneId, name, and position). null when there are no lanes
Reason (up to 10000 characters). Required for "send_back" and "reject"
sendBackToStepId
string
—
ID of the step to send back to (for "send_back"; a step in sendBackCandidates of gate). If omitted, it is sent back to the step in sendBackDefaultStepId
destinationId
string
—
Destination (for "proceed"; destinationId in destinations of gate; up to 64 characters). Required to proceed a review request that has destinations
commandId
string
—
A value to identify resends (up to 128 characters)
If you resend the same content with the same commandId, the result of the first request ({ "decision": …, "alreadyDecided": true }) is returned. Sending different content with the same commandId returns 409 Conflict (command_conflict).
Sending to a review request that has already been decided with a different commandId (or without commandId) returns 409 Conflict (already_decided). Get the review request again and read the current decision.
Send-backs are allowed up to the maximum number of send-backs to one step (gate.sendBackLimit).
workItemId or sendBackToStepId is not a UUID, decision is missing or not one of the values above, commandId or destinationId is only whitespace, or a field has the wrong type or length
400
invalid_body
The body is malformed JSON or not a JSON object
400
reason_required
reason is missing for "send_back" or "reject"
400
invalid_send_back_step
sendBackToStepId is not a step that can be specified as the send-back step
400
destination_required
Tried to proceed a review request that has destinations without destinationId
400
invalid_destination
destinationId is not one of the destinations, or destinationId was sent with a decision other than "proceed"
403
insufficient_scope
The project:decide scope is missing
403
forbidden
Called with a system integration token
403
sso_required
The user does not sign in with SSO
403
not_gate_owner
A member of the project who is not a reviewer
404
workitem_not_found
The review request does not exist, or you cannot read it
409
already_decided
It has already been decided
409
command_conflict
Different content was sent with the same commandId
409
invalid_state
It is not waiting for review (for example, it was cancelled)
409
send_back_limit_exceeded
The maximum number of send-backs has been reached
413
body_too_large
The body exceeds 3 MiB
415
unsupported_media_type
The Content-Type of the body is not application/json
Reads the MCP servers and A2A agents used by project executions. Only the information the other side publishes (tool names and descriptions, and the agent card) is returned. Endpoint URLs and credentials are not returned.
You can find the connector ID (connectionId) in connectors[].connectionId of Get Project and in operations[].connectionId of the list of tool calls.
Any user of the tenant can read any connector (even without being a member of the project). A connector that was disabled or deleted on the administration screen returns 404 Not Found (connector_not_found).
Sign-in to a connector is done on the project screen.
You can find conversationId in conversationId of the execution history and the execution result.
Only the person who created the project (for a copied project, the person who copied it) can read it, because project executions run in the creator's name (see Who decides what). Other owners and members get 404 Not Found. It cannot be read from a system integration.
An execution of a workflow step, and an execution of a cycle started by a webhook or an email, each have one conversation. For periodic sweeps of a cycle, the messages of each round are added to one conversation per placement and step. Because the conversation API does not link messages to executions, identify them by the messages whose sender is "User" (the request to the Agent for that round) around the start time of the execution (startedAt).
HTTP status codes that may be returned by all endpoints.
Status
Description
400 Bad Request
Invalid request parameters
401 Unauthorized
Token is invalid or missing
403 Forbidden
No access permission to the resource
404 Not Found
Resource does not exist
409 Conflict
Operation conflict, such as the resource currently being processed
413 Payload Too Large
Request body exceeds the size limit
415 Unsupported Media Type
The request body format (Content-Type) is not supported
429 Too Many Requests
Rate limit or concurrent-run limit exceeded. error.type is rate_limit_error, and error.code depends on the endpoint (for example monthly_quota_exceeded for the monthly limit and too_many_active_runs for concurrent project runs). Please wait and retry.
500 Internal Server Error
Internal server error
502 Bad Gateway
Communication error with upstream services (authentication / chat backends, etc.)
The parameter that caused the error. Included only for validation errors
error.suggested_action
string
Recommended action to take. Included only for some errors
JSON
{ "error":{ "type":"invalid_request_error", "message":"Invalid parameter: limit", "code":"invalid_parameter", "param":"limit", "suggested_action":"limit must be between 1 and 100" } }