> ## Documentation Index
> Fetch the complete documentation index at: https://developers.dock.us/llms.txt
> Use this file to discover all available pages before exploring further.

# Uploading files

> Learn how to upload files using API.

Creating an asset from a file is a two-step process: upload the file, then create the asset from it. Link and embed assets skip the upload entirely — create them directly with a `url` (or `customCode`).

## 1. Create a file and upload the bytes

Call [Create a file](/api-reference/endpoint/files/create-a-file) with the file's name and MIME type. The response contains the file `id` and a presigned `upload` target:

```bash theme={null}
curl -X POST https://api.dock.us/v1/files \
  -H "Authorization: Bearer $DOCK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fileName": "sales-deck.pdf", "mimeType": "application/pdf"}'
```

```json theme={null}
{
  "data": {
    "file": {
      "id": "f9Ghw2n0Ju3D",
      "uploadStatus": "in_progress",
      "url": null
    },
    "upload": {
      "url": "https://storage.googleapis.com/...",
      "method": "PUT",
      "headers": { "Content-Type": "application/pdf" },
      "expiresAt": "<one hour after the file was created>"
    }
  }
}
```

Then `PUT` the raw bytes directly to `upload.url` with the returned `Content-Type` header, before `expiresAt` (1 hour):

```bash theme={null}
curl -X PUT "<upload.url>" \
  -H "Content-Type: application/pdf" \
  --data-binary @sales-deck.pdf
```

<Note>
  The `Content-Type` header on the PUT request must exactly match the `mimeType`
  the file was created with, or Google Cloud Storage rejects the upload.
</Note>

## 2. Create the asset

Call [Create an asset](/api-reference/endpoint/assets/create-an-asset) with the file id. Dock verifies the upload completed, marks the file ready, and creates the asset — optionally tagged with existing [tags](/api-reference/endpoint/tags/create-a-tag):

```bash theme={null}
curl -X POST https://api.dock.us/v1/assets \
  -H "Authorization: Bearer $DOCK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "pdf",
    "name": "Sales deck",
    "fileId": "f9Ghw2n0Ju3D",
    "tagIds": ["RiHO4e0Ju3DS"]
  }'
```

Calling this before the bytes are uploaded returns a `400` — retry after the PUT completes. A file can back exactly one asset.

## Supported asset types

| `type`     | Source                | Notes                                                       |
| ---------- | --------------------- | ----------------------------------------------------------- |
| `pdf`      | `fileId`              | Page count and document metadata extracted automatically    |
| `image`    | `fileId`              | Dimensions extracted automatically                          |
| `video`    | `fileId`              | Pass `metadata.width/height/duration` if available          |
| `audio`    | `fileId`              | Pass `metadata.duration` if available                       |
| `docx`     | `fileId`              | Converted to PDF; returned as `microsoftWordEmbedPdf`       |
| `ppt`      | `fileId`              | Converted to PDF; returned as `microsoftPowerPointEmbedPdf` |
| `xlsx`     | `fileId`              | Converted to PDF; returned as `microsoftExcelEmbedPdf`      |
| `htmlPage` | `fileId`              | Standalone HTML file rendered as a page                     |
| `link`     | `url`                 | Link preview metadata resolved automatically                |
| `embed`    | `url` or `customCode` | Exactly one of the two                                      |

## Office documents convert asynchronously

Uploaded office documents (`docx`, `ppt`, `xlsx`) are rendered to PDF in the background. The asset is created immediately, but its backing file reports `uploadStatus: "in_progress"` until conversion finishes. Poll [Retrieve a file](/api-reference/endpoint/files/retrieve-a-file) with `properties[]=uploadStatus` to track it.
