---
title: "Finish a resumable upload"
method: POST
path: "/v1/uploads/{uuid}/complete"
tags: ["Files"]
---

# Finish a resumable upload

`POST /v1/uploads/{uuid}/complete`

## Request

- Base URL: `https://contentmaschine.ai/api`
- URL: `https://contentmaschine.ai/api/v1/uploads/{uuid}/complete`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://contentmaschine.ai/api/oauth/authorize`, token URL `https://contentmaschine.ai/api/oauth/token`)

Joins the parts, checks the size and the content, and adds the file to your library.
Video and audio come back with `media` filled in. Repeating a complete that succeeded
returns the same file.

## Path parameters

- `uuid` string, uuid, required

## Request body

- object
  - `parts` object[], required: Every part, once.
    - `part_number` integer, required: 1 to parts.
    - `etag` string, required: The ETag header the PUT returned.

## Response `200`

The file.

- object
  - `success` boolean
  - `data` object
    - `file_uuid` string, uuid
    - `file` FileListItem
      - `uuid` string, uuid
      - `file_name` string
      - `mime_type` string
      - `size_bytes` integer, nullable
      - `width` integer, nullable
      - `height` integer, nullable
      - `created_at` string, nullable
      - `thumbnail_url` string, nullable: Session thumbnail path, or null.
      - `media` object, nullable: Video and audio only; null for images. Fields are null until the file is probed.
        - `duration_ms` integer, nullable
        - `width` integer, nullable
        - `height` integer, nullable
        - `fps` object, nullable
          - `num` integer
          - `den` integer
        - `has_audio` boolean, nullable
        - `video_codec` string, nullable
        - `audio_codec` string, nullable
  - `timestamp` string, date-time

## Other responses

- `400`: Invalid parts list.
- `401`: Missing or invalid API key.
- `403`: The token does not hold files:write.
- `404`: Unknown upload, or not yours.
- `409`: Parts are missing on the storage side, or the upload is not open.
- `410`: The upload expired.
- `422`: Size or content does not match; the file was deleted.
- `503`: Storage not reachable; try again.
- `default`: Any other error. Every failure this API emits uses the same envelope; branch on `error.type`, never on `error.message`, and quote `error.correlation_id` to support.

---

[API](https://skmtc.dev/contentmaschine/apis/contentmaschine-ai-api.md) · [All operations](https://skmtc.dev/contentmaschine/apis/contentmaschine-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/contentmaschine/apis/contentmaschine-ai-api/revisions/28c74f46051c?raw)
