Skip to main content
When a PDF is uploaded to a designated Box folder, this service extracts the vendor name, invoice number, dates, total, and currency with Box AI, then writes those values back to the file as metadata.

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.
Keep the metadata template key, inbox folder ID, and enterprise ID handy. The prompt and your .env file need them.
The metadata template defines the fields Box AI extracts. Create it once, and every invoice processed by the service returns values in this shape.
This step requires Admin access. If you do not have access, contact your Box administrator.
  1. Open the Box Admin Console and select Metadata.
  2. In the Invoices tab, select New and name it Invoice.
  3. Add the following fields:
  1. Copy the template key from under the Template Name. You need it for the prompt and for .env.
  2. Select Save.
For a detailed walkthrough, see .
Create a dedicated folder in Box to serve as the invoice drop zone.
  1. In Box, create a new folder called Invoices Inbox.
  2. Note the folder ID from the URL. For example, if the URL is https://app.box.com/folder/123456789, the folder ID is 123456789.
  3. 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.
This step is critical. Without it, all API calls return 404 “Not found” errors.To find your service account email: go to the Developer Console, open your app, and look under General Settings for the Service Account ID (it looks like AutomationUser_xxxxx_xxxxxx@boxdevedition.com).Invite this email as a collaborator on the folder with the Editor role. Editor access is required because the app needs to write metadata back to files.

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
Choose your stack and copy the prompt. It already lists these as prerequisites, so the agent reads them from environment variables instead of trying to create them. Replace the <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.
Python + Flask

Review generated code before using it in production. Never paste Box credentials into your coding agent.

When the agent finishes, copy .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

Clone the Flask app, add your Box credentials, and run.

TypeScript working sample

Clone the Express app, add your Box credentials, and run.
  1. Open your terminal and create a new project directory:
  1. Install dependencies for your language:
Python: After activation, your terminal prompt shows (.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.
  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.
Understanding environment variables: The .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.
Create the Box client module in your project directory:
Client Credentials Grant is recommended for server-to-server automations where no end user is present. For other authentication options, see .
Create the extraction module. This is the core of the service. It takes a file ID, calls Box AI to extract fields using your metadata template, and returns the structured result.
The metadata template tells Box AI exactly which fields to look for and what data types to return. This means the response shape is predictable and consistent, regardless of how each vendor formats their invoices.
Create the metadata module. After extraction, this function attaches the extracted values to the file as a metadata instance:
Creating metadata only succeeds the first time. If the file already has an instance of the template, Box returns 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.
Once metadata is attached, the extracted fields become searchable, filterable, and visible in the Box web app. You can use to find all invoices above a certain amount, filter by vendor, or build dashboards in Box Apps.
Create the HTTP application that receives webhook notifications when new files arrive in the inbox folder:
In production, you should verify webhook signatures to confirm that requests originate from Box. See for implementation details.
At this point, your project directory should contain the following files:
When you finish scaffolding, continue to Run and verify.

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.
This requires two terminal windows open at the same time. Terminal 1 runs the server (which must stay running). Terminal 2 sends a test request to it.
  1. Terminal 1 - start the server. Make sure you are in the invoice-intake directory, then use the command for your stack:
    You should see the server listening on port 5000. Leave this terminal running.
  2. 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.
    Use the file ID, not the folder ID. The file ID comes from the file’s URL: https://app.box.com/file/123456789 → the file ID is 123456789. The folder ID comes from a different URL pattern: https://app.box.com/folder/987654321.
  3. 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:
Replace <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:
Map those fields (and the Box file ID, if your ERP needs an external reference) into whatever shape your ERP expects, then POST with your stack’s normal HTTP client.

Scaling to production

Box webhook delivery can produce duplicates. The 409 fallback in 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.
For high-volume environments, consider using instead of webhooks. Enterprise events provide a durable, polling-based stream that is better suited to batch processing thousands of invoices.
If your invoices contain complex layouts, multi-page line items, or non-standard formatting, use the for improved accuracy. Add this agent reference to your existing POST /2.0/ai/extract_structured call (alongside the metadata template):
Pass it the same way your SDK already passes metadata_template / metadataTemplate. For SDK-specific samples, see the .

Troubleshooting

Your Python 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.
From the project directory, run npm install. Confirm box-node-sdk appears in package.json dependencies and that you are using Node.js 20 or higher (node -v).
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 (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.
The service account does not have access to the file or folder. Invite the service account email (found in Developer Console > General Settings) as a collaborator with Editor role on the folder containing your invoice files.
The 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.
The file already has an instance of the template, so creating one fails. This is common when you retest a file that a previous run already processed. Extraction succeeded; only the metadata write failed.Add the 409 fallback shown in Build by hand under 4. Write metadata back to the file so the service updates the existing instance instead of creating a second one. To retest with a clean file, remove the instance from the file’s Metadata tab in Box, or delete it through the API:
The template, inbox folder, and enterprise ID come from Before you start; an agent cannot create them. Re-paste the prompt with the prerequisites block intact so the agent reads BOX_METADATA_TEMPLATE_KEY, INVOICES_FOLDER_ID, and BOX_ENTERPRISE_ID from the environment, or follow Build by hand.

Next steps

Sales RFP answer bank

Build an AI-powered knowledge base for sales teams using Box Hubs and Box AI.

Extract API reference

See the full API specification for structured extraction.
Last modified on August 18, 2026