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.
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 |
Example
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"}}'
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
{
"id": 847,
"filename": "invoice.pdf",
"status": "New",
"contact_id": 5,
"folder_id": 12,
"created_at": "2025-11-15T08:23:41Z"
}
List 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
# 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
{
"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
Returns the full document record including all extracted fields, line items, confidence score, and CRM references.
Example
curl "https://YOUR-INSTANCE/api/documents/847" \
-H "Authorization: Bearer YOUR_TOKEN"
Response
{
"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
Valid status values: New, Processing, Needs Review, Missing Info, Ready, Approved, Export, Exception, Archived
Example
curl -X PATCH "https://YOUR-INSTANCE/api/documents/847/status" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "Approved"}'
Response
{
"id": 847,
"status": "Approved",
"updated_at": "2025-11-15T09:05:00Z"
}
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.
Common Patterns
Poll for completed documents
Check for documents that have finished processing and are ready for review:
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
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']}")
The Rules Engine can do this automatically without any code — set a rule: confidence_score >= 90 → Set Status = Approved. See Rules Engine.
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 |