Manage governance workflow approvals (Inbox)
Use client.inbox in the Atlan Python SDK to programmatically inspect and bulk-approve or bulk-reject governance workflow tasks—the items you see in Atlan's Inbox.
This system is enabled per tenant via Admin → Labs → Governance Workflows and Inbox. When it's on, new requests are handled by governance workflows and appear in the Inbox; the classic Requests module continues to hold any older requests. For the classic module, see Manage requests. A tenant can have items in both systems at the same time.
Understand three identifiers
Working with the Inbox involves three different GUIDs—knowing which one to use where saves a lot of confusion:
| Identifier | What it means | Where to use it |
|---|---|---|
| Task GUID | the Inbox item itself (a Task asset) | group_key in approve_all / reject_all to action that one task |
| Related-asset GUID | the asset the request targets | group_key to action every pending task on that asset in one call |
| Workflow-request GUID | the underlying approval record | client.inbox.get() only—the detail view with status and approver routing |
The workflow-request GUID isn't a top-level task field—it's embedded in the task's task_actions fulfillment URL (.../approval-workflow-requests/<guid>). The discovery example below shows how to extract it. Passing a task GUID to get() fails—only the workflow-request GUID works there.
Discover pending tasks
Inbox tasks are Task assets, so you list them with a regular search:
- Python
import re
from pyatlan.client.atlan import AtlanClient
from pyatlan.model.assets import Task
from pyatlan.model.fluent_search import CompoundQuery, FluentSearch
client = AtlanClient()
search = (
FluentSearch()
.where(CompoundQuery.active_assets())
.where(CompoundQuery.asset_type(Task)) # (1)
.include_on_results(Task.TASK_RECIPIENT) # (2)
.include_on_results(Task.TASK_EXECUTION_ACTION) # (3)
.include_on_results(Task.TASK_RELATED_ASSET_GUID)
.include_on_results(Task.TASK_ACTIONS)
).to_request()
for task in client.asset.search(search):
if task.task_execution_action != "PENDING":
continue
wf_request_guid = None
if task.task_actions: # (4)
match = re.search(
r"approval-workflow-requests/([0-9a-f-]{36})",
str(task.task_actions[0].task_action_fulfillment_url),
)
wf_request_guid = match.group(1) if match else None
print(task.guid, task.task_recipient, task.task_related_asset_guid, wf_request_guid)
- Inbox items are assets of type
Task. - The recipient is the user the task is waiting on—only this identity can action the task (see the warning below).
- Execution state:
PENDING,APPROVED,REJECTED, orWITHDRAWN. - Extracts the workflow-request GUID for use with
client.inbox.get().
Inspect workflow request
To see a request's status and its approver routing:
- Python
request = client.inbox.get(guid=wf_request_guid) # (1)
print(request.status, request.approval_workflow_request_type)
print(request.approval_details) # (2)
- Use the workflow-request GUID (not the task GUID).
approval_detailsshows the configured approvers and each one's decision—useful for understanding who a pending task is waiting on.
Bulk-approve or reject tasks
Approvals and rejections are group operations: you name a group with group_key, and every pending task in that group (addressed to you) is actioned in a single server-side call.
- Python
- Raw REST API
# a task GUID actions exactly that one task
response = client.inbox.approve_all(
group_key="24be8e31-4857-4f1a-b9e9-281db6c9f934", # (1)
comment="Approved via automation",
)
print(response.total_tasks) # 1
# an asset GUID actions EVERY pending task on that asset
response = client.inbox.approve_all(
group_key="48056772-a24d-4643-a880-affec0164e9f", # (2)
sub_type="DATA_ACCESS", # (3)
comment="Bulk approved",
)
print(response.total_tasks) # e.g. 2
group_key= task GUID → a group of one.group_key= related-asset GUID → all pending tasks on that asset at once.- Optionally narrow by task sub-type:
DATA_ACCESS,CHANGE_MANAGEMENT,PUBLICATION_MANAGEMENT, orPOLICY_APPROVAL(seeApprovalWorkflowRequestType). Usereject_all()with the same arguments to reject.
curl -s -X PUT "https://tenant.atlan.com/api/service/approval-workflow-requests/actions/bulk" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"group_key": "48056772-a24d-4643-a880-affec0164e9f", "decision": "APPROVED", "comment": "Bulk approved"}'
A successful call means the tasks were queued (total_tasks tells you how many). The state change lands a few seconds later—re-query the tasks and check task_execution_action if you need confirmation.
Who can action tasks
Only the user a task is addressed to (its task_recipient) can approve or reject it. An admin role doesn't override this. If none of a group's pending tasks are addressed to your token's identity, the API responds with error 1003 ("No pending tasks found for the specified group") even when the group visibly contains pending tasks for someone else. The same error also appears when every task in the group has already been actioned; check task_execution_action to tell the two cases apart.
The governance workflow builder currently supports only human users and groups as approvers—an API key's or OAuth client's service account can't be named as an approver. That means Inbox approvals can only be automated with a token whose identity is a configured approver (for example, a user bearer token). Note that user session tokens are short-lived (~15 minutes), so they aren't a durable path for unattended automation. If you need headless Inbox approval, raise this with your Atlan contact—supporting service accounts as workflow approvers is a known product ask.
Good to know
- Async client: every method is also available on
AsyncAtlanClient. Useawait client.inbox.approve_all(...). - A requester can't approve their own request unless the workflow's approver configuration routes it back to them.
get()with an unknown GUID currently returns a server error rather thanNone; treat errors fromget()as "not a workflow-request GUID."