Skip to main content
Enterprise procurement documents rarely contain just a few flat fields. A single supplier agreement can include vendor contact details, delivery milestones, ship-to locations, and payment terms across paragraphs and tables. This tutorial shows you how to turn that complexity into clean, structured output. You use the struct and table field types in Box AI structured extraction to define a schema that matches the shape of the document, then call the extract endpoint with the Enhanced Extract Agent to return data that is ready for downstream systems, automations, and Box metadata.

What you are building

By the end of this tutorial, you have a working Python project that:
  • Authenticates to Box and reads a supplier agreement stored in a Box folder.
  • Defines an extraction schema that uses a struct field for grouped vendor details and a table field for a repeating delivery schedule.
  • Calls the POST /2.0/ai/extract_structured endpoint with the Enhanced Extract Agent.
  • Maps the response into a procurement record that you can push to an ERP, procurement platform, or project tracker.

Why struct and table

The POST /2.0/ai/extract_structured endpoint supports two complex field types in addition to scalar types such as string, float, date, enum, and multiSelect: These types let you mirror how the data is actually used. Instead of parsing one long vendor block or collapsing a delivery schedule into a single string after extraction, you map the result directly into a supplier master record or procurement workflow.
For a full reference of both field types and their supported sub-field types, see .

Prerequisites

Before you start, make sure you have the following:
  • A free , which gives you access to the Box AI API.
  • A Box application configured with Client Credentials Grant authentication.
  • Python 3.11 or higher.
  • A supplier agreement uploaded to Box. You can download a and upload it to a Box folder. Note its file ID from the URL. For example, if the URL is https://app.box.com/file/123456789, the file ID is 123456789.
  • The following scopes enabled on your app:
    • Read and write all files and folders stored in Box
    • Manage AI

Step-by-step process

This tutorial uses one Box Platform capability and one Box AI agent: The Enhanced Extract Agent is a predefined Box AI agent, so you do not create or configure it yourself. You reference it by its ID (enhanced_extract_agent) in the ai_agent parameter of your extraction request, which you build in the Build the extraction function step below. To learn more, see the reference.
1

Set up the development environment

  1. Open your terminal and create a new project directory:
  1. Create and activate a Python virtual environment:
After activation, your terminal prompt shows (.venv) at the beginning. This confirms you are working inside the virtual environment.
Every time you open a new terminal window or tab, re-activate the virtual environment by running source .venv/bin/activate from the project directory. If you see ModuleNotFoundError when running commands, it usually means the venv is not activated.
  1. Install the required packages:
  1. Create a .env file to store your credentials, then add the following content. Replace the placeholder values with your actual credentials from the Box Developer Console:
Never commit .env files to version control. Add .env to your .gitignore.
2

Authenticate the Box client

Create a file called box_client.py and add the following code. It builds an authenticated client that you use to call Box AI through the SDK.
Client Credentials Grant is recommended for server-to-server automations where no end user is present. For other authentication options, see .
A CCG application acts as a separate service account user that does not automatically have access to your content. Invite the service account email (found in the Developer Console under General Settings) as a collaborator on the folder that contains your agreement. Without access, API calls return 404 Not found.
3

Define the extraction schema

Create a file called schema.py and add the following code. The schema describes the agreement using two complex fields:
  • vendor is a struct field that groups related vendor details into one nested object.
  • delivery_schedule is a table field that returns one row per milestone.
Each complex field requires a fields array that defines its sub-fields. Sub-fields support scalar types only. Nested struct or table types are not allowed.
Table extraction is not limited to visually formatted tables. The table type extracts repeating data whether it appears as a grid, key-value pairs, a form layout, or plain prose.
4

Build the extraction function

Create a file called extract.py and add the following code. It uses the SDK’s create_ai_extract_structured method to send the schema to Box AI and specifies the Enhanced Extract Agent, which improves accuracy for nested and repeating fields.
The Enhanced Extract Agent is not strictly required, but it improves results for richer schemas and complex document layouts, especially when nested and repeating fields are involved.
5

Map the structured output

Create a file called app.py and add the following code. Box AI returns the vendor field as a nested object and the delivery_schedule field as a list of rows. This script runs the extraction and maps the result into a flat record that is ready for a downstream system.
At this point, your project directory should contain the following files:
6

Run the extraction

Make sure you are in the supplier-extraction directory with the virtual environment activated, then run the script:
Box AI returns the struct field as a single nested object and the table field as a list of objects. Your output looks similar to this:
The script then prints the mapped procurement record, which you can send to your ERP, procurement platform, or project tracker.

Troubleshooting

Your virtual environment is not activated. Run source .venv/bin/activate from the project directory before running any python3 commands. Each new terminal tab needs its own activation.
Check your .env file:
  • Verify BOX_CLIENT_ID and BOX_CLIENT_SECRET match the values in Developer Console > Configuration.
  • Confirm BOX_ENTERPRISE_ID is your enterprise ID.
  • Ensure your app is authorized in the Developer Console and uses Client Credentials Grant.
The service account does not have access to the file. Invite the service account email (found in Developer Console > General Settings) as a collaborator on the folder that contains your agreement.
Nested struct and table types are not supported as sub-fields, and a struct or table field must include a fields array. Confirm your sub-fields use only scalar types, and add a prompt to the complex field to clarify what to extract.

Scaling to production

To make agreements searchable and routable inside Box, write the flattened top-level values back to the file as a metadata instance, then use to filter by vendor, country, or effective date. See for an end-to-end metadata write-back pattern.
Instead of running the script manually, register a webhook on your agreements folder so each upload triggers extraction. See to validate incoming requests in production.
Add a field-level prompt to guide extraction, and keep the Enhanced Extract Agent for multi-page agreements with dense tables. For consistent schemas across many documents, define the fields in a instead of inline.

Next steps

Invoice intake automation

Watch a folder for new invoices, extract fields, and write them back as searchable metadata.

Extract API reference

See the full API specification for structured extraction.
Last modified on July 13, 2026