Skip to content

Approve or reject up to 50 pending approvals at once

POST /automation-approval/resolve-batch

One decision and one optional note for up to 50 ids. Each is answered on its own with the same checks as the single resolve, so one refusal never undoes another: every id gets a result, either `ok` with the settled approval or the error the single resolve would have given (`not_found`, `not_an_approver`, `approval_already_voted`, `approval_self_approval_forbidden`, `approval_not_pending`, `approval_expired`). Payments and approvals that require step-up are never answered in bulk: they are refused per item with `approval_bulk_excluded` (rows carry `can_bulk_resolve`). 403 `approval_human_only` for an AI surface.

Request Body

decisionstring
Possible values:
approvereject
idsstring[]
notestring

Response Body

failedinteger
resultobject[]
approvalobject
47 properties
actionstring,null

The exact thing being asked in one sentence ("Pay $1,250.00 to Acme Ltd from Stripe"); set for a payment, null for an ordinary approval whose title is the sentence.

approver_countinteger
approver_previewobject
2 properties
countinteger
namesstring[]
automation_idstring
automation_namestring
bulk_resolve_blocked_reasonstring,null

Why a request the caller can answer on its own is kept out of a bulk decision, in words.

can_bulk_resolveboolean

May be answered in a bulk decision: can_resolve, and not a payment or a step-up gate (those are answered one at a time).

can_resolveboolean
can_view_automationboolean

The caller may open the workflow (an approver is not necessarily able to).

can_view_runboolean

The caller may open the run (use access or better on the workflow).

console_urlstring
created_atstring
current_versioninteger,null

The workflow's current published version number.

deliverynull | object

What became of the Slack and email delivery, per channel, as counts of approvers per outcome. Counts only: never an address, token or message. Null before the first delivery runs and on requests from before outcomes were recorded.

One of
object · 4 properties
channelnull | object
One of
object · 5 properties
disabledinteger
failedinteger
no_installationinteger
sentinteger
user_not_foundinteger
emailobject

Email.

5 properties
disabledinteger
failedinteger
no_installationinteger
sentinteger
user_not_foundinteger
skippedobject

Approvers no channel was attempted for: inactive are no longer active members, over_limit are past the cap on how many people one request messages. Absent when none were skipped.

2 properties
inactiveinteger
over_limitinteger
slackobject

Slack direct messages.

5 properties
disabledinteger
failedinteger
no_installationinteger
sentinteger
user_not_foundinteger
delivery_linestring,null

Who was told about this request and, when someone was not, why, in plain words ("Notified 1 of 1 · Slack, email"). Computed from delivery and the caller's own standing, so a reader who was never asked to approve is told they were not notified.

detailsobject[]
2 properties
labelstring
valuestring
details_omittedinteger

Detail rows the step produced beyond the ones kept; 0 when nothing was cut.

escalate_atstring,null
escalated_atstring,null
expires_atstring
from_older_versionboolean

Pending, and its run is pinned to an older version than the workflow's current published one: approving resumes that run with its old steps. False once settled. A heads-up only; it never changes what an answer does.

gated_tierstring
idstring
is_approverboolean
messagestring
message_formatstring

How message is written. Display only: draw slack mrkdwn or a small Markdown subset as formatting, never as HTML.

Possible values:
textslackmarkdown
notifiedobject
2 properties
countinteger
totalinteger
on_approvestring

What happens if the caller approves, in plain words.

on_rejectstring

What happens to the run if the caller rejects, in plain words.

owner_display_namestring,null
owner_user_idstring
prevent_self_approvalboolean
resolution_notestring,null
resolve_requiresobject
2 properties
blocked_reasonstring,null
step_upboolean
resolved_atstring,null
resolved_bystring,null
resolved_by_display_namestring,null
resolved_viastring,null
run_idstring
run_versioninteger,null

The version number the run is pinned to.

statusstring
Possible values:
pendingapprovedrejectedexpiredcancelled
step_keystring
step_pathstring
step_up_requiredboolean
titlestring
trigger_actor_user_idstring,null
version_idstring
errorobject
2 properties
codestring
messagestring
idstring
okboolean
succeededinteger
curl -X POST 'https://api.elaichi.ai/automation-approval/resolve-batch' \
  -H 'Authorization: Bearer $ELAICHI_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"ids":[],"decision":"approve","note":"your_note"}'
const body = {
  "ids": [],
  "decision": "approve",
  "note": "your_note"
};

const response = await fetch('https://api.elaichi.ai/automation-approval/resolve-batch', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ' + process.env.ELAICHI_API_TOKEN,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(body),
});

const data = await response.json();
console.log(data);
import os
import requests

url = "https://api.elaichi.ai/automation-approval/resolve-batch"
headers = {
    "Authorization": f"Bearer {os.environ['ELAICHI_API_TOKEN']}",
    "Content-Type": "application/json",
}
payload = {
    "ids": [],
    "decision": "approve",
    "note": "your_note"
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())