Documents

Data Upload

POST
/documents/data/upload

Uploads a structured JSON data file to Storage so it can be referenced as a data source in a document-generation request — either the synchronous POST /v1/documents/document/generate (operationId: documents-document-generate) or the asynchronous POST /v1/documents/document/generate/async (operationId: documents-document-generate-async) — via "data": {"loadMethod": "Storage", "urn": "<storage id>"} (the id returned by this endpoint). This is the only place a Storage upload can be consumed.

Two request shapes are accepted, selected by Content-Type: (1) multipart/form-data with one or more .json files; (2) a raw JSON body with Content-Type: application/json, stored as-is as an opaque blob.

A generate request only ever accepts a single "data" source (one urn), so each uploaded file gets its own independent storage id and is consumed on its own, separate generate call. Uploading multiple .json files in one multipart request is a convenience for preparing several unrelated data sources at once (e.g. ahead of generating several separate documents) — it does not combine those files into one data payload for a single generate request, and there's no way to merge them after upload. The application/json variant accepts only one JSON payload per request; it has no multi-file equivalent.

Uploaded data must follow a fixed shape: a root data object whose direct members are named lists of records (e.g. "data": {"customer": [...], "payments": [...], "attachments": [...]}), with every value inside those records as a string, formatted in the locale the generate request will use (e.g. "EffectiveDate": "Jun 30, 2025", "UnitPrice": "4,800"). Any nested collection inside a record (e.g. LineItems) must also be a list.

Uploaded data is used as-is at generation time — there's no way to filter, transform, or select from it after upload. If you need to select or shape data at generation time instead of uploading it here, skip this endpoint and see the documents-document-generate / documents-document-generate-async requests requests' data object for other options.

Uploaded data is held in Storage for 24 hours, and is removed sooner than that by the next document-generation request that consumes it (sync or async) — consumption removes it whether that request succeeds or fails. Once it is gone by either route its storage id stops resolving, so upload the data again if you need it. Max size is enforced at the gateway (20MB Production, 10MB Staging). A file over that limit is rejected by the web server before the operation runs, so it surfaces as a 500 rather than a validation error.

Authorization

AuthorizationBearer <token>

JWT token to authenticate the request.

In: header

X-Api-Key<token>

API key, sent as a request header.

In: header

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

body?unknown

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/documents/data/upload" \  -H "Content-Type: application/json" \  -d '{    "data": {      "customer": [        {          "Name": "Acme Logistics Group",          "AccountId": "0001008213"        }      ],      "payments": [        {          "Amount": "123.45"        }      ]    }  }'

{  "result": {    "data": {      "files": [        {          "id": "3f9a7c14-2b8e-4d6a-9f01-5c7e2a1b3d4e",          "fileName": "customer-data.json"        },        {          "id": "b9f629a1-88e6-484b-97ff-d0a431ba660d",          "fileName": "payments-data.json"        }      ]    },    "statusCode": 201,    "message": "Created"  },  "origin": "POST https://api.doctavian.com/v1/documents/data/upload",  "dateTime": "2026-09-08T12:47:56.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "1a2b3c4d-5e6f-4a1b-8c2d-3e4f5a6b7c8d"}

{  "error": {    "statusCode": 400,    "message": "The file 'payload.xml' has an unsupported extension. Allowed: .json",    "innerErrors": [      {        "code": "INVALID_DATA_FORMAT",        "message": "The file 'payload.xml' has an unsupported extension. Allowed: .json",        "userMessage": "Only .json files can be uploaded here. Convert your data to .json and try again."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/documents/data/upload",  "dateTime": "2026-09-08T12:47:56.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "1a2b3c4d-5e6f-4a1b-8c2d-3e4f5a6b7c8d"}
{  "error": {    "statusCode": 401,    "message": "The request could not be authenticated.",    "innerErrors": [      {        "code": "UNAUTHORIZED",        "message": "The request could not be authenticated.",        "userMessage": "Your session has expired or is invalid. Please sign in again."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/documents/data/upload",  "dateTime": "2026-09-08T12:47:56.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "1a2b3c4d-5e6f-4a1b-8c2d-3e4f5a6b7c8d"}
{  "error": {    "statusCode": 500,    "message": "Failed to persist the uploaded file to storage.",    "innerErrors": [      {        "code": "FILE_UPLOAD_FAILED",        "message": "Failed to persist the uploaded file to storage.",        "userMessage": "Something went wrong while uploading. Please try again or contact support."      }    ]  },  "origin": "POST https://api.doctavian.com/v1/documents/data/upload",  "dateTime": "2026-09-08T12:47:56.000Z",  "operationId": "3a4b5c6d7e8f90112233445566778899",  "userId": "1a2b3c4d-5e6f-4a1b-8c2d-3e4f5a6b7c8d"}