> For the complete documentation index, see [llms.txt](https://docs.uptiq.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.uptiq.ai/platform-resources/skill-library/document-skills/document-upload.md).

# Document Upload

**Document Upload** ingests files and stores them — from a customer uploading a form, from a web link your workflow picks up, or from content a previous skill produced. It is the entry point for anything file-shaped, and the `documentId` it returns is what every downstream document skill works from.

## How it works

1. **Input resolution** — resolves input from `$input` (the previous skill's output) or `$secret` (vault secrets).
2. **Validation** — checks the configuration and the source/destination combination.
3. **Source handling** — when `source='remoteUrl'`, streams and downloads the file.
4. **Destination routing:**
   * `conversation` — stores in the in-memory cache, returns a `documentId`.
   * `storage` — writes to the specified path, returns a `storagePath`.
   * `signedUrl` — performs an HTTP PUT/POST to the URL you provide.
5. **Output envelope** — builds a uniform output envelope.
6. **Execution** — blocking. The skill returns only after the upload completes or fails.

## Worked example: collecting loan applications

A financial institution automates the first step of a loan application: collecting the form and its supporting documents — ID proof, income statements — directly from the customer.

**The problem.** Collecting and organizing documents from many applicants by hand is slow, error-prone, and creates delays. You need a secure, automated way for customers to submit files straight into the workflow.

**The approach.** Start the workflow with a Document Upload skill. Files are ingested and stored automatically, ready for the agent to process.

Configure it to collect a PDF application and save it to persistent storage:

1. **Set the source.** Under **Source**, select **User Input** — a person will be uploading the file.
2. **Constrain and explain.** In **Supported File Types**, enter the allowed extensions (`pdf`). In **Display Message**, write the instruction the customer will see: *"Please upload your completed Loan Application Form (PDF)."*
3. **Choose the destination.** Select **Storage** to save the document permanently. Optionally set a **Storage Path** (`new-applications/customer-xyz/`) to organize documents into subfolders.

<figure><img src="/files/mwktciVHp6ZsWmwaoPL6" alt=""><figcaption></figcaption></figure>

The `documentId` this returns is what you pass to [Document Fetch](/platform-resources/skill-library/document-skills/document-fetch.md), [Document To Image](/platform-resources/skill-library/document-skills/document-to-image.md), or [Document Delete](/platform-resources/skill-library/document-skills/document-delete.md) later in the workflow.

## Configuration reference

| Field                | Type                                             | Required                       | Description                         |
| -------------------- | ------------------------------------------------ | ------------------------------ | ----------------------------------- |
| `destination`        | `'conversation'` \| `'storage'` \| `'signedUrl'` | ✅                              | Final storage target.               |
| `source`             | `'userInput'` \| `'content'` \| `'remoteUrl'`    | ✅                              | How the file is supplied.           |
| `fileBase64`         | string                                           | when `source='content'`        | Base-64 encoded content.            |
| `remoteUrl`          | string                                           | when `source='remoteUrl'`      | Pre-signed or public GET URL.       |
| `remoteUrlHeaders`   | object                                           | —                              | Extra headers for the remote GET.   |
| `supportedFileTypes` | array                                            | — (`source='userInput'`)       | Allowed extensions, e.g. `["pdf"]`. |
| `displayMessage`     | string                                           | — (`source='userInput'`)       | UI hint shown to the user.          |
| `storagePath`        | string                                           | — (`destination='storage'`)    | Folder/key prefix in the bucket.    |
| `documentId`         | string                                           | —                              | Force object key / overwrite.       |
| `signedUrl`          | string                                           | when `destination='signedUrl'` | Pre-signed PUT/POST URL.            |
| `signedUrlMethod`    | `'PUT'` \| `'POST'`                              | — (`destination='signedUrl'`)  | Defaults to `PUT`.                  |
| `signedUrlHeaders`   | object                                           | —                              | Extra headers for the push.         |
| `name`               | string                                           | —                              | Display label on the canvas.        |
| `description`        | string                                           | —                              | Long-form help text.                |

## Output

| Field        | Type           | Always | Description                                                                   |
| ------------ | -------------- | ------ | ----------------------------------------------------------------------------- |
| `statusCode` | number         | ✅      | `200` success · `400` bad request · `500` internal error.                     |
| `documentId` | string \| null | ✅      | Identifier for downstream skills. **`null` when `destination='signedUrl'`.**  |
| `mimeType`   | string         | ✅      | Detected MIME type, e.g. `application/pdf`. Useful for conditional branching. |
| `error`      | string \| null | —      | Error message if processing failed; `null` on success.                        |

## Errors

All errors populate `error` and set `success=false`.

| Code               | Cause                                                      |
| ------------------ | ---------------------------------------------------------- |
| `VALIDATION_ERROR` | Invalid field combination or a missing required field.     |
| `DOWNLOAD_FAILED`  | `source='remoteUrl'` and the HTTP GET failed.              |
| `UPLOAD_FAILED`    | Writing to storage or the signed URL failed.               |
| `UNSUPPORTED_TYPE` | The user selected a file type not in `supportedFileTypes`. |

## Security

* Use `$secret` for tokens in `remoteUrlHeaders` or `signedUrlHeaders` — they are redacted from logs.
* Files in `conversation` scope follow the chat-retention TTL and are encrypted.
* Persistent storage inherits bucket IAM from `storageId`.
* Signed-URL pushes never log the full URL, so write permissions cannot leak.

## Testing in isolation

To execute this skill alone — via the UI **Test** button or directly:

* **Path** — `/skill-runtime/workflows/nodes/DocumentUpload/execute`
* **Method** — `POST`
* **Body:**

```json
{
  "nodeType": "DOCUMENT_UPLOAD",
  "config": { },
  "input": { }
}
```

<figure><img src="/files/JoN0ZQJuJK7iquP6HtF8" alt="" width="560"><figcaption><p>Document Upload processing flow</p></figcaption></figure>

***

To add this skill to an agent, see [Adding a Skill to the Agent](/agent-builder/build/adding-a-skill-to-the-agent.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.uptiq.ai/platform-resources/skill-library/document-skills/document-upload.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
