# Get a presigned URL to upload a document

Source: https://docs.usetone.ai/reference/knowledge/createUploadUrl

> Phase one of a two-phase upload: declare the file, PUT the bytes to the URL you get back, then confirm.

`POST /v1/knowledge-bases/{id}/documents/upload-url`
Phase one of a two-phase upload: declare the file, PUT the bytes to the URL you get back, then confirm. `contentLength` is signed into the URL and must match exactly — a presigned PUT that does not pin the length is an unbounded write.

Requires the `write` scope.

## Parameters

| Name | In | | Meaning |
|---|---|---|---|
| `id` | path | required | The knowledge base's id. |

## Request body

| Field | Type | | Meaning |
|---|---|---|---|
| `contentLength` | integer | required | Exact size in bytes of the file you are about to PUT. Required because it is signed into the URL — a presigned PUT that does not pin the length is an unbounded write. A mismatch fails the upload. |
| `contentType` | string | required | The MIME type you are about to upload. |
| `filename` | string | required | The file name, with no path separators. Shown in the document list. |
| `kind` | string | required | What kind of document this is. Web pages are not uploaded — import those with POST /v1/knowledge-bases/{{id}}/documents/url instead. Open set — handle an unrecognised value rather than throwing. Today: `pdf`, `docx`, `txt`, `csv`, `md`. |

### Example request

```json
{
  "contentLength": 248311,
  "contentType": "application/pdf",
  "filename": "returns-policy.pdf",
  "kind": "file"
}
```

## Response

| Field | Type | | Meaning |
|---|---|---|---|
| `documentId` | string | required | Already reserved. Pass it to the confirm call once the upload succeeds. |
| `expiresInSeconds` | integer | required | How long the presigned upload URL stays valid. Upload before it lapses, then call the confirm endpoint. |
| `headers` | object | required | Send these verbatim on the PUT — the signature covers them. |
| `url` | string | required | PUT the file here. A short-lived signed URL — upload before it expires, then confirm. |

### Example response

```json
{
  "data": {
    "documentId": "9f1c2d84-4e3a-4f6c-b902-7d1e8a33c451",
    "expiresInSeconds": 0,
    "headers": {},
    "url": "https://uploads.usetone.ai/kb/9f1c2d84…?signature=…"
  }
}
```
