Work
Approvals
Actions the assistant staged for a person to review before they go out. The API calls a batch of staged actions a cart. Show the approval to the user, then approve it with its `contentHash` so exactly what they saw is sent.
GET/portal/carts
List approvals
Returns the approvals waiting on the user, newest first, up to 50. Filter with `status`.
Query parameters
statusstringComma-separated subset of pending_approval, time_boxed. Default: both.
Responses
200Approvals
ok reqboolean
carts reqobject[]
id reqstringThe approval (cart) id.
taskIdstring | null
taskTitlestring
assistantNamestring | null
status reqenumopen: the assistant is still adding actions. submitted: handed over, approval mode being decided. pending_approval: waiting for the user. time_boxed: runs when the window ends unless stopped. approved: approved and queued. executing: being sent. executed: done. cancelled: cancelled by a person with the cancel endpoint or by a time-boxed window set to cancel. rejected: declined from an approval link, such as the Reject link in an approval email. failed: could not be sent.opensubmittedpending_approvaltime_boxedapprovedexecutingexecutedcancelledrejectedfailed
resolvedApprovalModeenumautotime-boxedmanual
timeBoxedExpiresAtstring | nullFor time_boxed: when the window ends.
timeBoxedExpiryenumWhat happens when a time-boxed window ends.executecancel
dispatches reqobject[]
indexintegerPosition in the approval; use it in the dispatch paths.
typestringKind of action, such as a message sent as the assistant or a calendar change.
platformstring | nullChannel, such as email or sms.
fromstring
tostring[]
ccstring[]
bccstring[]
subjectstring
bodystring
descriptionstringPlain description of the action.
payloadobject | nullAction-specific detail, such as the full event for a calendar change.
filesobject[]Attachments that go out with the action.
filenamestring | null
mimeTypestring | null
sizenumber | null
fileIdstring | null
editedByUserbooleanTrue when the text shown is the user's own edit; it is sent exactly as written.
currentVersionIdstring | null
validUntilstring | nullWhen the content stops being true; null with evergreen false means none declared.
evergreenboolean
contentHash reqstringHash of exactly the content shown. Send it back on approve.
createdAtstring
updatedAtstring
400status names no valid value.
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
Request
curl 'https://api.agnt.ai/portal/carts' \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]"
Response
{
"ok": true,
"carts": [
{
"id": "6660c4a1f2e3b7d8a9c01234",
"status": "pending_approval",
"dispatches": [
{
"index": null,
"type": null,
"platform": null,
"from": null
}
],
"contentHash": "9f2c1b7e4a"
}
]
}
GET/portal/carts/{cartId}
Retrieve an approval
Retrieves an approval with its staged actions and the `contentHash` to approve it with.
Path parameters
Responses
200Approval
ok reqboolean
cart reqobject
id reqstringThe approval (cart) id.
taskIdstring | null
taskTitlestring
assistantNamestring | null
status reqenumopen: the assistant is still adding actions. submitted: handed over, approval mode being decided. pending_approval: waiting for the user. time_boxed: runs when the window ends unless stopped. approved: approved and queued. executing: being sent. executed: done. cancelled: cancelled by a person with the cancel endpoint or by a time-boxed window set to cancel. rejected: declined from an approval link, such as the Reject link in an approval email. failed: could not be sent.opensubmittedpending_approvaltime_boxedapprovedexecutingexecutedcancelledrejectedfailed
resolvedApprovalModeenumautotime-boxedmanual
timeBoxedExpiresAtstring | nullFor time_boxed: when the window ends.
timeBoxedExpiryenumWhat happens when a time-boxed window ends.executecancel
dispatches reqobject[]
indexintegerPosition in the approval; use it in the dispatch paths.
typestringKind of action, such as a message sent as the assistant or a calendar change.
platformstring | nullChannel, such as email or sms.
fromstring
tostring[]
ccstring[]
bccstring[]
subjectstring
bodystring
descriptionstringPlain description of the action.
payloadobject | nullAction-specific detail, such as the full event for a calendar change.
filesobject[]Attachments that go out with the action.
filenamestring | null
mimeTypestring | null
sizenumber | null
fileIdstring | null
editedByUserbooleanTrue when the text shown is the user's own edit; it is sent exactly as written.
currentVersionIdstring | null
validUntilstring | nullWhen the content stops being true; null with evergreen false means none declared.
evergreenboolean
contentHash reqstringHash of exactly the content shown. Send it back on approve.
createdAtstring
updatedAtstring
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404No such approval for this user.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>' \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]"
Response
{
"ok": true,
"cart": {
"id": "6660c4a1f2e3b7d8a9c01234",
"status": "pending_approval",
"dispatches": [
{
"index": 1,
"type": "type",
"platform": "platform",
"from": "from"
}
],
"contentHash": "9f2c1b7e4a"
}
}
POST/portal/carts/{cartId}/approve
Approve an approval
Approves the staged actions exactly as the user saw them and queues them to run, with no further model step. Pass the `contentHash` from the read you showed the user. If the content changed since then, the call returns `409` and nothing is sent. Call it only on the user's explicit decision.
Path parameters
Request body
contentHash reqstringThe contentHash from the latest read of this approval.
reasonstringOptional note.
Responses
200Approved and queued
okboolean
cartIdstring
statusenumapproved
400content_hash_required, cart_already_resolved (not awaiting approval) or cart_task_closed (the task closed and the draft was withdrawn).
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404No such approval for this user.
409cart_content_changed: the content changed since it was read. Read it again and show the user before approving.
500Queuing failed; the approval is left as it was. Retry.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/approve' \
-X POST \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]" \
-H "Content-Type: application/json" \
-d '{
"contentHash": "9f2c1b7e4a"
}'
Response
{
"ok": true,
"cartId": "6660c4a1f2e3b7d8a9c01234",
"status": "approved"
}
POST/portal/carts/{cartId}/cancel
Cancel an approval
Cancels the staged actions and sets the status to `cancelled`. Nothing is sent. The assistant receives the optional `reason` and adjusts.
Path parameters
Request body
reasonstringOptional reason passed to the assistant.
Responses
200Cancelled
okboolean
cartIdstring
statusenumcancelled
400Already executed, cancelled or rejected.
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404No such approval for this user.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/cancel' \
-X POST \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]" \
-H "Content-Type: application/json" \
-d '{
"reason": "Approved by Jane"
}'
Response
{
"ok": true,
"cartId": "6660c4a1f2e3b7d8a9c01234",
"status": "cancelled"
}
PATCH/portal/carts/{cartId}/dispatches/{index}/edit
Edit a staged action
Changes the subject or body of one staged action, or how long its content stays valid. The edit is kept as a new version and changes the `contentHash`. Recipients and payload cannot be changed with this call.
Path parameters
cartId reqstring
index reqstring
Request body
subjectstring
bodystring
validUntilstringISO 8601 time with offset, in the future. Replaces the declared validity.
evergreenbooleantrue: the content never goes stale. Replaces the declared validity.
Responses
200Updated approval
ok reqboolean
cart reqobject
id reqstringThe approval (cart) id.
taskIdstring | null
taskTitlestring
assistantNamestring | null
status reqenumopenpending_approvaltime_boxedapprovedexecutingexecutedcancelledrejectedfailed
resolvedApprovalModeenumautotime-boxedmanual
timeBoxedExpiresAtstring | nullFor time_boxed: when the window ends.
timeBoxedExpiryenumWhat happens when a time-boxed window ends.executecancel
dispatches reqobject[]
indexintegerPosition in the approval; use it in the dispatch paths.
typestringKind of action, such as a message sent as the assistant or a calendar change.
platformstring | nullChannel, such as email or sms.
fromstring
tostring[]
ccstring[]
bccstring[]
subjectstring
bodystring
descriptionstringPlain description of the action.
payloadobject | nullAction-specific detail, such as the full event for a calendar change.
filesobject[]Attachments that go out with the action.
filenamestring | null
mimeTypestring | null
sizenumber | null
fileIdstring | null
editedByUserbooleanTrue when the text shown is the user's own edit; it is sent exactly as written.
currentVersionIdstring | null
validUntilstring | nullWhen the content stops being true; null with evergreen false means none declared.
evergreenboolean
contentHash reqstringHash of exactly the content shown. Send it back on approve.
createdAtstring
updatedAtstring
400Invalid or empty edit, a change to to, cc, bcc or payload, or an action type that cannot be edited (edit_not_supported)
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404Approval or action not found.
409cart_not_editable: the approval is no longer pending_approval or time_boxed.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/dispatches/<index>/edit' \
-X PATCH \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]" \
-H "Content-Type: application/json" \
-d '{
"subject": "subject",
"body": "Prefers morning meetings.",
"validUntil": "2026-10-15T14:30:00Z",
"evergreen": true
}'
Response
{
"ok": true,
"cart": {
"id": "6660c4a1f2e3b7d8a9c01234",
"status": "pending_approval",
"dispatches": [
{
"index": 1,
"type": "type",
"platform": "platform",
"from": "from"
}
],
"contentHash": "9f2c1b7e4a"
}
}
PATCH/portal/carts/{cartId}/dispatches/{index}
Update a staged action
Updates one staged action, including its recipients and payload. Only the fields you send change, and the `contentHash` changes.
Path parameters
cartId reqstring
index reqstring
Request body
subjectstring
bodystring
tostring[]
ccstring[]
bccstring[]
payloadobjectAction-specific fields to change.
Responses
200Updated approval
ok reqboolean
cart reqobject
id reqstringThe approval (cart) id.
taskIdstring | null
taskTitlestring
assistantNamestring | null
status reqenumopenpending_approvaltime_boxedapprovedexecutingexecutedcancelledrejectedfailed
resolvedApprovalModeenumautotime-boxedmanual
timeBoxedExpiresAtstring | nullFor time_boxed: when the window ends.
timeBoxedExpiryenumWhat happens when a time-boxed window ends.executecancel
dispatches reqobject[]
indexintegerPosition in the approval; use it in the dispatch paths.
typestringKind of action, such as a message sent as the assistant or a calendar change.
platformstring | nullChannel, such as email or sms.
fromstring
tostring[]
ccstring[]
bccstring[]
subjectstring
bodystring
descriptionstringPlain description of the action.
payloadobject | nullAction-specific detail, such as the full event for a calendar change.
filesobject[]Attachments that go out with the action.
filenamestring | null
mimeTypestring | null
sizenumber | null
fileIdstring | null
editedByUserbooleanTrue when the text shown is the user's own edit; it is sent exactly as written.
currentVersionIdstring | null
validUntilstring | nullWhen the content stops being true; null with evergreen false means none declared.
evergreenboolean
contentHash reqstringHash of exactly the content shown. Send it back on approve.
createdAtstring
updatedAtstring
400Invalid or empty patch.
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404Approval or action not found.
409cart_not_editable: the approval is no longer pending_approval or time_boxed.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/dispatches/<index>' \
-X PATCH \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]" \
-H "Content-Type: application/json" \
-d '{
"subject": "subject",
"body": "Prefers morning meetings.",
"to": [
"to"
],
"cc": [
"cc"
]
}'
Response
{
"ok": true,
"cart": {
"id": "6660c4a1f2e3b7d8a9c01234",
"status": "pending_approval",
"dispatches": [
{
"index": 1,
"type": "type",
"platform": "platform",
"from": "from"
}
],
"contentHash": "9f2c1b7e4a"
}
}
DELETE/portal/carts/{cartId}/dispatches/{index}
Remove a staged action
Removes one action from a pending approval. An approval with no actions left stays pending until you cancel it.
Path parameters
cartId reqstring
index reqstring
Responses
200Updated approval
ok reqboolean
cart reqobject
id reqstringThe approval (cart) id.
taskIdstring | null
taskTitlestring
assistantNamestring | null
status reqenumopenpending_approvaltime_boxedapprovedexecutingexecutedcancelledrejectedfailed
resolvedApprovalModeenumautotime-boxedmanual
timeBoxedExpiresAtstring | nullFor time_boxed: when the window ends.
timeBoxedExpiryenumWhat happens when a time-boxed window ends.executecancel
dispatches reqobject[]
indexintegerPosition in the approval; use it in the dispatch paths.
typestringKind of action, such as a message sent as the assistant or a calendar change.
platformstring | nullChannel, such as email or sms.
fromstring
tostring[]
ccstring[]
bccstring[]
subjectstring
bodystring
descriptionstringPlain description of the action.
payloadobject | nullAction-specific detail, such as the full event for a calendar change.
filesobject[]Attachments that go out with the action.
filenamestring | null
mimeTypestring | null
sizenumber | null
fileIdstring | null
editedByUserbooleanTrue when the text shown is the user's own edit; it is sent exactly as written.
currentVersionIdstring | null
validUntilstring | nullWhen the content stops being true; null with evergreen false means none declared.
evergreenboolean
contentHash reqstringHash of exactly the content shown. Send it back on approve.
createdAtstring
updatedAtstring
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404Approval or action not found.
409cart_not_editable: the approval is no longer pending_approval or time_boxed.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/dispatches/<index>' \
-X DELETE \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]"
Response
{
"ok": true,
"cart": {
"id": "6660c4a1f2e3b7d8a9c01234",
"status": "pending_approval",
"dispatches": [
{
"index": 1,
"type": "type",
"platform": "platform",
"from": "from"
}
],
"contentHash": "9f2c1b7e4a"
}
}
GET/portal/carts/{cartId}/snapshots
List undoable actions
Returns one entry per action that ran, with whether it can still be undone and until when.
Path parameters
Responses
200Snapshots
cartIdstring
countinteger
snapshotsobject[]
dispatchIndexinteger
dispatchTypestring
resourceTypestring
reversiblebooleanWhether the action can be reverted after it ran. A non-reversible action can only be stopped while it waits to send.
undoStatusenumavailableundoneexpirednot_applicable
undoExpiresAtstring | null
undoneAtstring | null
undoAvailableboolean
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404No such approval for this user.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/snapshots' \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]"
Response
{
"cartId": "6660c4a1f2e3b7d8a9c01234",
"count": 42,
"snapshots": [
{
"dispatchIndex": 1,
"dispatchType": "dispatchtype",
"resourceType": "resourcetype",
"reversible": true
}
]
}
POST/portal/carts/{cartId}/dispatches/{index}/undo
Undo an action
Reverts one action that ran, or stops one that is still waiting to send. Available until the action's undo window closes.
Path parameters
cartId reqstring
index reqstring
Responses
200Undone
okboolean
undoneboolean
typeenumreversedcancelled_during_delay
dispatchTypestring
resultobject
400Not available to undo, window expired, or undo_not_supported for this action type.
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404Approval or snapshot not found.
409The target changed since and cannot be reverted safely.
410The target no longer exists.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/dispatches/<index>/undo' \
-X POST \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]"
Response
{
"ok": true,
"undone": true,
"type": "reversed",
"dispatchType": "dispatchtype"
}
POST/portal/carts/{cartId}/undo
Undo all actions
Reverts every reversible action in the approval, in reverse order, and reports the result for each.
Path parameters
Responses
200Result per action
okboolean
cartIdstring
undoneinteger
skippedinteger
expiredinteger
failedinteger
detailsobject[]
403The caller is not acting as a user: send X-User-Email with an account key, or use a user-scoped key. Certificate tokens and AGNT console sessions are refused.
404No such approval for this user.
Request
curl 'https://api.agnt.ai/portal/carts/<cartId>/undo' \
-X POST \
-H "Authorization: Bearer ak_live_..." \
-H "X-User-Email: [email protected]"
Response
{
"ok": true,
"cartId": "6660c4a1f2e3b7d8a9c01234",
"undone": 1,
"skipped": 1
}
GET/portal/account/kill-switch
Retrieve the kill switch
Returns whether outbound actions are frozen for the whole account. While the account is frozen, creating and running tasks returns `423` with `error_code: "KILL_SWITCH_ENGAGED"`. Only a person signed in to your hosted app can freeze or release the account; API keys and tokens cannot. To stop one task, stop the task instead.
Responses
200State
stateenumfrozen blocks every outbound action, reply and inbound processing for the account; active is normal operation.activefrozen
engagedAtstring | nullWhen the current freeze started; null while active
engagedByobject | nullWho engaged the current freeze: actor is their email
actorstring | null
sourcestring | null
reasonstring | null
Request
curl 'https://api.agnt.ai/portal/account/kill-switch' \
-H "Authorization: Bearer ak_live_..."
Response
{
"state": "active",
"engagedAt": "2026-10-15T14:30:00Z",
"engagedBy": {
"actor": "actor",
"source": "source"
},
"reason": "Approved by Jane"
}