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

# Files & sources

> How to get documents into NDI, and which formats each method supports

Every job starts with a `file` object in the request body:

```json theme={"dark"}
{
  "file": {
    "source_url": "...",
    "file_name": "annual-report.pdf"
  }
}
```

`source_url` accepts three schemes.

## `ndi://file/<uuid>` — upload handles (recommended)

Upload the document once with [`POST /upload`](/api-reference/upload), then pass the returned handle everywhere:

```json theme={"dark"}
{ "file": { "source_url": "ndi://file/7f4d2a10-3b7e-4c25-9f61-8f0f4f0a1b2c" } }
```

* **Upload once, use many times** — the same handle works across parse, ground, and categorize.
* `file_name` is optional; it defaults to the name captured at upload.
* Handles **expire after \~6 days** (the exact `expires_at` is returned by the upload). Using an expired handle returns `410 Gone`; a handle from another tenant returns `404`.

## `https://` — public or presigned URLs

If the document is already reachable over HTTPS (a public URL or a presigned URL from your own storage), point NDI at it directly:

```json theme={"dark"}
{
  "file": {
    "source_url": "https://your-bucket.s3.amazonaws.com/report.pdf?X-Amz-...",
    "file_name": "report.pdf"
  }
}
```

Constraints, all enforced server-side:

* **HTTPS only.** Plain `http://` is rejected — document links carry your data and must be encrypted in transit.
* **Publicly reachable hosts only.** IP-literal hosts, `localhost`, and private-network addresses are rejected (`422`).
* **No redirects.** The URL must serve the bytes directly.
* **Maximum download: 1 GiB.**
* `file_name` is **required** — NDI uses its extension to detect the format.

## `s3://` — direct S3 URLs

Available to tenants with a bring-your-own-bucket storage arrangement, and for referencing artifacts NDI previously produced for you (e.g. passing a prior parse's `markdown_url` back into ground or categorize). `file_name` is required. If your account uses NDI-managed storage, arbitrary `s3://` inputs are rejected — use uploads or `https://` URLs instead.

## Supported formats

The format is inferred from the file extension of `file_name` (or the uploaded file's name). An unsupported extension fails fast with a `422` before any job is started.

| Method         | Supported extensions                                                                                                                                                                     |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **parse**      | `.csv` `.doc` `.docm` `.docx` `.eml` `.htm` `.html` `.jpeg` `.jpg` `.log` `.msg` `.pdf` `.png` `.ppt` `.pptx` `.tif` `.tiff` `.txt` `.vsd` `.vsdx` `.webp` `.xls` `.xlsm` `.xlsx` `.xml` |
| **categorize** | same as parse                                                                                                                                                                            |
| **ground**     | same as parse, **minus** `.eml` `.msg` `.vsd` `.vsdx`, **plus** `.bmp` `.jsonl` `.md` `.mdx`                                                                                             |

## Upload limits and lifetime

| Limit                  | Value                                              |
| ---------------------- | -------------------------------------------------- |
| Maximum upload size    | 200 MB (`413` when exceeded)                       |
| Upload handle lifetime | \~6 days (see `expires_at` in the upload response) |

## Result artifacts

Job results reference produced artifacts (markdown files, cropped match images) by URL. For standard accounts these are **time-limited download URLs valid for 1 hour**. Fetch them promptly, or call [`GET /jobs/{job_id}`](/api-reference/get-job) again at any time to receive freshly signed URLs — the underlying artifacts persist.
