---
title: "Upload documents"
canonical_url: "https://www.nutrient.io/guides/dws-viewer/developer-guides/upload-documents/"
md_url: "https://www.nutrient.io/guides/dws-viewer/developer-guides/upload-documents.md"
last_updated: "2026-05-27T15:15:53.462Z"
description: "Learn how to upload documents to Nutrient DWS using the API, supported formats, and the workflow for document management."
---

# Upload documents

Documents must be uploaded to Nutrient Document Web Services (DWS) before they can be used via server API or and opened in Nutrient Web SDK. Use the [`POST /viewer/documents`](https://www.nutrient.io/api/reference/viewer/public/#tag/Documents/operation/upload-document) endpoint to upload documents.

## File upload considerations

**Supported file formats** — `.pdf`, `.doc`, `.docx`, `.ppt`, `.pptx`, `.xls`, `.xlsx`, and other formats. For more information, refer to the [file type support](https://www.nutrient.io/api/reference/viewer/public/#tag/File-Type-Support) guide.

## Document upload workflow

The typical workflow involves uploading your document and extracting the document ID from the response, as demonstrated in the steps below.

> This example uses binary file upload, which is the most common and straightforward approach. DWS Viewer API also supports `multipart/form-data` for advanced use cases such as attaching XFDF files or specifying custom metadata.

### Uploading the document

Upload your document using binary file upload with headers:

```js

// Server-side document upload.
const uploadDocument = async (fileBuffer, mimeType) => {
  const response = await fetch("https://api.nutrient.io/viewer/documents", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": mimeType,
      "Content-Length": fileBuffer.length.toString(),
    },
    body: fileBuffer, // Binary file data (Buffer, Uint8Array, or ArrayBuffer). NOT `FormData`.
  });

  if (!response.ok) {
    throw new Error(`Upload failed: ${response.statusText}`);
  }

  return await response.json();
};

```

### Extracting the document ID from the response

The upload response contains the document ID in a nested structure:

```js

// Handle the nested response structure.
const extractDocumentId = (uploadResponse) => {
  // The document ID is always nested in the response data.
  return uploadResponse.data?.document_id;
};

// Example response structure:
// {
//   "data": {
//     "document_id": "actual-document-id-here",
//     "title": "document-title"
//   }
// }

```

## Troubleshooting

Below are solutions to the most common upload problems.

### Document upload errors

**"Invalid multipart" (400 Bad Request)**

- **Cause** — Incorrect multipart form data structure

- **Solution** — Ensure proper `FormData` usage with correct field names:

```js

// Correct — Using `multipart/form-data` (convenient for complex uploads).
const formData = new FormData();
formData.append("file", file);

const response = await fetch("https://api.nutrient.io/viewer/documents", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    // Don't set `Content-Type` — let the browser set it with boundary.
  },
  body: formData,
});

// Alternative — Binary upload (simpler for single file uploads).
const response = await fetch("https://api.nutrient.io/viewer/documents", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": file.type,
    "Content-Length": file.size.toString(),
  },
  body: fileBuffer,
});

```

**"404 Not Found" on document upload**

- **Cause** — Using the incorrect API endpoint

- **Solution** — Ensure you’re using the correct viewer-specific endpoint:

```js

// Incorrect
fetch('https://api.nutrient.io/documents', {...})

// Correct
fetch('https://api.nutrient.io/viewer/documents', {...})

```

### Document ID extraction issues

**Document ID is undefined or null**

- **Cause** — Expecting the document ID at the root level of response

- **Solution** — Handle the nested response structure:

```js

// Incorrect
const documentId = response.document_id;

// Correct — Handle nested structure.
const documentId = response.data?.document_id;

```

## Server implementation considerations

### Network timeouts

Set appropriate timeouts for document uploads. For example:

```js

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000);

const response = await fetch(url, {...options,
  signal: controller.signal,
});

```

## Error handling

API errors follow the structure below:

```json

{
  "error": "error_type",
  "message": "Human readable error message",
  "details": "Additional error context"
}

```

Common errors:

- `invalid_document` — Document not found or inaccessible

- `unsupported_format` — File format not supported

## Next steps

After uploading a document and obtaining the document ID, you can:

1. [Generate a session token](https://www.nutrient.io/guides/dws-viewer/developer-guides/generate-a-session-token.md) for the document.

2. [Open the document in Web SDK](https://www.nutrient.io/guides/dws-viewer/developer-guides/open-a-document-in-web.md) using the session token.

For a complete server implementation that combines document upload with session token generation, refer to the [Node.js integration example](https://www.nutrient.io/guides/dws-viewer/examples/nodejs-integration-example.md) guide.
---

## Related pages

- [Generate a session token](/guides/dws-viewer/developer-guides/generate-a-session-token.md)
- [Dashboard](/guides/dws-viewer/developer-guides/dashboard.md)
- [Architecture of DWS Viewer API integration](/guides/dws-viewer/developer-guides/architecture.md)
- [DWS Viewer API backend authentication](/guides/dws-viewer/developer-guides/backend-authentication.md)
- [DWS Viewer API client authentication flow](/guides/dws-viewer/developer-guides/client-authentication-flow.md)
- [Deployment options](/guides/dws-viewer/developer-guides/deployment-options.md)
- [DWS Viewer API developer guides](/guides/dws-viewer/developer-guides.md)
- [Open a document in Web SDK](/guides/dws-viewer/developer-guides/open-a-document-in-web.md)
- [Integrate DWS Viewer API with your own backend](/guides/dws-viewer/developer-guides/use-with-your-backend.md)

