Before you start
Complete these Box setup steps before you build. You need:- A , or a with Box AI enabled.
- A Box application configured with Client Credentials Grant authentication, authorized in the Admin Console, with these scopes:
- Read and write all files and folders stored in Box
- Manage AI
- Manage webhooks
- A runtime for the stack you choose: Python 3.11+, Node.js 20+, Java 17+, or .NET 8+.
- For the agent path, a coding agent such as Codex, Claude Code, or Cursor. Installing helps it use current Box APIs.
.env file need them.
1. Create the metadata template
1. Create the metadata template
- Open the Box Admin Console and select Metadata.
- In the Invoices tab, select New and name it
Invoice. - Add the following fields:
- Copy the template key from under the Template Name. You need it for the prompt and for
.env. - Select Save.
2. Create the invoices inbox folder
2. Create the invoices inbox folder
- In Box, create a new folder called
Invoices Inbox. - Note the folder ID from the URL. For example, if the URL is
https://app.box.com/folder/123456789, the folder ID is123456789. - Share the folder with your application’s service account. This is required because CCG applications act as a separate service account user that does not automatically have access to your content.
Build with an agent
Gather these values from Before you start:- Metadata template key - from the template you created
- Invoices Inbox folder ID - from the folder URL
- Enterprise ID - from the Developer Console, using the icon in the top-right
<TEMPLATE_KEY>, <FOLDER_ID>, and <ENTERPRISE_ID> placeholders if you want the agent to pre-fill .env; otherwise leave them and fill .env yourself after scaffolding.
Review generated code before using it in production. Never paste Box credentials into your coding agent.
.env.example to .env and fill in your client ID, client secret, enterprise ID, metadata template key, and folder ID. Then skip ahead to Run and verify.
Prefer to write the code yourself? See Build by hand below.
Build by hand
Use this path if you prefer to write the code yourself, or if you need a reference when the agent drifts. Complete Before you start first, then follow the steps in order. Use the language tabs in each code block to switch between Python and TypeScript. You can also clone a working sample if you prefer to start from running code:Python working sample
TypeScript working sample
1. Set up the development environment
1. Set up the development environment
- Open your terminal and create a new project directory:
- Install dependencies for your language:
(.venv) at the beginning. Every time you open a new terminal window or tab, re-activate the virtual environment with source .venv/bin/activate from the project directory. If you see ModuleNotFoundError, the venv is usually not activated.TypeScript: tsx runs TypeScript directly during development. You can compile with npx tsc for production builds.- Create a
.envfile to store your credentials then add the following content. Replace the placeholder values with your actual credentials from the Box Developer Console:
.env file stores sensitive values (your actual credentials). Your code reads these values by referencing their names. When you copy the code in the following steps, keep the quoted variable names exactly as shown. Do not replace them with your actual credentials.2. Authenticate the Box client
2. Authenticate the Box client
3. Build the extraction function
3. Build the extraction function
4. Write metadata back to the file
4. Write metadata back to the file
409 Conflict on Metadata Instance, so this function falls back to a JSON-Patch update. That keeps the service safe to re-run on a file you already processed, which happens with duplicate webhook deliveries and resent invoices.Use the add operation rather than replace. add sets a value whether or not the field is already present, so the update still succeeds when Box AI returns fewer fields than the previous run.5. Create the webhook listener
5. Create the webhook listener
Run and verify
You can test the extraction pipeline locally without setting up a public URL or webhook. This simulates what Box would send when a new file arrives.-
Terminal 1 - start the server. Make sure you are in the
invoice-intakedirectory, then use the command for your stack:You should see the server listening on port 5000. Leave this terminal running. -
Terminal 2 - send a test request. Open a new terminal tab or window. Send a simulated webhook payload using curl. Replace
<FILE_ID>with the file ID of the invoice PDF you uploaded to Box. -
Check the result. Switch back to Terminal 1. You should see the extracted fields printed, followed by a confirmation that metadata was applied:
Open the file in Box and select the Metadata tab to verify the values were written correctly.
Register a webhook for production
The local curl test simulates what Box sends, but for a production deployment you need Box to send real webhook notifications automatically. This requires a publicly accessible HTTPS endpoint:<FOLDER_ID> with your invoices folder ID and update the address to your tunnel URL with /webhook appended.
Once registered, any PDF uploaded to the folder automatically triggers extraction and metadata application.
Optional: push totals to an ERP
Once you have structured metadata, pushing data downstream is straightforward. After metadata is applied, start from the Box AI extract object:Scaling to production
Handle duplicate deliveries
Handle duplicate deliveries
apply_metadata already keeps the write safe, but a duplicate still pays for a second Box AI extraction. To skip that work, check for an existing instance with GET /2.0/files/:id/metadata/enterprise/:template at the top of the handler and return early if one is present.Only skip when a repeat run is redundant. If vendors resend corrected invoices under the same file ID, let the extraction run so the metadata reflects the latest version.Process at scale with event streams
Process at scale with event streams
Use the Enhanced Extract Agent for complex invoices
Use the Enhanced Extract Agent for complex invoices
POST /2.0/ai/extract_structured call (alongside the metadata template):metadata_template / metadataTemplate. For SDK-specific samples, see the .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.Cannot find module 'box-node-sdk' or similar
Cannot find module 'box-node-sdk' or similar
npm install. Confirm box-node-sdk appears in package.json dependencies and that you are using Node.js 20 or higher (node -v).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. - Confirm
BOX_ENTERPRISE_IDis your enterprise ID (found in Admin Console > Account & Billing, or Developer Console > icon in the top-right > Copy Enterprise ID). - Ensure your app is authorized in the Developer Console.
- Make sure the app type is Client Credentials Grant.
404 Not Found
404 Not Found
metadata_template must have both scope and template_key
metadata_template must have both scope and template_key
BOX_METADATA_TEMPLATE_KEY value in your .env file is missing or empty. Add the template key you noted when creating the metadata template in Before you start.409 Conflict on Metadata Instance
409 Conflict on Metadata Instance
The agent tried to create the template or folder
The agent tried to create the template or folder
BOX_METADATA_TEMPLATE_KEY, INVOICES_FOLDER_ID, and BOX_ENTERPRISE_ID from the environment, or follow Build by hand.