# Create a presigned file upload

- API version: 1.8.0
- Last updated: 2026-08-26
- Base URL: `https://api.ailingtu.com`
- Authentication: `x-api-key: <YOUR_API_KEY>`
- Success condition: HTTP 2xx and response `code === 0`
- Canonical operation schema: [JSON](/openapi/operations/createFileUpload.json)
- All operations: [operation index](/openapi/operations/index.json)

## POST /v1/file/presign

Operation ID: `createFileUpload`

Create a presigned file upload

Returns a file ID and a presigned object-storage URL. When `isNew` is false, skip PUT and confirmation. When `isNew` is true, PUT the raw file bytes to `uploadUrl` with the same Content-Type, without the x-api-key header, then confirm the upload.

| Field | Location | Type | Required | Description |
|---|---|---|---:|---|
| `fileName` | body | string | yes | File name including extension |
| `contentType` | body | string | yes | File MIME type |
| `size` | body | integer | yes | File size in bytes |
| `hash` | body | string | yes | SHA-256 of the UTF-8 encoded lowercase hex representation of the file bytes |

### Request example

```json
{
  "fileName": "video.mp4",
  "contentType": "video/mp4",
  "size": 12345678,
  "hash": "3786a02b..."
}
```

### Success response

```json
{
  "code": 0,
  "data": {
    "fileId": 591,
    "uploadUrl": "https://object-storage.example.com/presigned-url",
    "url": "https://cdn.ailingtu.com/media/video.mp4",
    "isNew": true,
    "expiresAt": "2026-07-29T12:00:00Z"
  },
  "message": "success"
}
```

### Important notes

- When isNew is true, PUT the raw file to uploadUrl with the same Content-Type, then call confirm.
- Do not send x-api-key to the object-storage PUT URL.

### Errors

| HTTP | Meaning |
|---:|---|
| 400 | Invalid request parameters or body. |
| 401 | The API key is missing or invalid. |
| 403 | The API key does not have permission for this operation. |
| 429 | Too many requests. Retry with exponential backoff. |
| 500 | Unexpected server error. Retry transient failures with exponential backoff. |
