Skip to main content
Version: 2.0

File Upload API

The File Upload API is the entry point for supplying supporting files (PowerPoint, PDF, images, etc.) to downstream jobs such as AutoGenerator and Template Converter.

Two endpoints cover the upload patterns:

  • POST /api/v1/preprocess — chunked upload.
  • POST /api/v1/validate — validate previously uploaded files and/or web links.

Full schemas and try-it-out forms live in the interactive API Reference.

Authentication​

All endpoints require a Bearer token:

Authorization: Bearer YOUR_API_KEY

See Getting Started → Authentication.

Response envelope​

Every endpoint returns the canonical envelope: { "success": true, "data": { ... } } on success or the standard error envelope on error.

Endpoint summary​

MethodPathDescriptionSync/Async
POST/api/v1/preprocessPreprocess a file in chunksSync
POST/api/v1/validateValidate uploaded files and/or web linksSync

All endpoints are in the auto_generator rate-limit category. See Developer Guide → Usage quotas and rate limits.


POST /api/v1/preprocess — Chunked upload​

Accepts one chunk of a multi-chunk file upload. The caller drives chunking via chunkIndex and totalChunks; chunks for the same upload share a requestIdentifier. Once all chunks for a requestIdentifier arrive, the file is assembled and made available to downstream operations.

A parallel chunked-upload endpoint exists for Template Converter specifically (POST /api/v1/template-converter/preprocess) and uses the same request shape; only .pptx files are accepted there.

Request body​

FieldTypeRequiredDescription
fileContentstringyesChunk content as base64 / data: URL.
fileNamestringyesOriginal filename including extension.
chunkIndexinteger ≥ 0yesZero-based index of this chunk.
totalChunksinteger ≥ 1yesTotal number of chunks for this upload.
requestIdentifierstringyesCaller-supplied identifier that groups chunks of the same upload.

Example (one chunk)​

curl -X POST https://api.prezent.ai/api/v1/preprocess \
-H "Authorization: Bearer $PREZENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileName": "big-deck.pptx",
"fileContent": "UEsDBBQAAAAIAA...",
"chunkIndex": 0,
"totalChunks": 4,
"requestIdentifier": "upload-2026-05-18-001"
}'

Success response (200)​

{
"success": true,
"data": {
"request_identifier": "upload-2026-05-18-001",
"file_name": "big-deck.pptx",
"message": "Chunk received."
}
}

POST /api/v1/validate — Validate files / links​

Validates a set of previously uploaded files (referenced by fileIdentifiers) and/or a list of web links. At least one of fileIdentifiers or webLinks must be non-empty.

Call this after every chunk of a file has been sent to POST /api/v1/preprocess. The file_id it returns is the id to pass in the files array of AutoGenerator and Posters requests.

Request body​

FieldTypeRequiredDescription
fileIdentifiersobjectconditionalMap of requestIdentifier → fileName, one entry per file. Use the same requestIdentifier you sent with that file's /preprocess chunks.
webLinksarray of URIconditionalList of URLs to validate.

Example​

curl -X POST https://api.prezent.ai/api/v1/validate \
-H "Authorization: Bearer $PREZENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileIdentifiers": { "3f9c2b1e-7a4d-4e8b-9c1f-2d6a5b8e0f71": "context.pdf" },
"webLinks": ["https://example.com/whitepaper"]
}'

Success response (200)​

{
"success": true,
"data": {
"files": [
{
"file_id": "cbef85d9-d8ef-43c4-aa89-317f7d255bab",
"unique_id": "cbef85d9-d8ef-43c4-aa89-317f7d255bab",
"status": "success",
"file_type": "application/pdf",
"file_size": 1.77,
"number_of_pages": 3,
"is_corrupted": false,
"is_password_protected": false,
"log": "success"
}
],
"web_links": [
{ "url": "https://example.com/whitepaper", "valid": true }
],
"message": "Validation complete."
}
}
FieldDescription
file_idId of the validated file. Pass this in the files array of generation requests.
unique_idSame value as file_id.
status"success" when the file can be used. Any other value means it failed validation.
file_typeMIME type of the file.
file_sizeFile size in MB.
number_of_pagesPage or slide count.
is_corruptedtrue if the file could not be read.
is_password_protectedtrue if the file is password protected. Remove the password and upload again.
logProcessing message.

A failed file is not reported with an HTTP error. Its entry has a status other than "success", and is_corrupted or is_password_protected shows the cause.


End-to-end example: upload, then validate​

A complete upload is three steps:

  1. Encode the whole file as a data: URL (data:<mime-type>;base64,<content>).
  2. Split that string into chunks and send each one to POST /api/v1/preprocess. Every chunk carries the same requestIdentifier — a UUID you generate — plus its chunkIndex and the totalChunks count.
  3. Validate with POST /api/v1/validate, passing { "<requestIdentifier>": "<fileName>" } as fileIdentifiers. The file_id in the response is the id to pass in the files array of Presentations and Posters requests.

Chunk the encoded string, not the raw file bytes — each chunk is a slice of the same data: URL, and the server joins them back together in chunkIndex order.

The script below does all three, with retries on each chunk. It needs Python 3.8+ and requests (pip install requests).

upload_file.py
#!/usr/bin/env python3
"""Upload a file to Prezent and print the file_id to use in generation requests.

Usage:
export PREZENT_API_KEY=your-api-key
python3 upload_file.py path/to/document.pdf
"""
import base64
import mimetypes
import os
import sys
import time
import uuid
from pathlib import Path

import requests

BASE_URL = "https://api.prezent.ai"
CHUNK_SIZE = 5 * 1024 * 1024 # characters of the encoded data URL per chunk
MAX_RETRIES = 3

HEADERS = {
"Authorization": f"Bearer {os.environ['PREZENT_API_KEY']}",
"Content-Type": "application/json",
}


def encode_as_data_url(path: Path) -> str:
"""Step 1: base64-encode the whole file as a data: URL."""
mime_type = mimetypes.guess_type(path.name)[0] or "application/octet-stream"
content = base64.b64encode(path.read_bytes()).decode("utf-8")
return f"data:{mime_type};base64,{content}"


def upload_chunks(data_url: str, file_name: str) -> str:
"""Step 2: send the data URL to /preprocess in chunks. Returns the requestIdentifier."""
request_id = str(uuid.uuid4())
chunks = [data_url[i : i + CHUNK_SIZE] for i in range(0, len(data_url), CHUNK_SIZE)]

for index, chunk in enumerate(chunks):
payload = {
"fileContent": chunk,
"fileName": file_name,
"chunkIndex": index,
"totalChunks": len(chunks),
"requestIdentifier": request_id,
}
for attempt in range(1, MAX_RETRIES + 1):
try:
response = requests.post(
f"{BASE_URL}/api/v1/preprocess", headers=HEADERS, json=payload, timeout=60
)
if response.ok:
break
error = f"HTTP {response.status_code}: {response.text}"
except requests.RequestException as exc:
error = str(exc)
if attempt == MAX_RETRIES:
sys.exit(f"Chunk {index} failed after {MAX_RETRIES} attempts — {error}")
time.sleep(attempt) # back off before retrying
print(f"Uploaded chunk {index + 1}/{len(chunks)}")

return request_id


def validate(request_id: str, file_name: str) -> dict:
"""Step 3: validate the assembled file. Returns its validation result."""
response = requests.post(
f"{BASE_URL}/api/v1/validate",
headers=HEADERS,
json={"fileIdentifiers": {request_id: file_name}},
timeout=60,
)
response.raise_for_status()
return response.json()["data"]["files"][0]


def main() -> None:
if len(sys.argv) != 2:
sys.exit(__doc__)
path = Path(sys.argv[1])

data_url = encode_as_data_url(path)
request_id = upload_chunks(data_url, path.name)
result = validate(request_id, path.name)

if result.get("status") != "success":
reasons = [
label
for label, flag in (
("password protected", result.get("is_password_protected")),
("corrupted", result.get("is_corrupted")),
)
if flag
]
sys.exit(f"Validation failed: {', '.join(reasons) or result}")

print(f"Pages: {result.get('number_of_pages')}")
print(f"file_id: {result['file_id']}")


if __name__ == "__main__":
main()

Run it:

export PREZENT_API_KEY=your-api-key
python3 upload_file.py quarterly-review.pdf
Uploaded chunk 1/2
Uploaded chunk 2/2
Pages: 12
file_id: cbef85d9-d8ef-43c4-aa89-317f7d255bab

Then pass the file_id into a generation request:

{
"prompt": "Summarize the quarterly review for the leadership team",
"files": [{ "file_id": "cbef85d9-d8ef-43c4-aa89-317f7d255bab" }]
}

To upload several files, run steps 1 and 2 for each one, then validate them together in one call — fileIdentifiers accepts one requestIdentifier → fileName entry per file.


Errors​

Common error codes:

  • 400 — MISSING_FILE_CONTENT, MISSING_REQUIRED_FIELD, INVALID_PAYLOAD, FILE_UPLOAD_FAILED.
  • 401 — INVALID_API_KEY, EXPIRED_API_KEY, UNAUTHORIZED.
  • 404 — ENDPOINT_NOT_FOUND, RESOURCE_NOT_FOUND.
  • 415 — UNSUPPORTED_FILE_TYPE.
  • 422 — INVALID_INPUT, UNPROCESSABLE_ENTITY.
  • 429 — RATE_LIMIT_EXCEEDED, TOO_MANY_REQUESTS.
  • 500 / 503 / 504 — standard server-side codes.

See the full catalog in Developer Guide → Error codes.