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

# Documents API

> Upload documents, retrieve extracted data, update statuses, and manage documents programmatically.

The Documents API is the core of RecordEngine's integration layer. Use it to upload documents from external systems, retrieve structured extraction results, and update document statuses — all without touching the UI.

All requests require a Bearer token in the `Authorization` header. See [Authentication](/api-reference/authentication).

***

## Upload a Document

```
POST /api/documents/upload
```

Uploads a file to RecordEngine and queues it for AI processing. The document appears in the UI immediately with **New** status, then transitions to **Processing** and **Needs Review** automatically.

### Request

Send as `multipart/form-data`:

| Field           | Type          | Required | Description                                                                        |
| --------------- | ------------- | -------- | ---------------------------------------------------------------------------------- |
| `file`          | file          | ✅        | The document file to upload                                                        |
| `contact_id`    | integer       | ✅        | ID of the contact to assign the document to                                        |
| `folder_id`     | integer       | ✅        | ID of the folder to place the document in                                          |
| `profile_id`    | integer       |          | ID of the extraction profile to use (uses contact default if omitted)              |
| `external_refs` | string (JSON) |          | CRM correlation references — see [CRM Correlation](/api-reference/crm-correlation) |

### Example

```bash theme={null}
curl -X POST https://YOUR-INSTANCE/api/documents/upload \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@invoice.pdf" \
  -F "contact_id=5" \
  -F "folder_id=12" \
  -F "profile_id=2" \
  -F 'external_refs={"salesforce":{"record_id":"001Qy00000BnXt2IAF","record_type":"Opportunity","record_url":"https://yourorg.salesforce.com/001Qy00000BnXt2IAF"}}'
```

```python theme={null}
import requests

with open("invoice.pdf", "rb") as f:
    response = requests.post(
        "https://YOUR-INSTANCE/api/documents/upload",
        headers={"Authorization": "Bearer YOUR_TOKEN"},
        files={"file": f},
        data={
            "contact_id": 5,
            "folder_id": 12,
            "profile_id": 2,
            "external_refs": '{"salesforce":{"record_id":"001Qy...","record_type":"Opportunity"}}'
        }
    )

print(response.json())
```

### Response

```json theme={null}
{
  "id": 847,
  "filename": "invoice.pdf",
  "status": "New",
  "contact_id": 5,
  "folder_id": 12,
  "created_at": "2025-11-15T08:23:41Z"
}
```

***

## List Documents

```
GET /api/documents
```

Returns a paginated list of documents. Supports filtering by status, contact, folder, and date range.

### Query Parameters

| Parameter    | Type    | Description                                        |
| ------------ | ------- | -------------------------------------------------- |
| `contact_id` | integer | Filter by contact                                  |
| `folder_id`  | integer | Filter by folder                                   |
| `status`     | string  | Filter by status (e.g. `Needs Review`, `Approved`) |
| `limit`      | integer | Number of results per page (default: 50, max: 200) |
| `offset`     | integer | Pagination offset                                  |

### Example

```bash theme={null}
# Get all documents awaiting review for contact 5
curl "https://YOUR-INSTANCE/api/documents?contact_id=5&status=Needs%20Review" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

### Response

```json theme={null}
{
  "total": 142,
  "limit": 50,
  "offset": 0,
  "documents": [
    {
      "id": 847,
      "filename": "acme-invoice-nov-2025.pdf",
      "status": "Needs Review",
      "confidence_score": 87,
      "confidence_label": "Good",
      "contact_id": 5,
      "folder_id": 12,
      "created_at": "2025-11-15T08:23:41Z"
    }
  ]
}
```

***

## Get a Single Document

```
GET /api/documents/{id}
```

Returns the full document record including all extracted fields, line items, confidence score, and CRM references.

### Example

```bash theme={null}
curl "https://YOUR-INSTANCE/api/documents/847" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

### Response

```json theme={null}
{
  "id": 847,
  "filename": "acme-invoice-nov-2025.pdf",
  "status": "Needs Review",
  "doc_type": "Invoice",
  "doc_date": "2025-11-15",
  "contact_id": 5,
  "contact_name": "Acme Corporation",
  "folder_id": 12,
  "folder_name": "Q4 Invoices",
  "ai_summary": "Invoice from Acme Corporation for consulting services...",
  "confidence_score": 87,
  "confidence_label": "Good",
  "confidence_reasoning": "All 8 fields extracted successfully.",
  "extracted_fields": {
    "vendor": "Acme Corporation",
    "invoice_number": "INV-2025-1147",
    "invoice_date": "2025-11-15",
    "due_date": "2025-12-15",
    "currency": "CNY",
    "total_amount": "18500.00"
  },
  "line_items": [
    {
      "description": "Consulting services — October 2025",
      "quantity": 10,
      "unit_price": 1500.00,
      "amount": 15000.00
    }
  ],
  "external_refs": {
    "salesforce": {
      "record_id": "001Qy00000BnXt2IAF",
      "record_type": "Opportunity",
      "record_url": "https://yourorg.salesforce.com/001Qy00000BnXt2IAF"
    }
  },
  "notes": "Reviewed by J. Douchet — approved for Q4 batch",
  "created_at": "2025-11-15T08:23:41Z",
  "updated_at": "2025-11-15T09:01:12Z"
}
```

***

## Update Document Status

```
PATCH /api/documents/{id}/status
```

Changes the status of a document. Use this to move documents through the workflow programmatically — for example, automatically approving high-confidence documents from an external script.

### Request Body

```json theme={null}
{
  "status": "Approved"
}
```

Valid status values: `New`, `Processing`, `Needs Review`, `Missing Info`, `Ready`, `Approved`, `Export`, `Exception`, `Archived`

### Example

```bash theme={null}
curl -X PATCH "https://YOUR-INSTANCE/api/documents/847/status" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "Approved"}'
```

### Response

```json theme={null}
{
  "id": 847,
  "status": "Approved",
  "updated_at": "2025-11-15T09:05:00Z"
}
```

<Warning>
  Setting a document to **Export** status via the API triggers the outbound Document Webhook — the same as clicking Webhook Export in the UI. Make sure your webhook receiver is ready before doing this at scale.
</Warning>

***

## Common Patterns

### Poll for completed documents

Check for documents that have finished processing and are ready for review:

```python theme={null}
import requests

def get_documents_ready_for_review(token, contact_id):
    response = requests.get(
        "https://YOUR-INSTANCE/api/documents",
        headers={"Authorization": f"Bearer {token}"},
        params={
            "contact_id": contact_id,
            "status": "Needs Review"
        }
    )
    return response.json()["documents"]
```

### Auto-approve high confidence documents

```python theme={null}
def auto_approve_high_confidence(token, contact_id, threshold=90):
    docs = get_documents_ready_for_review(token, contact_id)
    
    for doc in docs:
        if doc["confidence_score"] >= threshold:
            requests.patch(
                f"https://YOUR-INSTANCE/api/documents/{doc['id']}/status",
                headers={"Authorization": f"Bearer {token}"},
                json={"status": "Approved"}
            )
            print(f"Auto-approved document {doc['id']} — score {doc['confidence_score']}")
```

<Tip>
  The Rules Engine can do this automatically without any code — set a rule: `confidence_score >= 90 → Set Status = Approved`. See [Rules Engine](/user-guide/rules-engine).
</Tip>

***

## Error Reference

| Status Code | Cause                                                                         |
| ----------- | ----------------------------------------------------------------------------- |
| `400`       | Invalid status value in PATCH request                                         |
| `401`       | Missing or invalid Bearer token                                               |
| `404`       | Document ID does not exist                                                    |
| `422`       | Upload request missing required fields (`contact_id`, `folder_id`, or `file`) |
| `500`       | Server error — check that all containers are running                          |
