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

# Uploading Documents

> Supported file types, upload methods, and multi-file processing.

## Supported file types

FlexOrch accepts the following formats:

| Category      | Extensions                                                 |
| ------------- | ---------------------------------------------------------- |
| Documents     | `.pdf`, `.docx`, `.txt`                                    |
| Spreadsheets  | `.xlsx`                                                    |
| Presentations | `.pptx`                                                    |
| Web / markup  | `.html`, `.htm`                                            |
| Email         | `.eml`, `.msg`                                             |
| E-invoices    | `.xml` (UBL/Peppol, GİB TR, FatturaPA, XRechnung, ZUGFeRD) |
| Images        | `.jpg`, `.jpeg`, `.png`, `.tiff`                           |

Image files and scanned PDFs are processed with OCR automatically. Scanned pages are also automatically deskewed (rotation and small-angle tilt correction) before OCR runs.

<Note>
  CSV files are not supported for upload — use XLSX for tabular data.
</Note>

FlexOrch also checks the actual file content, not just the extension — if a
file's content doesn't match its extension (e.g. a PDF renamed to `.docx`),
it's automatically routed to the correct parser when the real type is
supported, or rejected with `EXTENSION_MISMATCH` when it isn't. See
[Common error codes](/api-reference/introduction#common-error-codes).

***

## Single file upload

```bash theme={null}
curl -X POST https://api.flexorch.com/v1/data-process/async \
  -H "X-API-KEY: dfx_your_key_here" \
  -F "files=@contract.pdf"
```

Response:

```json theme={null}
{
  "data": {
    "job_ids": ["job_abc123"],
    "status": "queued"
  }
}
```

***

## Multi-file upload

Send multiple files in a single request:

```bash theme={null}
curl -X POST https://api.flexorch.com/v1/data-process/async \
  -H "X-API-KEY: dfx_your_key_here" \
  -F "files=@invoice_jan.pdf" \
  -F "files=@invoice_feb.pdf" \
  -F "files=@payroll_q1.xlsx"
```

Each file gets its own `job_id`. The response includes all IDs:

```json theme={null}
{
  "data": {
    "job_ids": ["job_001", "job_002", "job_003"],
    "status": "queued"
  }
}
```

***

## Upload from a connector (S3 / GCS / Azure)

If you have a connector configured, you can process files directly from cloud storage without downloading them first:

```bash theme={null}
curl -X POST https://api.flexorch.com/v1/data-process/async \
  -H "X-API-KEY: dfx_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "connector_id": 1,
      "keys": ["documents/invoice_2024.pdf", "documents/payroll_q1.xlsx"]
    }
  }'
```

See [Connectors](/connectors/overview) for setup instructions.

***

## File size limits

The maximum file size is **5 MB per file**, the same across all plans. Files exceeding the limit return `400 FILE_TOO_LARGE`.

Encrypted PDFs are rejected with `ENCRYPTED_PDF` — remove the password before uploading. Very long documents are also capped independently of file size, since a small file can still be complex enough to slow down processing: PDFs over 300 pages return `PDF_TOO_MANY_PAGES`, and XLSX sheets over 50,000 rows return `XLSX_TOO_MANY_ROWS`. Split the file and upload the parts separately if you hit either limit.

***

## Duplicate detection

FlexOrch automatically detects duplicate documents (using a content hash). If you upload a file that was already processed:

* No new credit is consumed
* The existing job and execution IDs are returned
* Processing is skipped

```json theme={null}
{
  "data": {
    "is_duplicate": true,
    "existing_document_id": "doc_xyz",
    "existing_job_id": "job_abc"
  }
}
```

***

## Polling for results

After upload, poll the job endpoint until `status` is `completed` or `failed`:

```bash theme={null}
curl https://api.flexorch.com/v1/jobs/{job_id} \
  -H "X-API-KEY: dfx_your_key_here"
```

The SDK handles polling automatically with `job.wait_until_done()`.

<Tip>
  Typical processing time is 5–30 seconds depending on file size and type. Image-heavy PDFs take longer due to OCR.
</Tip>
