The job

You receive a 60-page annual report as a PDF. You want the reporting period, total revenue and the auditor’s opinion as fields, the revenue-by-segment table as rows, and a reading of the key chart, without anyone paging through the file.

Sample input

annual-report-2025.pdf, 60 pages:
  • Pages 1–4: cover with the company logo, contents, and the chair’s letter with a signature.
  • Pages 5–18: narrative sections with photos of sites and products, and a bar chart of revenue by quarter.
  • Pages 19–44: financial statements. Dense tables with multi-level column headers (current year, prior year, and change, under each segment), subtotals, and footnote markers that point to notes at the foot of the page.
  • Pages 45–56: notes to the accounts, mostly paragraphs and small tables.
  • Pages 57–60: the independent auditor’s report, scanned from paper, with a signature and the firm’s stamp.
Every page carries a running header with the company name and a footer with the page number.

How fileScout processes it

Illustrative: the element breakdown is internal; the API returns the structured values.
fileScout reads the file as a set of elements and handles each kind on its own path, all within the same file: Running headers and footers, such as the company name and page numbers on every page, carry no data. fileScout skips them, so they cost no tokens. Long files like this one are read in chunks; spreadsheets take a separate path of their own. The fields you get back are the ones your AI Schema defines. The breakdown above is how fileScout finds them; it is not part of the response.

Steps

The cURL commands use two environment variables:
See Regions for regional hosts.
1

Request an upload URL

Send the file name, its MIME type in fileType, and enabledProducts: ["FILE_SCOUT"]. fileScout needs normal processing, so leave storageOnly out. See Choose products for the rules.
Keep uploadId and presignedUploadURL from the response. enabledProducts works only on this single upload route and in workspaces enabled for it; otherwise the request returns 422.
2

PUT the file

The URL is valid for 300 seconds. Send the same Content-Type you gave as fileType.
3

Wait for processing

Poll GET /v1/uploads/{uploadId} until every entry in files is processed or action_required, or wait for a processing callback. A 60-page file takes longer than a one-page invoice, so poll patiently.
The report is one document, so files has one entry. If you upload with isSplit: true, one file can become several documents; iterate over files in that case.
4

Read the values, with every table row

Pass includeFullTableData=true so tables over 100 rows come back whole.

Result

Illustrative: shape from the API reference. Field and column titles depend on the schema in your workspace. Rows are shortened here.
GET /v1/files/{fileId}/values?includeFullTableData=true
  • Scalar fields carry their answer in value. Total revenue is a JSON number: grouped text such as 412,850,000 is read as 412850000. Reports often print figures in thousands or millions, so say in the field’s description which unit you want. See Extraction prompts.
  • Revenue by segment is a list field. Its value is null and its rows are in valueArray, each row an array of cells with their own title, type and value. A multi-level header (segment, then current year and prior year) comes back as flat, named columns. See Tables.
  • Revenue by quarter chart is a field that describes a visual element: here, what the chart shows. It is a reading of the chart, not the underlying data; when the report also prints the figures as a table, extract that table for exact numbers.
  • A number that is 0 comes back as null, in fields and in table cells. Treat null in a number field as zero or missing according to your own rules. See Data types.

What it shows

  • One upload handles a long, mixed file: tables, text, charts, photos and scanned pages are each read on their own path, so you don’t pre-sort pages.
  • Page furniture is skipped, so running headers and footers never turn into fields.
  • Long tables need includeFullTableData=true. Without it a table over 100 rows returns its first 100 and no error.
  • A chart comes back as a description. When you need exact figures, take them from a table.

Next steps

AI Schemas

Define the fields and tables fileScout fills.

Data types

Tables, valueArray and how values are typed.

Bank statement extraction

Long tables and a totals check.

Uploads

Every upload option, including enabledProducts.