From upload to routed review with Box Extract and OpenAI Decisions API
Imagine a certificate of insurance (COI) arriving in Box as a PDF through a File Request, while the project’s insurance requirements sit in a sibling folder. Box AI extracts key fields from both documents, and the application saves them as metadata on the uploaded COI. It then sends the extracted v

Posted on Oct 21 • Originally published at blog.box.com
Imagine a certificate of insurance (COI) arriving in Box as a PDF through a File Request, while the project’s insurance requirements sit in a sibling folder. Box AI extracts key fields from both documents, and the application saves them as metadata on the uploaded COI. It then sends the extracted values and filename to the OpenAI Decisions API, which answers a closed-ended question: which of a set of three predefined workflows fits the evidence? The application then uses the selected route and returns a confidence value in its routing rules.
A Box V2 webhook starts the workflow as soon as the upload reaches the intake folder. The application creates a Box task with the evidence and reason, assigns it to the configured reviewer, and adds the insurance specialist as a file collaborator when needed. Box is where the documents arrive and where people review them. Let’s see how this works under the hood.
Every route creates a Box review task with context for the reviewer. The reviewer is configured by a Box user ID in the application setup. For request_endorsement and specialist_review, the insurance specialist is also added as a collaborator on the uploaded file.
Box AI extracts fields such as the project completion date, required liability limits, named insured, policy expiration, and additional-insured evidence. Then, the application passes these fields and the uploaded filename to Decisions as shared context. The fixed choices let the application create a task that explains why the file needs review.
If the route is unclear or unsupported, or its confidence falls below the defined application’s threshold, the code sends the case to specialist_review. The task includes the project requirements and extracted COI values, giving the reviewer a useful starting point.
These two APIs have separate jobs. Box AI Extract turns each source document into a small set of requested fields. The Decisions API evaluates this context and selects the next workflow route.
First, the Box SDK calls Box’s structured extraction endpoint. The request identifies a Box file and supplies field definitions with prompts.
def extract ( client: BoxClient, file_id: str, fields: list ) -> dict: response = client. ai. create_ai_extract_structured ( items = [ AiItemBase ( id = file_id )], fields = fields, ) return plain_dict ( getattr ( response, " answer ", {})) Enter fullscreen mode Exit fullscreen mode Data is pulled both from project requirements and an incoming COI document.
coi = extract ( client, file_id, COI_FIELDS ) requirements = extract ( client, state [ " requirements_file_id " ], REQUIREMENT_FIELDS ) Enter fullscreen mode Exit fullscreen mode Next, the application builds a compact text input containing the uploaded filename and both keyed extraction results. It sends that evidence to the Decisions API with a choice question and the three routes as allowed values:
decision = OpenAI (). decisions. create ( model = model, input = ( f " { prompt } \n\n " f " Uploaded filename: { file_name } \n\n " f " Project requirements extracted from the Box reference document: \n " f " { json. dumps ( requirements, indent = 2, default = str ) } \n\n " f " COI evidence extracted from the Box upload: \n " f " { json. dumps ( coi, indent = 2, default = str ) } " ), questions = [ { " type ": " choice ", " name ": " route ", " instructions ": " Choose one administrative workflow route based on the evidence and criteria. ", " choices ": ROUTES, } ], ) Enter fullscreen mode Exit fullscreen mode The choices include descriptions explaining when each route applies.
ROUTES = [ { " value ": " request_endorsement ", " description ": " The COI is readable and the needed coverage details are present, but the separate required additional-insured endorsement is missing. Create a review task so the project team can request the updated document. ", }, { " value ": " specialist_review ", " description ": " A required date, limit, coverage detail, named party, or document is missing, unreadable, contradictory, or otherwise unclear.
Assign a specialist to review. ", }, { " value ": " ready_for_human_review ", " description ": " The file appears to contain the requested coverage details and separate endorsement. Create a review task.
", }, ] Enter fullscreen mode Exit fullscreen mode The API returns a typed choice instead of a paragraph the application must parse. The app checks that the answer is usable, applies its confidence policy, and only then runs the matching Box actions.
After the application checks the Decisions API result, it maps the final route to Box actions. Every route creates a review task; request_endorsement and specialist_review paths also add the predefined insurance specialist as a file collaborator. The task message gives the reviewer useful context when they open the source document. The application also writes the extracted values and decision confidence to the uploaded file using the enterprise metadata template.
The demo project includes fictional PDFs for the project requirements, an incomplete COI, an unclear-expiration COI, a separate endorsement example, and a complete submission packet.
Follow these steps to set up this project:
# Box Developer Token from the Box Developer Console (demo token expires periodically). BOX_DEVELOPER_TOKEN= # OpenAI API key. OPENAI_API_KEY= OPENAI_DECISIONS_MODEL=gpt-6-luna BOX_REVIEWER_USER_ID= BOX_SPECIALIST_USER_ID= Enter fullscreen mode Exit fullscreen mode Webhook handling for this project is optional.
The script can be triggered manually or with the webhook handler. When running the webhook receiver locally, expose your port through a public HTTPS tunnel, for example with ngrok. Set BOX_WEBHOOK_ADDRESS to https://<your-host>/box-webhook.
The tunnel forwards that public callback to the local receiver. # Used by seed.py to create/update the intake upload webhook. # Set to the public HTTPS tunnel URL ending in /box-webhook BOX_WEBHOOK_ADDRESS= Enter fullscreen mode Exit fullscreen mode Create a Box File Request template in the Box web application. It gives users a simple upload page and places submitted content directly in the intake folder. This is the only manual configuration step, as the Box API requires an existing template to create a new one programmatically.
See the File Request instructions. Add an email address field if you want the request to collect the submitter’s contact address. Save the project and copy its link from the File Request builder URL.
Put that value in the.env file as BOX_FILE_REQUEST_TEMPLATE_ID.
# ID from the File Request builder URL (/filerequest/<id>), not the public upload URL (/f/<token>). BOX_FILE_REQUEST_TEMPLATE_ID= Enter fullscreen mode Exit fullscreen mode
Start the HTTPS tunnel in a separate terminal and leave it running:
ngrok http 8000 Enter fullscreen mode Exit fullscreen mode In the project terminal, run the seed after setting BOX_WEBHOOK_ADDRESS to the tunnel’s HTTPS URL:
python seed.py Enter fullscreen mode Exit fullscreen mode If you created the File Request after the first seed, set its builder ID and run the seed again. Start the receiver with:
python demo.py Enter fullscreen mode Exit fullscreen mode Upload one of the sample COIs through the File Request link. Box sends the upload event; the receiver queues the file and runs extraction, decision, metadata, and review actions.
To exercise the same processing path before webhook delivery is configured, use the manual trigger with an uploaded Box file ID:
python manual_trigger.py <BOX_FILE_ID> Enter fullscreen mode Exit fullscreen mode Watch the terminal for the extraction fields and decision logs. In Box, open the uploaded file to inspect its COI Intake Review metadata, Activity panel, review task, and specialist collaboration. The sample PDFs are fictional; the COI layout is inspired by familiar certificate fields and the Texas Department of Insurance sample, but these artifacts are not official forms or evidence of actual insurance.
This demo focuses on the intake-to-review path and can serve as a boilerplate for various use cases. It is not production workflow software. Before deploying a real workflow, move event and processing state to durable storage, make retries safe, and add monitoring so failed or delayed submissions are visible.
From here, the project could grow in a few practical directions:
If you have any questions or run into setup difficulties, contact Box.