> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runpulse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Extract File

> The primary endpoint for the Pulse API. Parses uploaded documents or remote
file URLs and returns rich markdown content with optional structured data
extraction based on user-provided schemas and extraction options.

Set `async: true` to return immediately with a job_id for polling via
GET /job/{jobId}. Otherwise processes synchronously.

To process many files at once, see [Batch Extract](api:POST/batch/extract)
or the [Batch Processing guide](/batch).

## Overview

<Info>
  **Pipeline Step 1** — Extract is where document processing begins: every downstream step consumes its `extraction_id`. After extraction, you can optionally [split](/api-reference/endpoint/split) the document into topics, apply [schema extraction](/api-reference/endpoint/schema) to get structured data, or use [tables](/api-reference/endpoint/tables) for span-aware table extraction.

  Handling mixed document types? [`/classify`](/api-reference/endpoint/classify) can run before Extract to route each raw document to the right pipeline — it only chooses *which* pipeline runs, so extraction still happens here.
</Info>

Extract content from documents. Returns markdown or HTML formatted content with optional structured data extraction.

For large results (typically documents over 70 pages, spreadsheet extractions, or any response above 5 MB), the API returns a one-time download link at `https://api.runpulse.com/results/{job_id}` instead of inlining the payload. Fetching that URL returns the same complete extraction result JSON you would receive inline. See [Large Result Response](#large-result-response) below.

<Note>
  For large documents or batch processing workflows, set `async: true` to process asynchronously and poll for results via [GET /job/{'{'}jobId{'}'}](/api-reference/endpoint/poll).
</Note>

<Note>
  To process many files at once, use [Batch Extract](/api-reference/endpoint/batch-overview#batch-extract). It accepts an S3 prefix, local directory, or list of URLs and runs `/extract` on each file in parallel.
</Note>

### Async Mode

Set `async: true` to return immediately with a job ID for polling:

```json theme={null}
{
  "file_url": "https://example.com/document.pdf",
  "async": true
}
```

**Async Response (200):**

```json theme={null}
{
  "job_id": "abc123-def456",
  "status": "pending",
  "message": "Document processing started"
}
```

Use `GET /job/{job_id}` to poll for completion.

## Request

### Document Source

Provide the document using one of these methods:

| Field      | Type   | Description                                                    |
| ---------- | ------ | -------------------------------------------------------------- |
| `file`     | binary | Document file to upload directly (multipart/form-data).        |
| `file_url` | string | Public or pre-signed URL that Pulse will download and extract. |

### Extraction Options

| Field               | Type          | Default   | Description                                                                                                                                                                                                                                                     |
| ------------------- | ------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `model`             | string (enum) | `default` | Extraction model to use. One of `default` or `pulse-ultra-2`. `pulse-ultra-2` uses Pulse's vision-language model with built-in refinement, figure/chart extraction, and word-level bounding boxes.                                                              |
| `pages`             | string        | -         | Page range filter (1-indexed). Supports segments like `1-2` or mixed ranges like `1-2,5`. Page 1 is the first page.                                                                                                                                             |
| `figure_processing` | object        | -         | Settings that control how figures in the document are processed. These affect the **markdown output directly** and do not produce additional output fields. See [Figure Processing](#figure-processing).                                                        |
| `extensions`        | object        | -         | Settings that enable additional processing or alternate output formats. Each enabled extension produces a corresponding result under `response.extensions.*`. See [Extensions](#extensions).                                                                    |
| `spreadsheet`       | object        | -         | Settings for Excel/spreadsheet extraction. Controls hidden rows, columns, sheets, raw values, phantom-cell trimming, and whether table `cell_data` is included. Applies to `.xlsx`, `.xlsm`, and `.xls` files. See [Spreadsheet Options](#spreadsheet-options). |
| `storage`           | object        | -         | Options for persisting extraction artifacts. See [Storage Options](#storage-options).                                                                                                                                                                           |
| `async`             | boolean       | `false`   | If `true`, returns immediately with a `job_id` for polling via `GET /job/{jobId}`.                                                                                                                                                                              |
| `force_url`         | boolean       | `false`   | When `true`, return the complete extraction result as a URL even if it is small. Spreadsheet responses are URL-backed by default; set `force_url: false` to request inline spreadsheet output. URL delivery changes only the transport, not the result shape.   |
| `structured_output` | object        | -         | **⚠️ Deprecated** — Use the [`/schema`](/api-reference/endpoint/schema) endpoint after extraction instead. Still works for backward compatibility.                                                                                                              |

### Figure Processing

Settings under `figure_processing` control how figures (images, charts, diagrams) and embedded visuals are processed. Applies to both PDFs/images (figures detected from layout) and spreadsheets (charts and embedded images read directly from the workbook). Affects the markdown output and the `bounding_boxes.Images[]` array.

| Field                           | Type    | Default | Description                                                                                                                                                                                                                                                                                |
| ------------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `figure_processing.description` | boolean | `false` | Generate descriptive captions for extracted visuals. Captions appear under `bounding_boxes.Images[].description` and inline in the markdown output. Applies to both detected charts and non-chart images.                                                                                  |
| `figure_processing.show_images` | boolean | `false` | Return image URLs for extracted visuals. URLs appear under `bounding_boxes.Images[].image_url` and resolve to a Pulse-hosted PNG/JPEG served from [`GET /results/{jobId}/images/{filename}`](/api-reference/endpoint/results-image). Applies to both detected charts and non-chart images. |

<Note>
  For spreadsheets specifically, `show_images: true` collects every embedded chart and image in the workbook and emits one entry per visual under `bounding_boxes.Images`, with chart-specific fields like `chart_type`, `chart_title`, and `source_ranges` populated. See [Bounding Boxes](/api-reference/bounding-boxes#images-array) for the full field list.
</Note>

### Spreadsheet Options

Settings under `spreadsheet` control how Excel workbooks (`.xlsx`, `.xlsm`, `.xls`) are processed. By default, hidden rows, columns, and sheets are excluded from extraction output, cell values are rendered the way Excel displays them, and table cell metadata is included. Phantom-cell trimming is opt-in. Spreadsheet responses are returned as full-result URLs by default because workbook `cell_data` can make the payload large even for modest `.xlsx` files.

| Field                               | Type    | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                          |
| ----------------------------------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `spreadsheet.include_hidden_rows`   | boolean | `false` | Include rows that are hidden in the Excel workbook.                                                                                                                                                                                                                                                                                                                                                                  |
| `spreadsheet.include_hidden_cols`   | boolean | `false` | Include columns that are hidden in the Excel workbook.                                                                                                                                                                                                                                                                                                                                                               |
| `spreadsheet.include_hidden_sheets` | boolean | `false` | Include sheets that are hidden in the Excel workbook.                                                                                                                                                                                                                                                                                                                                                                |
| `spreadsheet.use_raw_values`        | boolean | `false` | Emit the underlying numeric value for number cells instead of the Excel display-formatted text — e.g. `1201.67` rather than `$1,202` when the cell uses a rounded currency format. Useful when downstream processing needs exact amounts (cent-level precision) rather than what the workbook shows visually. Percent-formatted cells and dates keep their display rendering. Does not apply to legacy `.xls` files. |
| `spreadsheet.only_data_rows`        | boolean | `false` | When `true`, trim trailing empty rows past the last cell carrying a value or formula. See [Phantom-cell trimming](#phantom-cell-trimming-only_data_rows--only_data_cols) below.                                                                                                                                                                                                                                      |
| `spreadsheet.only_data_cols`        | boolean | `false` | When `true`, trim trailing empty columns past the last cell carrying a value or formula. Same rationale as `only_data_rows`.                                                                                                                                                                                                                                                                                         |
| `spreadsheet.cell_data`             | boolean | `true`  | Include cell-level table metadata under `bounding_boxes.Tables[].cell_data`. Set to `false` to omit this metadata and reduce output size.                                                                                                                                                                                                                                                                            |

<Note>
  These settings accept both camelCase (`includeHiddenRows`, `onlyDataRows`, `cellData`) and snake\_case (`include_hidden_rows`, `only_data_rows`, `cell_data`) formats.
</Note>

#### Phantom-cell trimming (`only_data_rows` / `only_data_cols`)

Excel files exported from claims systems, ERPs, and other automated pipelines routinely declare a "used range" that extends hundreds of thousands of rows past where the data actually ends. A typical case: a 57 MB workbook with only \~500 rows of real data, where the other \~1,000,000 rows are empty cells that exist only because they were once selected and styled. These phantom cells inflate file size by orders of magnitude and can exhaust parser memory on the extraction pipeline.

Set `only_data_rows: true` and `only_data_cols: true` to have Pulse scan each sheet once before parsing, find the largest row and column containing a value or formula, and ignore everything beyond that extent. Surviving cells keep their **original A1 coordinates** (e.g., a value at `B7` in the source is still `B7` in the output), so any citation or bounding box that references a specific cell remains stable. The trim only kicks in on large sheets (≥5 MB of XML per sheet), so small, well-formed workbooks pay no overhead either way.

Both flags default to `false`.

### Pulse Ultra 2 Options

These options are available only when `model: pulse-ultra-2` is set. Passing any of them with the default model returns a 400 error listing the offending fields.

| Field                       | Type    | Default | Description                                                                                                                                                                                                                                                           |
| --------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `refine`                    | boolean | `false` | Run a full-page OCR and formatting correction pass after extraction. Improves accuracy on dense layouts, numerical values, and table structure. Adds \~1–2s per page. Overridden by `refine_options` if both are provided.                                            |
| `refine_options`            | object  | -       | Granular refinement targets. Takes precedence over the boolean `refine` flag. See below.                                                                                                                                                                              |
| `refine_options.tables`     | boolean | `false` | Fix table cell values, structure, and headers against the source image.                                                                                                                                                                                               |
| `refine_options.text`       | boolean | `false` | Fix OCR errors, missing or extra content, and numerical accuracy (tables untouched).                                                                                                                                                                                  |
| `refine_options.formatting` | boolean | `false` | Add strikethrough, italic, bold, super/subscript, and LaTeX formatting (tables untouched).                                                                                                                                                                            |
| `extract_figure`            | boolean | `false` | Convert charts and data visualizations into HTML `<table>` blocks, wrapped in `<figure-table>` tags. Useful for financial decks, dashboards, and scientific charts.                                                                                                   |
| `figure_description`        | boolean | `false` | Generate a 1–2 paragraph natural-language description of each picture, wrapped in `<figure-description>` tags. Combines well with `extract_figure`.                                                                                                                   |
| `detect_selections`         | boolean | `true`  | Detect selected and unselected marks with a specialized selection-mark model. Improves accuracy on forms, checkboxes, radio buttons, handwritten checkmarks, X marks, and similar controls. Enabled by default for `pulse-ultra-2`; set to `false` to skip this pass. |
| `additional_prompt`         | string  | `""`    | Extra context injected into the extraction prompt. Use to steer extraction toward a specific domain or attention focus. Max 4000 characters.                                                                                                                          |
| `custom_image_prompt`       | string  | `""`    | Extra context appended to the prompt used by `figure_description` and `extract_figure`. Tunes image and chart interpretation. Max 2000 characters.                                                                                                                    |
| `custom_refine_prompt`      | string  | `""`    | Extra context appended to the refinement prompt. Only applies when `refine: true` or `refine_options` is set. Max 2000 characters.                                                                                                                                    |

#### Selection mark detection

Use `detect_selections: true` with `model: pulse-ultra-2` when a document contains forms, checkboxes, radio buttons, handwritten selection marks, or other marked-choice controls. Pulse runs a specialized detection pass for these marks so selected/unselected states are less likely to be missed or confused with nearby text, boxes, or handwriting. When available, the detected state is returned on the relevant bounding-box items as `selected`.

#### Markdown output additions

When `extract_figure` or `figure_description` is enabled, figures in `response.markdown` include additional tags:

```html theme={null}
<figure data-page="1">
  <figure-table>...HTML table for the chart...</figure-table>
  <figure-description>...1–2 paragraph description...</figure-description>
</figure>
```

When `refine` (or `refine_options`) is set, markdown content is post-processed page-by-page; output is cleaner but typically grows \~1.5–3x in size for dense documents. No new tags are introduced.

### Extensions

Settings under `extensions` enable additional processing passes or alternate output formats. Each enabled extension produces a **corresponding output field** under `response.extensions.*`. For example, enabling `extensions.chunking` produces `response.extensions.chunking`, and enabling `extensions.alt_outputs.return_html` produces `response.extensions.alt_outputs.html`.

| Field                                | Type      | Default | Description                                                                                                                                 |
| ------------------------------------ | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `extensions.document_metadata`       | boolean   | `false` | Extract native properties and deterministic structure from the original file. Results appear under `response.extensions.document_metadata`. |
| `extensions.footnote_references`     | boolean   | `false` | Link footnote markers to their corresponding footnote text.                                                                                 |
| `extensions.chunking`                | object    | -       | Chunking configuration. See below.                                                                                                          |
| `extensions.chunking.chunk_types`    | string\[] | -       | List of chunking strategies: `semantic`, `header`, `page`, `recursive`.                                                                     |
| `extensions.chunking.chunk_size`     | integer   | -       | Maximum characters per chunk.                                                                                                               |
| `extensions.alt_outputs`             | object    | -       | Alternate output formats. See below.                                                                                                        |
| `extensions.alt_outputs.wlbb`        | boolean   | `false` | Enable word-level bounding boxes (PDF only). Results in `response.extensions.alt_outputs.wlbb`.                                             |
| `extensions.alt_outputs.return_html` | boolean   | `false` | Include HTML representation. `response.markdown` is still present; HTML is at `response.extensions.alt_outputs.html`.                       |
| `extensions.alt_outputs.return_xml`  | boolean   | `false` | Include XML representation (work in progress).                                                                                              |

### `pulse-ultra-2` Rate Limits

Requests made with `model: pulse-ultra-2` are subject to dedicated rate limits, separate from standard extraction:

| Limit      | Value          |
| ---------- | -------------- |
| Per minute | 5 extractions  |
| Per hour   | 20 extractions |
| File size  | 50 MB          |
| Concurrent | 2 per API key  |

The concurrent limit is the one that most commonly applies in practice — long-running extractions held open while new requests arrive will trip it first.

### Storage Options

Control whether extractions are saved to your extraction library:

| Field                 | Type          | Default | Description                                                                           |
| --------------------- | ------------- | ------- | ------------------------------------------------------------------------------------- |
| `storage.enabled`     | boolean       | `true`  | Whether to persist extraction artifacts. Set to `false` for temporary extractions.    |
| `storage.folder_name` | string        | -       | Target folder name to save the extraction to. Creates the folder if it doesn't exist. |
| `storage.folder_id`   | string (uuid) | -       | Target folder ID to save the extraction to. Takes precedence over `folder_name`.      |

### Deprecated Fields

The following input fields are deprecated and will be removed in a future version. They are still accepted for backward compatibility.

| Field               | Replacement                                                                                                                                                         |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `show_images`       | Use `figure_processing.show_images`                                                                                                                                 |
| `chunking`          | Use `extensions.chunking.chunk_types` (array instead of comma-separated string)                                                                                     |
| `chunk_size`        | Use `extensions.chunking.chunk_size`                                                                                                                                |
| `return_html`       | Use `extensions.alt_outputs.return_html`                                                                                                                            |
| `structured_output` | Use [`/schema`](/api-reference/endpoint/schema) endpoint after extraction. Pass `extraction_id` + `schema_config`. Accepts `schema`, `schema_prompt`, and `effort`. |
| `schema`            | Use [`/schema`](/api-reference/endpoint/schema) endpoint after extraction                                                                                           |
| `schema_prompt`     | Use [`/schema`](/api-reference/endpoint/schema) endpoint with `schema_config.schema_prompt`                                                                         |
| `custom_prompt`     | No replacement                                                                                                                                                      |
| `thinking`          | No replacement                                                                                                                                                      |

<Note>
  When legacy input fields are used, the API returns a deprecation warning in the `warnings` array directing you to the updated field names. See the [latest documentation](https://docs.runpulse.com/api-reference/endpoint/extract) for details.
</Note>

## Response

The response structure varies based on document size to optimize for different use cases.

### Standard Inline Response

For non-spreadsheet documents under 70 pages whose response payload stays below the inline threshold, results are returned directly in the response body:

```json theme={null}
{
  "markdown": "# Document Title\n\nExtracted content...",
  "page_count": 15,
  "extraction_id": "abc123-def456-ghi789",
  "extraction_url": "https://platform.runpulse.com/dashboard/extractions/abc123",
  "credits_used": 1.0,
  "plan_info": {
    "tier": "growth",
    "pages_used": 15,
    "total_credits_used": 49.5,
    "note": "Pulse Ultra"
  },
  "bounding_boxes": {
    "Title": [],
    "Text": [],
    "Tables": [],
    "Images": [
      {
        "id": "excel_image_1_1",
        "visual_type": "chart",
        "image_url": "https://api.runpulse.com/results/abc123-def456-ghi789/images/excel_image_1_1.png",
        "chart_type": "BarChart",
        "chart_title": "Revenue",
        "excel_range": "D2",
        "sheet_name": "Charts"
      }
    ],
    "markdown_with_ids": "<p data-bb-text-id=\"txt-1\">..."
  },
  "extensions": {
    "chunking": {
      "semantic": ["chunk 1...", "chunk 2..."],
      "header": ["section 1...", "section 2..."]
    },
    "altOutputs": {
      "html": "<html>...</html>"
    }
  },
  "warnings": []
}
```

#### Response Fields

| Field                           | Type          | Description                                                                                                                                                                                                                     |
| ------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `markdown`                      | string        | Clean markdown content extracted from the document. Always present.                                                                                                                                                             |
| `page_count`                    | integer       | Total number of pages processed.                                                                                                                                                                                                |
| `extraction_id`                 | string (uuid) | Persisted extraction ID. Present when storage is enabled (default). Use with `/split` and `/schema`.                                                                                                                            |
| `extraction_url`                | string        | URL to view the extraction in the Pulse Platform. Present when storage is enabled.                                                                                                                                              |
| `credits_used`                  | number        | Credits consumed by **this request**. Only present when the org has the credit billing system enabled.                                                                                                                          |
| `plan_info`                     | object        | Billing tier and **cumulative** usage information for the calling org, including this request. Includes `tier`, `total_credits_used` (primary billing metric), `pages_used` (legacy), and an optional `note`.                   |
| `bounding_boxes`                | object        | Typed bounding-box data — `Images`, `Tables`, `Text`, `Title`, `Footer`, plus `markdown_with_ids`. See [Bounding Boxes](/api-reference/bounding-boxes) for the full field list including the chart/image fields under `Images`. |
| `extensions`                    | object        | Output from enabled extensions. Only keys for enabled extensions are present. See below.                                                                                                                                        |
| `extensions.document_metadata`  | object        | Native properties and deterministic structure from the original file (when `extensions.document_metadata` is enabled). See [Document Metadata](#document-metadata) below.                                                       |
| `extensions.chunking`           | object        | Chunk results by strategy (when `extensions.chunking` is enabled).                                                                                                                                                              |
| `extensions.footnoteReferences` | array         | List of detected footnotes with their in-text references (when `extensions.footnote_references` is enabled). See [Footnote References](#footnote-references) below.                                                             |
| `extensions.altOutputs.wlbb`    | object        | Word-level bounding boxes (when `extensions.alt_outputs.wlbb` is enabled).                                                                                                                                                      |
| `extensions.altOutputs.html`    | string        | HTML representation (when `extensions.alt_outputs.return_html` is enabled).                                                                                                                                                     |
| `extensions.altOutputs.xml`     | string        | XML representation (when `extensions.alt_outputs.return_xml` is enabled, WIP).                                                                                                                                                  |
| `warnings`                      | array         | Non-fatal warnings generated during extraction, including deprecation notices for legacy input usage.                                                                                                                           |

#### Deprecated Response Fields

| Field               | Replacement                                     | Description                                                       |
| ------------------- | ----------------------------------------------- | ----------------------------------------------------------------- |
| `html`              | `extensions.altOutputs.html`                    | Present when legacy `return_html` input is used.                  |
| `chunks`            | `extensions.chunking`                           | Present when legacy `chunking` input is used.                     |
| `plan-info`         | `plan_info`                                     | Present when only legacy inputs are used.                         |
| `structured_output` | Use [`/schema`](/api-reference/endpoint/schema) | Present when deprecated `structured_output` input was used.       |
| `input_schema`      | Use [`/schema`](/api-reference/endpoint/schema) | Echo of the applied schema (deprecated path only).                |
| `schema_error`      | Use [`/schema`](/api-reference/endpoint/schema) | Error message if schema processing failed (deprecated path only). |

### Large Result Response

For documents with 70 or more pages, spreadsheet extractions, or any response payload above the 5 MB inline threshold, the API returns a one-time download link to `/results/{job_id}` instead of inlining the payload. This prevents timeout issues and keeps the immediate response small. The downloaded JSON is the complete extraction result with the normal response shape.

```json theme={null}
{
  "is_url": true,
  "url": "https://api.runpulse.com/results/abc123-def456-ghi789",
  "extraction_id": "abc123-def456-ghi789"
}
```

#### Large Result Response Fields

| Field           | Type    | Description                                                                                                                                                                                                                                                                                                                       |
| --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `is_url`        | boolean | Always `true` for URL-backed responses. Use this to detect URL-based responses.                                                                                                                                                                                                                                                   |
| `url`           | string  | One-time download link of the form `https://api.runpulse.com/results/{job_id}`. The link streams the complete extraction result the first time it is fetched and is then invalidated (subsequent reads return `410 Gone`). It also expires 1 hour after the job completes. Authenticate the request with your `x-api-key` header. |
| `extraction_id` | string  | Extraction/job identifier. The downloaded result contains the normal response fields, including metadata such as `page_count`, `credits_used`, and `plan_info` when available.                                                                                                                                                    |

<Warning>
  `/results/{job_id}` links are **single-use** and **expire 1 hour** after the job completes. Download and persist the payload immediately — do not pass the URL through queues or share it across workers.
</Warning>

#### Handling Large Document Responses

<CodeGroup>
  ```python Python theme={null}
  import requests
  from pulse import Pulse

  API_KEY = "YOUR_API_KEY"
  client = Pulse(api_key=API_KEY)

  response = client.extract(
      file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
  )

  if hasattr(response, "is_url") and response.is_url:
      full_result = requests.get(
          response.url,
          headers={"x-api-key": API_KEY},
      ).json()
      print(full_result["markdown"])
  else:
      print(response.markdown)
  ```

  ```typescript TypeScript theme={null}
  import { PulseClient } from 'pulse-ts-sdk';

  const API_KEY = "YOUR_API_KEY";
  const client = new PulseClient({ apiKey: API_KEY });

  const response = await client.extract({
      fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
  });

  if ((response as any).is_url) {
      const fullResult = await fetch((response as any).url, {
          headers: { "x-api-key": API_KEY },
      }).then(r => r.json());
      console.log(fullResult.markdown);
  } else {
      console.log(response.markdown);
  }
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@large_document.pdf"

  # Response: {"is_url": true, "url": "https://api.runpulse.com/results/abc123-..."}

  # Fetch the result once (single-use link, valid for 1 hour after job completion)
  curl -H "x-api-key: YOUR_API_KEY" \
    "https://api.runpulse.com/results/abc123-..."
  ```
</CodeGroup>

<Note>
  Because `/results/{job_id}` is one-time use, persist the result to your own storage on first download. If you need to access the result later, enable `storage.enabled` and retrieve it from your extraction library on the Pulse Platform.
</Note>

## Example Usage

### Basic Extraction

<CodeGroup>
  ```python Python theme={null}
  from pulse import Pulse
  from pulse.types import (
      ExtractRequestFigureProcessing,
      ExtractRequestExtensions,
      ExtractRequestExtensionsAltOutputs,
  )

  client = Pulse(api_key="YOUR_API_KEY")

  # Extract from URL with figure processing and HTML output
  response = client.extract(
      file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      figure_processing=ExtractRequestFigureProcessing(
          description=True,
      ),
      extensions=ExtractRequestExtensions(
          alt_outputs=ExtractRequestExtensionsAltOutputs(
              return_html=True,
          ),
      ),
  )

  print(f"Markdown: {response.markdown}")
  print(f"HTML: {response.extensions.alt_outputs.html}")
  print(f"Extraction ID: {response.extraction_id}")
  ```

  ```typescript TypeScript theme={null}
  import { PulseClient } from 'pulse-ts-sdk';

  const client = new PulseClient({ apiKey: "YOUR_API_KEY" });

  const response = await client.extract({
      fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      figureProcessing: { description: true },
      extensions: { altOutputs: { returnHtml: true } }
  });

  console.log(`Markdown: ${response.markdown}`);
  console.log(`HTML: ${response.extensions?.altOutputs?.html}`);
  console.log(`Extraction ID: ${response.extraction_id}`);
  ```

  ```bash curl theme={null}
  # Extract from URL with figure processing
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "file_url": "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      "figureProcessing": {"description": true},
      "extensions": {"altOutputs": {"returnHtml": true}}
    }'
  ```
</CodeGroup>

### File Upload

<CodeGroup>
  ```python Python theme={null}
  from pulse.types import ExtractRequestFigureProcessing

  # Upload and extract a local file
  with open("document.pdf", "rb") as f:
      response = client.extract(
          file=f,
      figure_processing=ExtractRequestFigureProcessing(
          description=True,
      ),
      )
  ```

  ```typescript TypeScript theme={null}
  import * as fs from 'fs';

  const fileBuffer = fs.readFileSync("document.pdf");
  const blob = new Blob([fileBuffer], { type: 'application/pdf' });

  const response = await client.extract({
      file: blob,
  });
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@document.pdf"
  ```
</CodeGroup>

### Structured Data (Extract → Schema)

<Warning>
  The `structured_output` parameter on `/extract` is **deprecated**. Use the [`/schema`](/api-reference/endpoint/schema) endpoint after extraction instead. This gives you better control, re-runnability, and support for split-mode schemas.
</Warning>

**Recommended two-step approach:**

<CodeGroup>
  ```python Python theme={null}
  # Step 1: Extract the document
  response = client.extract(
      file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
  )

  extraction_id = response.extraction_id

  # Step 2: Apply schema separately
  schema_result = client.schema(
      extraction_id=extraction_id,
      schema_config={
          "input_schema": {
              "type": "object",
              "properties": {
                  "total": {"type": "number"},
                  "vendor": {"type": "string"}
              }
          },
          "schema_prompt": "Extract invoice total and vendor"
      }
  )

  print(schema_result.schema_output)
  ```

  ```typescript TypeScript theme={null}
  // Step 1: Extract the document
  const response = await client.extract({
      fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf"
  });

  const extractionId = response.extraction_id;

  // Step 2: Apply schema separately
  const schemaResult = await client.schema({
      extraction_id: extractionId,
      schema_config: {
          input_schema: {
              type: "object",
              properties: {
                  total: { type: "number" },
                  vendor: { type: "string" }
              }
          },
          schema_prompt: "Extract invoice total and vendor"
      }
  });

  console.log(schemaResult.schema_output);
  ```

  ```bash curl theme={null}
  # Step 1: Extract the document
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@invoice.pdf"

  # Response includes extraction_id: "abc123-..."

  # Step 2: Apply schema
  curl -X POST https://api.runpulse.com/schema \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "extraction_id": "abc123-...",
      "schema_config": {
        "input_schema": {"type": "object", "properties": {"total": {"type": "number"}, "vendor": {"type": "string"}}},
        "schema_prompt": "Extract invoice total and vendor"
      }
    }'
  ```
</CodeGroup>

### Document Metadata

Enable `extensions.document_metadata` to read native properties from the original
file before conversion, rendering, or OCR. The option is a single boolean; Pulse
returns every safely recoverable field for the detected format.

<CodeGroup>
  ```python Python SDK theme={null}
  from pulse.types import ExtractRequestExtensions

  response = client.extract(
      file_url="https://example.com/report.pdf",
      extensions=ExtractRequestExtensions(
          document_metadata=True,
      ),
  )

  metadata = response.extensions.document_metadata
  print(metadata.properties.title)
  print(metadata.structure.page_count)
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@report.pdf" \
    -F 'extensions={"document_metadata":true};type=application/json'
  ```
</CodeGroup>

```json theme={null}
{
  "extensions": {
    "document_metadata": {
      "file": {
        "name": "pulse-complex-metadata-10-page.pdf",
        "extension": ".pdf",
        "media_type": "application/pdf",
        "size_bytes": 32506
      },
      "properties": {
        "title": "Pulse Complex Metadata Validation Report",
        "authors": ["Ritvik Pandey", "Pulse Document Intelligence"],
        "created_at": "2026-01-15T09:30:00-08:00"
      },
      "structure": {
        "page_count": 10,
        "outline_count": 10,
        "attachment_count": 1,
        "annotation_count": 5,
        "form_field_count": 3
      },
      "warnings": []
    }
  }
}
```

Absent metadata fields are omitted rather than returned as `null`. Metadata is
evidence declared by the source file and is not independently verified. Original
camera files may contain sensitive capture timestamps or GPS coordinates.

See [Document Metadata](/concepts/processing-parameters-document-metadata) for
format-specific behavior and implementation guidance.

### Page Range and Chunking

<CodeGroup>
  ```python Python theme={null}
  from pulse.types import (
      ExtractRequestExtensions,
      ExtractRequestExtensionsChunking,
  )

  response = client.extract(
      file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      pages="1-5,10",  # 1-indexed
      extensions=ExtractRequestExtensions(
          chunking=ExtractRequestExtensionsChunking(
              chunk_types=["semantic", "page"],
              chunk_size=1000,
          ),
      ),
  )

  # Chunk data is in extensions.chunking
  print(response.extensions.chunking.semantic)
  print(response.extensions.chunking.page)
  ```

  ```typescript TypeScript theme={null}
  const response = await client.extract({
      fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      pages: "1-5,10",  // 1-indexed
      extensions: {
          chunking: {
              chunkTypes: ["semantic", "page"],
              chunkSize: 1000
          }
      }
  });

  // Chunk data is in extensions.chunking
  console.log(response.extensions?.chunking?.semantic);
  console.log(response.extensions?.chunking?.page);
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@document.pdf" \
    -F "pages=1-5,10" \
    -F 'extensions={"chunking": {"chunkTypes": ["semantic", "page"], "chunkSize": 1000}}'
  ```
</CodeGroup>

### Footnote References

Enable `extensions.footnote_references` to detect footnote markers (e.g. `*`, `†`, `1`) in body text and link them to the footnote explanation paragraphs at the bottom of the page. Each result item includes the marker symbol, the bounding-box text ID of the footnote, and the bounding-box text IDs of all body-text paragraphs that reference it.

<CodeGroup>
  ```python Python theme={null}
  from pulse.types import ExtractRequestExtensions

  response = client.extract(
      file_url="https://example.com/research-paper.pdf",
      extensions=ExtractRequestExtensions(
          footnote_references=True,
      ),
  )

  # Footnote links are in extensions.footnote_references
  for ref in response.extensions.footnote_references:
      print(f"Marker: {ref.symbol}")
      print(f"  Footnote: {ref.footnote_text_id}")
      print(f"  Referenced by: {ref.reference_text_ids}")
  ```

  ```typescript TypeScript theme={null}
  const response = await client.extract({
      fileUrl: "https://example.com/research-paper.pdf",
      extensions: {
          footnoteReferences: true
      }
  });

  // Footnote links are in extensions.footnoteReferences
  for (const ref of response.extensions?.footnoteReferences ?? []) {
      console.log(`Marker: ${ref.symbol}`);
      console.log(`  Footnote: ${ref.footnoteTextId}`);
      console.log(`  Referenced by: ${ref.referenceTextIds}`);
  }
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@research-paper.pdf" \
    -F 'extensions={"footnoteReferences": true}'
  ```
</CodeGroup>

#### Example Response

```json theme={null}
{
  "markdown": "...",
  "bounding_boxes": { ... },
  "extensions": {
    "footnoteReferences": [
      {
        "symbol": "*",
        "footnoteTextId": "txt-11",
        "referenceTextIds": ["txt-4", "txt-5", "txt-6", "txt-7", "txt-8"]
      },
      {
        "symbol": "†",
        "footnoteTextId": "txt-12",
        "referenceTextIds": ["txt-8"]
      },
      {
        "symbol": "4",
        "footnoteTextId": "txt-48",
        "referenceTextIds": ["txt-45"]
      }
    ]
  }
}
```

#### Footnote Reference Fields

| Field              | Type      | Description                                                                                                                                                                       |
| ------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `symbol`           | string    | The footnote marker symbol as detected in the document (e.g. `*`, `†`, `‡`, `1`, `#`).                                                                                            |
| `footnoteTextId`   | string    | The bounding-box text ID (e.g. `txt-11`) of the footnote explanation paragraph. Cross-reference with `bounding_boxes.Footer` to get the footnote's content and position.          |
| `referenceTextIds` | string\[] | Bounding-box text IDs of body-text paragraphs that contain a reference to this footnote. Cross-reference with `bounding_boxes.Text` to get each paragraph's content and position. |

<Info>
  Footnote reference detection uses Azure Document Intelligence for paragraph classification, supplemented by PyMuPDF native text extraction for accurate symbol identification. This handles common OCR confusion between visually similar symbols like `†`/`+` and `‡`/`#`. Supported marker types include numbered (`1`, `2`, `3`), symbolic (`*`, `†`, `‡`, `§`, `#`), and lettered (`a`, `b`, `c`) footnotes.
</Info>

### Excel Spreadsheet Options

<CodeGroup>
  ```python Python theme={null}
  from pulse import Pulse
  from pulse.types import ExtractRequestSpreadsheet

  client = Pulse(api_key="YOUR_API_KEY")

  # Extract from Excel with hidden content included
  response = client.extract(
      file=open("financials.xlsx", "rb"),
      spreadsheet=ExtractRequestSpreadsheet(
          include_hidden_rows=True,
          include_hidden_cols=True,
          include_hidden_sheets=False,
      ),
  )

  print(response.markdown)
  ```

  ```typescript TypeScript theme={null}
  import { PulseClient } from 'pulse-ts-sdk';

  const client = new PulseClient({
      headers: { 'x-api-key': 'YOUR_API_KEY' }
  });

  const response = await client.extract({
      file: fs.createReadStream("financials.xlsx"),
      spreadsheet: {
          includeHiddenRows: true,
          includeHiddenCols: true,
          includeHiddenSheets: false
      }
  });

  console.log(response.markdown);
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@financials.xlsx" \
    -F 'spreadsheet={"includeHiddenRows": true, "includeHiddenCols": true, "includeHiddenSheets": false, "cellData": true}'
  ```
</CodeGroup>

<Note>
  Spreadsheet responses are URL-backed by default: the immediate response is `is_url: true` with a one-time `/results/{job_id}` link. Fetch that URL to receive the complete extraction result. The result shape is unchanged: table metadata remains under `bounding_boxes.Tables[].cell_data` when `spreadsheet.cell_data` is `true` (the default). Set top-level `force_url: false` only if you need the full result inline.
</Note>

<Note>
  Workbooks exported from claims systems, ERPs, and other automated pipelines often declare a "used range" that extends hundreds of thousands of rows past where the data actually ends. Set `spreadsheet.only_data_rows: true` and `spreadsheet.only_data_cols: true` to have Pulse trim those trailing empty "phantom" rows and columns before parsing. Surviving cells keep their original A1 coordinates, so any citation or bounding box that references a specific cell remains stable. Both flags default to `false`. See the extraction options above for the full reference.
</Note>

### Excel Charts and Embedded Images

When you set `figure_processing.show_images: true` on an Excel workbook, every embedded chart and image is collected from the workbook directly and returned under `bounding_boxes.Images[]`. Each entry carries a Pulse-hosted `image_url` you can fetch via [`results.getImage`](/api-reference/endpoint/results-image) (or any HTTP client with your API key) to get the raw PNG/JPEG bytes.

<CodeGroup>
  ```python Python theme={null}
  import re
  from pulse import Pulse
  from pulse.types import ExtractRequestFigureProcessing

  client = Pulse(api_key="YOUR_API_KEY")

  # 1) Extract the workbook with show_images enabled.
  response = client.extract(
      file=open("financials.xlsx", "rb"),
      figure_processing=ExtractRequestFigureProcessing(
          show_images=True,
          description=False,
      ),
  )

  # 2) Walk the typed Images array.
  for img in response.bounding_boxes.images or []:
      print(f"{img.id}: {img.visual_type} '{img.chart_title}' @ {img.excel_range}")
      print(f"    url: {img.image_url}")

  # 3) Fetch the bytes for one chart.
  img = response.bounding_boxes.images[0]
  m = re.search(r"/results/([^/]+)/images/([^/?#]+)", img.image_url)
  job_id, filename = m.group(1), m.group(2)

  chunks = list(client.results.get_image(job_id=job_id, filename=filename))
  with open("chart.png", "wb") as f:
      f.write(b"".join(chunks))
  ```

  ```typescript TypeScript theme={null}
  import { PulseClient } from "pulse-ts-sdk";
  import * as fs from "node:fs";

  const client = new PulseClient({ apiKey: "YOUR_API_KEY" });

  // 1) Extract the workbook with show_images enabled.
  const response = await client.extract({
      file: fs.createReadStream("financials.xlsx"),
      figureProcessing: { showImages: true, description: false },
  });

  // 2) Walk the typed Images array.
  for (const img of response.boundingBoxes?.Images ?? []) {
      console.log(
          `${img.id}: ${img.visualType} '${img.chartTitle}' @ ${img.excelRange}`,
      );
      console.log(`    url: ${img.imageUrl}`);
  }

  // 3) Fetch the bytes for one chart.
  const url = response.boundingBoxes?.Images?.[0]?.imageUrl;
  const m = url?.match(/\/results\/([^/]+)\/images\/([^/?#]+)/);
  const [, jobId, filename] = m!;
  const image = await client.results.getImage({ jobId, filename });
  // Persist `image` per your runtime (e.g. `await image.bytes()`).
  ```

  ```bash curl theme={null}
  # Step 1: extract and capture an image_url from the response.
  curl -sS -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@financials.xlsx" \
    -F 'figure_processing={"show_images": true}' \
    | jq -r '.bounding_boxes.Images[0].image_url'

  # Step 2: fetch the PNG bytes.
  curl -sS -X GET "https://api.runpulse.com/results/$JOB_ID/images/excel_image_1_1.png" \
    -H "x-api-key: YOUR_API_KEY" \
    -o chart.png
  ```
</CodeGroup>

#### Example `bounding_boxes.Images` Entry

```json theme={null}
{
  "id": "excel_image_1_1",
  "visual_type": "chart",
  "page_number": 1,
  "bounding_box": [],
  "image_url": "https://api.runpulse.com/results/13e3e75f-.../images/excel_image_1_1.png",
  "sheet_name": "Charts",
  "excel_range": "D2",
  "chart_type": "BarChart",
  "chart_title": "Revenue",
  "source_ranges": ["'Charts'!$A$2:$A$5", "'Charts'!$B$2:$B$5"],
  "description": "Bar chart showing revenue by quarter."
}
```

See [Bounding Boxes — Images Array](/api-reference/bounding-boxes#images-array) for the full field reference and [Get Result Image](/api-reference/endpoint/results-image) for the auth requirement on `image_url`.

### Disable Storage

<CodeGroup>
  ```python Python theme={null}
  response = client.extract(
      file_url="https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      storage={"enabled": False}
  )
  ```

  ```typescript TypeScript theme={null}
  const response = await client.extract({
      fileUrl: "https://platform.runpulse.com/api/examples/637e5678-30b1-45fa-acc4-877f2d636419/pdf",
      storage: { enabled: false }
  });
  ```

  ```bash curl theme={null}
  curl -X POST https://api.runpulse.com/extract \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@document.pdf" \
    -F 'storage={"enabled": false}'
  ```
</CodeGroup>


## OpenAPI

````yaml POST /extract
openapi: 3.1.0
info:
  title: Pulse API Structure
  version: 0.1.0
  description: >-
    Canonical contract for the Pulse extraction APIs. This specification is the
    single source of truth for shared request/response models that client and
    server packages consume.
servers:
  - url: https://api.runpulse.com
    description: Default Pulse API base URL
security:
  - ApiKey: []
paths:
  /extract:
    post:
      tags:
        - Extract
      summary: Extract rich content from a document
      description: >-
        The primary endpoint for the Pulse API. Parses uploaded documents or
        remote

        file URLs and returns rich markdown content with optional structured
        data

        extraction based on user-provided schemas and extraction options.


        Set `async: true` to return immediately with a job_id for polling via

        GET /job/{jobId}. Otherwise processes synchronously.


        To process many files at once, see [Batch
        Extract](api:POST/batch/extract)

        or the [Batch Processing guide](/batch).
      operationId: extractDocument
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/ExtractInput'
            encoding:
              figureProcessing:
                contentType: application/json
              extensions:
                contentType: application/json
              spreadsheet:
                contentType: application/json
              storage:
                contentType: application/json
              structuredOutput:
                contentType: application/json
              schema:
                contentType: application/json
      responses:
        '200':
          description: >-
            Extraction result.  For documents under 70 pages the full result is
            returned inline.  For larger documents and spreadsheet extractions
            the response can contain `is_url: true` and a single-use `url` to
            download the full result via `GET /results/{jobId}`.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ExtractResponse'
                  - $ref: '#/components/schemas/ExtractLargeResultResponse'
        '202':
          description: Extraction job accepted (when async=true)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AsyncSubmissionResponse'
        '400':
          description: Invalid request parameters
        '401':
          description: Authentication failed or missing API key
        '429':
          description: Rate limit exceeded
components:
  schemas:
    ExtractInput:
      description: >-
        Input schema for extraction requests. Provide either file (direct
        upload) or fileUrl (remote URL).
      allOf:
        - $ref: '#/components/schemas/ExtractSourceMultipart'
        - $ref: '#/components/schemas/ExtractOptions'
    ExtractResponse:
      type: object
      description: >-
        Full extraction result returned by the synchronous `/extract` endpoint.
        Inherits all core fields and adds deprecated backward-compatibility
        fields.
      allOf:
        - $ref: '#/components/schemas/ExtractResultCore'
        - type: object
          properties:
            html:
              type: string
              deprecated: true
              description: >-
                **Deprecated** — Use `extensions.altOutputs.html` instead. HTML
                representation of the extracted content. Present when the legacy
                `returnHtml` input was used.
            chunks:
              type: object
              deprecated: true
              description: >-
                **Deprecated** — Use `extensions.chunking` instead. Document
                content split into chunks. Present when the legacy `chunking`
                input was used.
              properties:
                semantic:
                  type: array
                  items:
                    type: string
                header:
                  type: array
                  items:
                    type: string
                page:
                  type: array
                  items:
                    type: string
                recursive:
                  type: array
                  items:
                    type: string
            structured_output:
              deprecated: true
              description: >-
                **Deprecated** — Only present when the deprecated
                `structuredOutput` input parameter was used. Use the `/schema`
                endpoint after extraction instead.
              allOf:
                - $ref: '#/components/schemas/StructuredOutputResult'
            input_schema:
              type: object
              deprecated: true
              description: >-
                **Deprecated** — Echo of the schema that was applied. Only
                present when the deprecated `structuredOutput` input parameter
                was used.
              additionalProperties: true
            schema_error:
              type: string
              deprecated: true
              description: >-
                **Deprecated** — Error message if schema processing failed via
                the deprecated `structuredOutput` input parameter.
            content:
              type: string
              deprecated: true
              description: >-
                **Deprecated** — Alias for `markdown`. Included for backward
                compatibility with older SDK versions. Prefer `markdown`.
            job_id:
              type: string
              deprecated: true
              description: >-
                **Deprecated** — Identifier assigned to the extraction job.
                Retained for backward compatibility.
            metadata:
              type: object
              additionalProperties: true
              deprecated: true
              description: >-
                **Deprecated** — Additional metadata supplied by the backend.
                Retained for backward compatibility.
      additionalProperties: true
    ExtractLargeResultResponse:
      type: object
      description: >-
        Returned instead of the full extraction result for large results,
        including documents with 70 or more pages and spreadsheet extractions.
        The `url` field is a single-use download link; fetch it once to retrieve
        the complete `ExtractResultCore` payload. Subsequent requests to the
        same URL return 410 Gone.
      required:
        - is_url
        - url
      properties:
        is_url:
          type: boolean
          description: Always `true` for large document responses.
          enum:
            - true
        url:
          type: string
          description: >-
            Single-use URL to download the full extraction result.  After one
            successful download the resource is deleted and further requests
            return 410 Gone.
        extraction_id:
          type: string
          format: uuid
          description: Extraction identifier (when storage is enabled).
        page_count:
          type: integer
          minimum: 1
          description: Number of pages in the document.
        plan_info:
          allOf:
            - $ref: '#/components/schemas/PlanInfo'
          description: >-
            Billing tier and cumulative usage information. Includes
            `total_credits_used` (primary billing metric) and `pages_used`
            (legacy compatibility).
    AsyncSubmissionResponse:
      type: object
      description: >-
        Acknowledgement returned when a request is submitted for asynchronous
        processing. Poll `GET /job/{job_id}` to check status and retrieve
        results.
      required:
        - job_id
        - status
      properties:
        job_id:
          type: string
          description: Identifier assigned to the asynchronous job.
        status:
          type: string
          description: Initial status reported by the server.
          enum:
            - pending
            - processing
            - completed
            - failed
            - canceled
        message:
          type: string
          description: Human-readable description of the accepted job.
        queuedAt:
          type: string
          format: date-time
          deprecated: true
          description: >-
            **Deprecated** — Timestamp indicating when the job was accepted.
            Retained for backward compatibility. Use `GET /job/{jobId}` for
            timing details.
        credits_used:
          type: number
          format: float
          nullable: true
          description: >-
            Number of credits consumed by this request. Only present when the
            organization has the credit billing system enabled.
    ExtractSourceMultipart:
      type: object
      description: >-
        Document source definition for multipart/form-data requests. Provide
        exactly one of `file` (direct upload) or `fileUrl` (remote URL).
      properties:
        file:
          type: string
          format: binary
          description: Document to upload directly. Required unless fileUrl is provided.
        fileUrl:
          type: string
          format: uri
          x-fern-property-name: file_url
          description: >-
            Public or pre-signed URL that Pulse will download and extract.
            Required unless file is provided.
    ExtractOptions:
      type: object
      description: Common extraction options shared by sync and async extraction requests.
      properties:
        model:
          type: string
          description: >-
            Extraction model to use. When set to `pulse-ultra-2`, routes the
            request through Pulse Ultra 2 (self-hosted VPC model) instead of the
            default cloud-based service. If omitted or set to `default`, the
            default model is used.
          enum:
            - default
            - pulse-ultra-2
        detectSelections:
          type: boolean
          x-fern-property-name: detect_selections
          description: >-
            Pulse Ultra 2 only. Enables a specialized selection-mark detection
            pass that improves selected/unselected state accuracy for forms,
            checkboxes, radio buttons, handwritten checkmarks, X marks, and
            similar controls. Enabled by default when `model` is
            `pulse-ultra-2`; set to false to skip this pass. Passing true
            without `model: pulse-ultra-2` returns a validation error.
        extractionConfigId:
          type: string
          format: uuid
          x-fern-property-name: extraction_config_id
          description: >-
            UUID of a saved extraction configuration (a "preset"). When
            provided, the server loads the saved configuration and applies its
            options on top of any inline parameters supplied in this request.
            Inline parameters always take precedence over preset values for the
            same field. Saved configs are managed via the platform UI or the
            `input_extractions` admin endpoints.
        pages:
          type: string
          description: >-
            Page range filter supporting segments such as `1-2` or mixed ranges
            like `1-2,5`.
          pattern: ^[0-9]+(-[0-9]+)?(,[0-9]+(-[0-9]+)?)*$
        forceUrl:
          type: boolean
          x-fern-property-name: force_url
          default: false
          description: >-
            When true, return the complete extraction result as a URL even if it
            is small. Spreadsheet extractions use URL delivery by default; set
            `force_url: false` to request inline spreadsheet output. URL
            delivery changes only the transport, not the result shape.
        figureProcessing:
          type: object
          x-fern-property-name: figure_processing
          description: >-
            Settings that control how figures and embedded visuals are
            processed. Applies to both PDFs/images (where figures are detected
            from layout) and spreadsheets (where charts and embedded images are
            read directly from the workbook). These options affect the markdown
            output and the `bounding_boxes.Images[]` array; they do not produce
            additional output fields elsewhere in the response.
          properties:
            description:
              type: boolean
              default: false
              description: >-
                Generate descriptive captions for extracted visuals. When
                `true`, applies to both detected charts and non-chart images.
                Captions appear under `bounding_boxes.Images[].description` and
                inline in the markdown output where applicable.
            showImages:
              type: boolean
              x-fern-property-name: show_images
              default: false
              description: >-
                Return image URLs for extracted visuals. When `true`, applies to
                both charts and non-chart images. URLs are emitted under
                `bounding_boxes.Images[].image_url` — typically a Pulse-hosted
                proxy URL served from `GET /results/{jobId}/images/{filename}`.
                Spreadsheet charts and embedded images are read directly from
                the workbook; PDF/image inputs use detected figure regions.
        extensions:
          type: object
          description: >-
            Settings that enable additional processing passes or alternate
            output formats. Each enabled extension produces a corresponding
            output field under `response.extensions.*`.
          properties:
            footnoteReferences:
              type: boolean
              x-fern-property-name: footnote_references
              default: false
              description: Link footnote markers to their corresponding footnote text.
            document_metadata:
              type: boolean
              default: false
              description: >-
                Extract the maximum safely recoverable metadata from the
                original file bytes before conversion, rendering, or OCR.
                Results appear under `response.extensions.document_metadata`.
            chunking:
              type: object
              description: >-
                Chunking configuration. When provided, the document is split
                into chunks using the specified strategies. Results appear in
                `response.extensions.chunking`.
              properties:
                chunkTypes:
                  type: array
                  x-fern-property-name: chunk_types
                  items:
                    type: string
                    enum:
                      - semantic
                      - header
                      - page
                      - recursive
                  description: >-
                    List of chunking strategies to apply (e.g. `["semantic",
                    "header", "page", "recursive"]`).
                chunkSize:
                  type: integer
                  minimum: 1
                  x-fern-property-name: chunk_size
                  description: Maximum characters per chunk.
            altOutputs:
              type: object
              x-fern-property-name: alt_outputs
              description: >-
                Alternate output format options. Each enabled format produces a
                corresponding field under `response.extensions.altOutputs`.
              properties:
                wlbb:
                  type: boolean
                  default: false
                  description: >-
                    Enable word-level bounding boxes. Runs an additional OCR
                    model to derive bounding boxes for each word. Only applies
                    to PDFs. Results in `response.extensions.altOutputs.wlbb`.
                returnHtml:
                  type: boolean
                  x-fern-property-name: return_html
                  default: false
                  description: >-
                    Include an HTML representation of the document. When
                    enabled, `response.markdown` is still present and the HTML
                    is available at `response.extensions.altOutputs.html`.
                returnXml:
                  type: boolean
                  x-fern-property-name: return_xml
                  default: false
                  description: >-
                    Include an XML representation of the document. Results in
                    `response.extensions.altOutputs.xml`. (Work in progress.)
        spreadsheet:
          type: object
          description: >-
            Settings for Excel/spreadsheet extraction. Controls handling of
            hidden rows, columns, and sheets, whether numeric cells are rendered
            using their display format or underlying raw value, whether table
            cell metadata is captured, and optional trimming of empty phantom
            rows/columns past the last data-bearing cell. Applies to `.xlsx`,
            `.xlsm`, and `.xls` files. Accepts both camelCase and snake_case
            field names.
          properties:
            includeHiddenRows:
              type: boolean
              x-fern-property-name: include_hidden_rows
              default: false
              description: Include rows that are hidden in the Excel workbook.
            includeHiddenCols:
              type: boolean
              x-fern-property-name: include_hidden_cols
              default: false
              description: Include columns that are hidden in the Excel workbook.
            includeHiddenSheets:
              type: boolean
              x-fern-property-name: include_hidden_sheets
              default: false
              description: Include sheets that are hidden in the Excel workbook.
            useRawValues:
              type: boolean
              x-fern-property-name: use_raw_values
              default: false
              description: >-
                Emit the underlying numeric value for number cells instead of
                the Excel display-formatted text (e.g. `1201.67` rather than
                `$1,202` when the cell uses a rounded currency format).
                Percent-formatted cells and dates keep their display rendering.
                Does not apply to legacy `.xls` files.
            onlyDataRows:
              type: boolean
              x-fern-property-name: only_data_rows
              default: false
              description: >-
                When true, trim trailing empty rows past the last cell carrying
                a value or formula before parsing. Excel exports from claims
                systems and ERPs routinely declare a used range with hundreds of
                thousands of empty-but-styled phantom rows that inflate file
                size and exhaust parser memory; enabling this strips them out
                without touching any cell that actually has data. Surviving
                cells keep their original A1 coordinates so citations that
                reference a specific cell remain stable. Defaults to false.
            onlyDataCols:
              type: boolean
              x-fern-property-name: only_data_cols
              default: false
              description: >-
                When true, trim trailing empty columns past the last cell
                carrying a value or formula. Same rationale and
                coordinate-stability guarantee as `onlyDataRows`. Defaults to
                false.
            cellData:
              type: boolean
              x-fern-property-name: cell_data
              default: true
              description: >-
                Include cell-level table metadata under
                `bounding_boxes.Tables[].cell_data`. Set to false to omit this
                metadata and reduce output size.
        storage:
          type: object
          description: >-
            Options for persisting extraction artifacts. When enabled (default),
            artifacts are saved to storage and a database record is created.
          properties:
            enabled:
              type: boolean
              description: >-
                Whether to persist extraction artifacts. Set to false for
                temporary extractions with no storage or database record.
              default: true
            folderName:
              type: string
              x-fern-property-name: folder_name
              description: >-
                Target folder name to save the extraction to. Creates the folder
                if it doesn't exist.
            folderId:
              type: string
              format: uuid
              x-fern-property-name: folder_id
              description: >-
                Target folder ID to save the extraction to. Takes precedence
                over folderName if both are provided.
        async:
          type: boolean
          default: false
          description: >-
            If true, returns immediately with a job_id for polling via GET
            /job/{jobId}. Otherwise processes synchronously.
        structuredOutput:
          type: object
          x-fern-property-name: structured_output
          deprecated: true
          description: >-
            **⚠️ DEPRECATED** — Use the `/schema` endpoint after extraction
            instead. Pass the `extraction_id` from the extract response to
            `/schema` with your `schema_config`. This parameter still works for
            backward compatibility but will be removed in a future version.
          properties:
            schema:
              type: object
              description: JSON schema describing the structured data to extract.
            schemaPrompt:
              type: string
              x-fern-property-name: schema_prompt
              description: Natural language prompt with additional extraction instructions.
            effort:
              type: boolean
              default: false
              description: >-
                Use higher quality model for better results. When true, uses a
                more capable model at the cost of higher latency.
        schema:
          description: >-
            (Deprecated) JSON schema describing structured data to extract. Use
            structuredOutput instead. Accepts either a JSON object or a
            stringified JSON representation.
          oneOf:
            - type: object
            - type: string
          deprecated: true
        schemaPrompt:
          type: string
          x-fern-property-name: schema_prompt
          description: >-
            (Deprecated) Natural language prompt for schema-guided extraction.
            Use structuredOutput.schemaPrompt instead.
          deprecated: true
        customPrompt:
          type: string
          x-fern-property-name: custom_prompt
          description: >-
            (Deprecated) Custom instructions that augment the default extraction
            behaviour. Use `figureProcessing` or `extensions` instead.
          deprecated: true
        chunking:
          type: string
          deprecated: true
          description: >-
            **⚠️ DEPRECATED** — Use `extensions.chunking.chunkTypes` instead.
            Comma-separated list of chunking strategies to apply (for example
            `semantic,header,page,recursive`). Still accepted for backward
            compatibility.
        chunkSize:
          type: integer
          minimum: 1
          x-fern-property-name: chunk_size
          deprecated: true
          description: >-
            **⚠️ DEPRECATED** — Use `extensions.chunking.chunkSize` instead.
            Override for maximum characters per chunk when chunking is enabled.
        extractFigure:
          type: boolean
          x-fern-property-name: extract_figure
          deprecated: true
          description: '**⚠️ DEPRECATED** — Toggle to enable figure extraction in results.'
          default: false
        figureDescription:
          type: boolean
          x-fern-property-name: figure_description
          deprecated: true
          description: >-
            **⚠️ DEPRECATED** — Use `figureProcessing.description` instead.
            Toggle to generate descriptive captions for extracted figures.
          default: false
        showImages:
          type: boolean
          x-fern-property-name: show_images
          deprecated: true
          description: >-
            **⚠️ DEPRECATED** — Use `figureProcessing.showImages` instead. Embed
            base64-encoded images inline in figure tags in the output. Increases
            response size.
          default: false
        returnHtml:
          type: boolean
          x-fern-property-name: return_html
          deprecated: true
          description: >-
            **⚠️ DEPRECATED** — Use `extensions.altOutputs.returnHtml` instead.
            Whether to include HTML representation alongside markdown in the
            response.
          default: false
        thinking:
          type: boolean
          description: (Deprecated) Enables expanded rationale output for debugging.
          default: false
          deprecated: true
    ExtractResultCore:
      type: object
      description: >-
        Core extraction result fields shared by the synchronous `/extract`
        endpoint and the pipeline extract step.
      properties:
        markdown:
          type: string
          description: >-
            Primary markdown content extracted from the document. Always present
            in the new format.
        extensions:
          type: object
          description: >-
            Output from enabled extensions. Each key corresponds to an extension
            that was enabled in the request under `extensions.*`. Only keys for
            enabled extensions are present.
          properties:
            document_metadata:
              allOf:
                - $ref: '#/components/schemas/DocumentMetadataResult'
              description: >-
                Native and structural metadata from the original file. Present
                only when `extensions.document_metadata` was true.
            chunking:
              type: object
              description: >-
                Chunk results by strategy. Present when `extensions.chunking`
                was provided in the request.
              properties:
                semantic:
                  type: array
                  items:
                    type: string
                  description: Semantically-segmented chunks.
                header:
                  type: array
                  items:
                    type: string
                  description: Chunks split by document headers/headings.
                page:
                  type: array
                  items:
                    type: string
                  description: One chunk per page.
                recursive:
                  type: array
                  items:
                    type: string
                  description: Recursively-split chunks respecting size limits.
            footnoteReferences:
              type: array
              x-fern-property-name: footnote_references
              description: >-
                List of detected footnotes with their in-text references.
                Present when `extensions.footnoteReferences` was enabled. Each
                item links a footnote paragraph to the body-text paragraphs that
                reference it, using bounding-box text IDs.
              items:
                type: object
                properties:
                  symbol:
                    type: string
                    description: The footnote marker symbol (e.g. "*", "†", "1", "#").
                  footnoteTextId:
                    type: string
                    description: >-
                      The bounding-box text ID (e.g. "txt-15") of the footnote
                      explanation paragraph.
                  referenceTextIds:
                    type: array
                    description: >-
                      Bounding-box text IDs of body-text paragraphs that contain
                      a reference to this footnote marker.
                    items:
                      type: string
            altOutputs:
              type: object
              x-fern-property-name: alt_outputs
              description: >-
                Alternate output formats. Each key corresponds to an enabled alt
                output.
              properties:
                wlbb:
                  type: object
                  description: >-
                    Word-level bounding box data. Present when
                    `extensions.altOutputs.wlbb` was enabled and input is a PDF.
                  properties:
                    words:
                      type: array
                      description: List of detected words with their positions.
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                            description: >-
                              Unique identifier for the word (e.g. "w-1", "w-2",
                              …).
                          text:
                            type: string
                            description: The recognised word text.
                          page_number:
                            type: integer
                            minimum: 1
                            description: 1-indexed page number in the original document.
                          bounding_box:
                            type: array
                            description: >-
                              Flat 4-corner polygon: [x1,y1, x2,y2, x3,y3,
                              x4,y4]. All coordinates normalised to 0–1 range.
                            items:
                              type: number
                            minItems: 8
                            maxItems: 8
                          average_word_confidence:
                            type: number
                            description: Recognition confidence score (0–1).
                    error:
                      type: string
                      description: Error message if word-level extraction failed.
                html:
                  type: string
                  description: >-
                    HTML representation of the document. Present when
                    `extensions.altOutputs.returnHtml` was enabled.
                xml:
                  type: string
                  description: >-
                    XML representation of the document. Present when
                    `extensions.altOutputs.returnXml` was enabled. (WIP)
        bounding_boxes:
          allOf:
            - $ref: '#/components/schemas/BoundingBoxes'
          description: >-
            Positional bounding-box data for text, titles, headers, footers,
            images, and tables. `Images` carries chart/image visuals (with
            `image_url` when `figure_processing.show_images` is enabled),
            `Tables` the detected tables, and `Text`/`Title`/`Footer` the
            paragraph/title/footer regions. Additional keys (e.g.
            `markdown_with_ids`, `defined_names`) round-trip without being
            typed.
        extraction_id:
          type: string
          format: uuid
          description: >-
            Persisted extraction ID. Present when storage is enabled (default).
            Use this ID with `/split` and `/schema` endpoints.
        extraction_url:
          type: string
          description: >-
            URL to view the extraction on the Pulse platform. Present when
            storage is enabled.
        page_count:
          type: integer
          minimum: 1
          description: Number of pages processed.
        plan_info:
          allOf:
            - $ref: '#/components/schemas/PlanInfo'
          description: >-
            Billing tier and cumulative usage information. Includes
            `total_credits_used` (primary billing metric) and `pages_used`
            (legacy compatibility).
        warnings:
          type: array
          items:
            type: string
          description: >-
            Non-fatal warnings generated during extraction. Includes deprecation
            notices when legacy input parameters are used, as well as processing
            warnings (e.g. word-level bounding box limitations).
        credits_used:
          type: number
          format: float
          nullable: true
          description: >-
            Number of credits consumed by this request. Only present when the
            organization has the credit billing system enabled.
    StructuredOutputResult:
      type: object
      description: Result of schema extraction with values and citations.
      properties:
        values:
          type: object
          description: Extracted values matching the provided schema.
          additionalProperties: true
        citations:
          type: object
          description: Citation references linking extracted values to source locations.
          additionalProperties: true
    PlanInfo:
      type: object
      description: >-
        Cumulative billing snapshot for the calling organization. Sourced from
        the `pulse-org-stats` aggregate table maintained asynchronously by the
        org-stats Lambda; the in-flight request's contribution is added on top
        so every response reflects post-request state. Returned by every
        endpoint that consumes credits (extract, schema, tables, split, form,
        and their batch / pipeline equivalents).
      properties:
        tier:
          type: string
          description: Billing tier, e.g. `"trial"`, `"growth"`, `"pulse_ultra_2"`.
        total_credits_used:
          type: number
          format: float
          description: >-
            Total credits consumed by the organization to date, including this
            request. The primary billing metric going forward.
        pages_used:
          type: integer
          minimum: 0
          description: >-
            Total pages processed by the organization to date, including this
            request. Kept for backward compatibility with clients that haven't
            migrated to `total_credits_used`.
        note:
          type: string
          description: >-
            Optional human-readable note about billing state for this response
            (e.g. trial credits remaining). Omitted when no note applies.
    DocumentMetadataResult:
      type: object
      description: >-
        Native and derived metadata extracted from the original source bytes.
        Values are file evidence and are not independently verified claims.
      required:
        - file
        - properties
        - structure
        - warnings
      properties:
        file:
          $ref: '#/components/schemas/DocumentMetadataFile'
        properties:
          $ref: '#/components/schemas/DocumentMetadataProperties'
        custom:
          type: object
          description: Custom properties declared by the source document.
          additionalProperties: true
        structure:
          $ref: '#/components/schemas/DocumentMetadataStructure'
        format_specific:
          type: object
          description: Native values that do not map into normalized fields.
          additionalProperties: true
        warnings:
          type: array
          items:
            type: string
          description: Non-fatal metadata parsing warnings.
    BoundingBoxes:
      type: object
      description: >-
        Positional bounding-box data for text, titles, headers, footers, images,
        and tables. Used by the frontend for annotation overlays and by SDK
        consumers to access detected visuals (charts and images) returned under
        `Images`. Keys not listed here are accepted for forward compatibility
        (e.g. `markdown_with_ids`, `defined_names`).
      properties:
        Images:
          type: array
          items:
            $ref: '#/components/schemas/BoundingBoxImage'
          description: >-
            Detected or embedded visuals. `image_url` is populated when
            `figure_processing.show_images` was enabled and the entry's
            `visual_type` matched the requested target.
        Tables:
          type: array
          items:
            $ref: '#/components/schemas/BoundingBoxTable'
          description: >-
            Detected tables. Each entry carries a `table_info` block plus
            optional `cell_data`.
        Text:
          type: array
          items:
            $ref: '#/components/schemas/BoundingBoxItem'
          description: >-
            Body-text paragraphs and detected text regions. For spreadsheets,
            includes free-form text outside table regions (titles, captions,
            instructions).
        Title:
          type: array
          items:
            $ref: '#/components/schemas/BoundingBoxItem'
          description: >-
            Detected title regions. Spreadsheets emit one `Sheet: <name>` title
            per processed sheet.
        Footer:
          type: array
          items:
            $ref: '#/components/schemas/BoundingBoxItem'
          description: >-
            Detected footer regions (e.g. spreadsheet "Totals" rows, PDF page
            footers).
        markdown_with_ids:
          type: string
          description: >-
            Markdown variant with stable `data-bb-*-id` attributes in figure /
            table / text tags. Lets clients join rendered HTML back to
            bounding-box entries by id.
      additionalProperties: true
    DocumentMetadataFile:
      type: object
      description: Transport-level facts derived from the uploaded source file.
      required:
        - name
        - extension
        - media_type
        - size_bytes
      properties:
        name:
          type: string
        extension:
          type: string
        media_type:
          type: string
        size_bytes:
          type: integer
          format: int64
          minimum: 0
        sha256:
          type: string
          description: SHA-256 content digest, when hashing is available.
    DocumentMetadataProperties:
      type: object
      description: Normalized native document properties. Absent properties are omitted.
      properties:
        title:
          type: string
        authors:
          type: array
          items:
            type: string
        subject:
          type: string
        description:
          type: string
        keywords:
          type: array
          items:
            type: string
        language:
          type: string
        application:
          type: string
        application_version:
          type: string
        producer:
          type: string
        last_modified_by:
          type: string
        revision:
          type: string
        category:
          type: string
        content_status:
          type: string
        identifier:
          type: string
        version:
          type: string
        company:
          type: string
        manager:
          type: string
        template:
          type: string
        presentation_format:
          type: string
        editing_time_minutes:
          type: integer
          minimum: 0
        copyright:
          type: string
        created_at:
          type: string
          description: ISO 8601 timestamp when the source provides one.
        modified_at:
          type: string
          description: ISO 8601 timestamp when the source provides one.
      additionalProperties: true
    DocumentMetadataStructure:
      type: object
      description: Deterministic structure derived from the source document format.
      properties:
        page_count:
          type: integer
          minimum: 0
        page_labels:
          type: array
          items:
            type: string
        page_sizes:
          type: array
          items:
            type: object
            additionalProperties: true
        outline_count:
          type: integer
          minimum: 0
        attachment_count:
          type: integer
          minimum: 0
        annotation_count:
          type: integer
          minimum: 0
        annotation_types:
          type: object
          additionalProperties:
            type: integer
        form_field_count:
          type: integer
          minimum: 0
        sheet_count:
          type: integer
          minimum: 0
        sheet_names:
          type: array
          items:
            type: string
        sheet_visibility:
          type: object
          additionalProperties:
            type: string
        active_sheet:
          type: string
        slide_count:
          type: integer
          minimum: 0
        note_count:
          type: integer
          minimum: 0
        hidden_slide_count:
          type: integer
          minimum: 0
        multimedia_clip_count:
          type: integer
          minimum: 0
        word_count:
          type: integer
          minimum: 0
        character_count:
          type: integer
          minimum: 0
        character_count_with_spaces:
          type: integer
          minimum: 0
        line_count:
          type: integer
          minimum: 0
        paragraph_count:
          type: integer
          minimum: 0
        paragraph_count_derived:
          type: integer
          minimum: 0
        table_count:
          type: integer
          minimum: 0
        section_count:
          type: integer
          minimum: 0
        embedded_image_count:
          type: integer
          minimum: 0
        width_px:
          type: integer
          minimum: 0
        height_px:
          type: integer
          minimum: 0
        frame_count:
          type: integer
          minimum: 0
        row_count:
          type: integer
          minimum: 0
        max_column_count:
          type: integer
          minimum: 0
      additionalProperties: true
    BoundingBoxImage:
      type: object
      description: >-
        Detected or embedded visual (chart or image) returned under
        `bounding_boxes.Images`. For PDFs/images, populated when figure
        detection is enabled. For spreadsheets, populated for embedded charts
        and images. `image_url` is set when `figure_processing.show_images` is
        enabled.
      required:
        - id
        - visual_type
      properties:
        id:
          type: string
          description: >-
            Stable visual identifier (e.g. `excel_image_1_1`, `fig-3`). Use this
            to join with the `data-bb-image-id` attribute in the markdown
            output.
        content:
          type: string
          description: >-
            Short caption for the visual (e.g. `Chart: Revenue`). Populated by
            the spreadsheet parser; PDF figures may leave this empty when no
            caption is detected.
        visual_type:
          allOf:
            - $ref: '#/components/schemas/VisualType'
          description: >-
            Visual class. Drives whether `figure_processing.description` /
            `figure_processing.show_images` apply to this entry.
        page_number:
          type: integer
          minimum: 1
          description: 1-indexed page or sheet index.
        bounding_box:
          type: array
          items:
            type: number
          description: >-
            Document coordinate polygon when available. Spreadsheet visuals
            typically use an empty array and rely on `excel_range` for
            positioning.
        image_url:
          type: string
          description: >-
            Pulse-hosted URL for the visual image bytes. Present when
            `figure_processing.show_images` was enabled for this visual_type.
            Spreadsheet visuals proxy through `GET
            /results/{jobId}/images/{filename}`; inline figure flows may use a
            data URI.
        description:
          type: string
          description: >-
            Generated visual description. Present when
            `figure_processing.description` was enabled for this visual_type.
        classification:
          type: object
          description: >-
            Visual classification metadata when classification was run. Includes
            confidence, model name, and any non-fatal classification error.
          additionalProperties: true
          properties:
            confidence:
              type: number
              minimum: 0
              maximum: 1
            model:
              type: string
            error:
              type: string
        sheet_name:
          type: string
          description: Spreadsheet-only sheet name.
        sheet_index:
          type: integer
          description: Spreadsheet-only parsed sheet index after hidden-sheet filtering.
        workbook_sheet_index:
          type: integer
          description: Spreadsheet-only original workbook sheet index.
        excel_range:
          type: string
          description: Spreadsheet-only anchor or covered cell range for the visual.
        chart_type:
          type: string
          description: >-
            Spreadsheet chart class name (e.g. `BarChart`, `LineChart`) when
            `visual_type` is `chart`.
        chart_title:
          type: string
          description: Spreadsheet chart title when available.
        source_ranges:
          type: array
          items:
            type: string
          description: >-
            Spreadsheet chart source ranges when available, e.g.
            `["Charts!$B$1:$B$3"]`.
        render_error:
          type: string
          description: >-
            Optional non-fatal rendering error for spreadsheet visuals. When
            set, the visual entry is still returned but `image_url` may be
            omitted.
        description_error:
          type: string
          description: Optional non-fatal description-generation error.
      additionalProperties: true
    BoundingBoxTable:
      type: object
      description: >-
        Detected table region returned under `bounding_boxes.Tables`. Carries a
        structured `table_info` block plus optional `cell_data`. Kept loose with
        `additionalProperties: true` to round-trip future fields the server may
        add (e.g. layout metadata).
      properties:
        table_info:
          type: object
          additionalProperties: true
          properties:
            id:
              type: string
            dimensions:
              type: array
              items:
                type: integer
            excel_range:
              type: string
            sheet_name:
              type: string
            sheet_index:
              type: integer
            workbook_sheet_index:
              type: integer
            section_index:
              type: integer
            section_type:
              type: string
            section_name:
              type: string
            table_name:
              type: string
            layout_type:
              type: string
            is_chart:
              type: boolean
            chart_type:
              type: string
            chart_title:
              type: string
            source_ranges:
              type: array
              items:
                type: string
            location:
              type: object
              additionalProperties: true
        cell_data:
          type: array
          description: >-
            Table cell payload when available. Shape varies by extraction path;
            SDK consumers should treat as opaque.
          items:
            type: object
            additionalProperties: true
      additionalProperties: true
    BoundingBoxItem:
      type: object
      description: >-
        Common base shape used for `Text`, `Title`, and `Footer` bounding-box
        entries. Spreadsheet rows may carry additional sheet-scoped fields such
        as `excel_range` and `sheet_name`; forward-compatible extra properties
        are accepted.
      properties:
        id:
          type: string
          description: >-
            Stable bounding-box identifier (e.g. `txt-1`, `excel_title_0`). Used
            by extensions like `footnoteReferences` to cross-reference
            paragraphs.
        content:
          type: string
          description: Plain-text content of the region.
        page_number:
          type: integer
          minimum: 1
          description: >-
            1-indexed page number. For spreadsheets this matches the parsed
            sheet index after hidden-sheet filtering.
        bounding_box:
          type: array
          items:
            type: number
          description: >-
            Document coordinate polygon when available. Spreadsheet visuals may
            use an empty array and `excel_range` instead.
        excel_range:
          type: string
          description: Spreadsheet-only anchor or covered cell range.
        sheet_name:
          type: string
          description: Spreadsheet-only sheet name.
        sheet_index:
          type: integer
          description: Spreadsheet-only parsed sheet index after hidden-sheet filtering.
        workbook_sheet_index:
          type: integer
          description: Spreadsheet-only original workbook sheet index.
        selected:
          type: boolean
          description: >-
            Selection state for a form control or marked-choice region when
            `detectSelections` was enabled and the detector could determine it.
      additionalProperties: true
    VisualType:
      type: string
      enum:
        - chart
        - image
      description: >-
        Visual class of a bounding-box image. `chart` covers data visualizations
        (bar/line/pie etc., including spreadsheet chart objects). `image` covers
        non-chart embedded or detected visuals (logos, photos, screenshots).
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key
      x-fern-header:
        name: apiKey
        env: PULSE_API_KEY

````