POST /reviews with selected evidence file IDs, the service tags those files with the claim ID and begins a Box Automate workflow. Box Automate assigns the approval task, waits for the decision, then runs the approved or rejected branch.
Clone the working sample
What you are building
By the end of this tutorial, you have a working Python service that:- Exposes a
POST /reviewsendpoint your claims system uses to start a review on selected evidence files. - Writes the claim ID onto each selected evidence file as Box metadata, so the workflow can read it as a variable.
- Looks up the published Automate workflow attached to the claims folder and starts it on the selected files.
Prerequisites
Before you start, make sure you have the following:- A with Box Automate enabled. See .
- A Box platform application configured with Client Credentials Grant authentication, with Read and write all files and folders stored in Box enabled, App + Enterprise Access, and Generate user access tokens turned on. After you change those settings, re-authorize the app in the Admin Console.
- The user ID of a managed user who can build and start Automate workflows (for testing, use your own user ID). The Automate list and start endpoints return workflows that user can start. They do not return results for the enterprise service account.
- Admin access to create a metadata template, or a Box administrator who can create one for you.
- Permission to build and publish workflows in the Box Automate builder.
- Python 3.11 or higher.
- A coding agent with installed. Run
npx skills add box/box-for-aiin your project, or install the Cursor, Codex, or Claude Code plugin. See for setup.
root_readwrite, the OAuth scope behind Read and write all files and folders stored in Box. The same scope covers writing claim metadata. If a scope or feature is missing from the Developer Console, contact Box Support with the user or app context you plan to use.Configure Box once
These steps happen in the Box Admin Console and Automate builder. An agent cannot do them for you. Complete them before you build the service.-
Create a
Claimmetadata template in the Admin Console under Metadata. Add two text fields: Claim ID and Review status. Click Save, click back into the template, then copy the template key. Confirm the generated field keys withGET /2.0/metadata_templates/enterprise/<TEMPLATE_KEY>/schema. This tutorial assumesclaimIdandreviewStatus. -
Configure Client Credentials Grant for a managed user. In Developer Console > your CCG app > Configuration, set application access to App + Enterprise Access, enable Generate user access tokens, and save. Re-authorize the app in the Admin Console. Copy the managed user’s ID (Admin Console > Users & Groups, or
GET /2.0/users/mewith that user’s token). You pass this ID asBOX_USER_IDso the service authenticates as that user, not as the enterprise service account. -
Create a
Claims Reviewfolder in Box as that managed user (or invite them as an Editor), note its folder ID from the URL, and upload two or three sample PDFs. Without folder access for the user your app acts as, file and metadata calls return 404. -
Build and publish a Manual Start workflow in the Box Automate builder. For a full walkthrough of the builder UI, see .
- Open Automate, select New+ → Workflow, and name it
Claims evidence review. - Drag Manual Start onto the canvas and scope it to the
Claims Reviewfolder. - Add a Task Action outcome. Set the type to Approval, assign the file to Trigger: File, and for testing set both complete and manage to Workflow owner. Optionally include the Claim ID metadata field in the task message.
- Branch on Approved and Rejected, and add Send Notification on each branch.
- Select Activate (not only Save).
- Open Automate, select New+ → Workflow, and name it
- Optional: inspect the workflow IDs so you recognize the response shape later. Use an access token for the same managed user your app will act as:
id is the action ID, not the workflow ID. Passing the action ID in the path returns a 404.
Build the service
Choose how to scaffold the service. Both paths produce the same app; continue to Run and verify when you finish.- Build with an agent
- Build by hand
.env; otherwise leave them and fill credentials yourself after scaffolding..env.example to .env and fill in your credentials, user ID, folder ID, and template key. Put each variable on its own line.Run and verify
- Start the server (venv activated):
- In a second terminal, start a review. Use file IDs from the sample PDFs in
Claims Review, not the folder ID:
-
Confirm in Box:
- Open an evidence file → Metadata tab shows claim
CLM-1042and statusin_review. - As the task assignee, open the approval task and confirm the claim ID appears in the message.
- Approve or reject from the file’s Activity sidebar panel, and confirm the matching branch runs.
- Open an evidence file → Metadata tab shows claim
Troubleshooting
ModuleNotFoundError: No module named '...'
ModuleNotFoundError: No module named '...'
source .venv/bin/activate from the project directory before running any python3 commands. Each new terminal tab needs its own activation.invalid_client: The client credentials are invalid
invalid_client: The client credentials are invalid
.env file:- Verify
BOX_CLIENT_IDandBOX_CLIENT_SECRETmatch the values in Developer Console > Configuration. - Ensure the app is authorized and its type is Client Credentials Grant.
invalid_grant: Grant credentials are invalid
invalid_grant: Grant credentials are invalid
BOX_USER_ID is the managed user’s ID (digits only, no spaces).Empty entries list from GET /2.0/automate_workflows
Empty entries list from GET /2.0/automate_workflows
- You are authenticated as a managed user who can run Automate, not as the enterprise service account. A user token that returns the workflow while the app returns
entries: []usually means the app still usesenterprise_idinstead ofuser_id. - The workflow is published, not saved as a draft.
- The workflow has a Manual Start trigger.
- The trigger’s folder is the folder whose ID you passed as
folder_id. - The managed user can access that folder.
404 Not Found on an Automate endpoint
404 Not Found on an Automate endpoint
- Box Automate is not enabled for your enterprise. Ask your admin to .
- Your account is on the Free Developer Plan, where these endpoints are unavailable.
- The
box-version: 2026.0header is missing. - You passed the action ID in the URL path. The path takes
entries[].workflow.id; the body takesentries[].id.
400 Action not found when starting the workflow
400 Action not found when starting the workflow
BOX_USER_ID, then confirm that file_ids contains at least one ID, at most 20 IDs, and that every file is within the Manual Start folder scope.400 Bad Request when starting the workflow
400 Bad Request when starting the workflow
file_ids contains at least one ID, that it holds no more than 20 IDs, and that every file is within the folder scope configured on the Manual Start trigger.The approval task shows no claim ID
The approval task shows no claim ID
tag_evidence match the fields[].key values returned by GET /2.0/metadata_templates/enterprise/:key/schema, and that the task message references the Claim ID field from that template.403 Forbidden
403 Forbidden
The agent used /2.0/workflows or invented SDK methods
The agent used /2.0/workflows or invented SDK methods
box-sdk-gen. Re-paste the prompt and emphasize client.make_request with box-version: 2026.0, or select the Build by hand tab in Build the service for the tested modules.Scaling to production
Cache the workflow and action IDs
Cache the workflow and action IDs
GET /2.0/automate_workflows on every review to resolve the workflow by name. That list call is optional in production. The IDs you need are stable for a given published workflow:find_workflow_action. Keep the list lookup as a fallback if start begins failing (for example after you replace the workflow in the builder).Make review starts idempotent
Make review starts idempotent
reviewStatus: in_review alone as a lock: this tutorial sets that value when a review starts and never clears it, so a naive skip would block legitimate resubmits.Prefer an idempotency check in your claims system (for example, ignore a repeat claim_id + file_ids start while a review is open), or inspect the file for an incomplete approval task before calling start. If you use metadata as the lock, add an Automate outcome on the approved and rejected branches that updates reviewStatus when the decision is done.Secure the endpoint
Secure the endpoint
POST /reviews needs authentication in production. Verify a signed request from your claims system, or place the service behind your existing gateway. Keep credentials in a secret manager rather than a .env file, and never expose user or app tokens to a browser client. Prefer a dedicated managed user with the least Automate and folder access your flow needs, rather than a personal admin account.Plan for fields at start
Plan for fields at start
claims_metadata.py makes that a single-module change.Handle more than 20 files
Handle more than 20 files
