---
title: "Finalize a document upload"
method: POST
path: "/context/brands/{slug}/documents/{documentId}/finalize"
tags: ["Documents"]
---

# Finalize a document upload

`POST /context/brands/{slug}/documents/{documentId}/finalize`

## Request

- Base URL: `https://api.adcrunch.dev`
- URL: `https://api.adcrunch.dev/context/brands/{slug}/documents/{documentId}/finalize`
- Auth: HTTP bearer

Completes a reserved document after you send the bytes, and is the third of the three steps of an upload. AdCrunch reads the size and the content type from the stored file. It does not take them from you, because the upload URL applies no rules of its own. This call is the only point of validation: a file over 25 MB, or of a type this API does not accept, is refused here and discarded. Until it succeeds, the Document is in no listing and in no read.

## Path parameters

- `documentId` string, required
- `slug` string, required

## Response `200`

The Document, now readable. `sizeBytes` and `mimeType` are read off the stored object rather than taken from your declaration. `name` is the display name, and it falls back to the filename. `url` is public: anybody holding it can read the file.

- object
  - `createdAt` number, required: Milliseconds since the Unix epoch, UTC.
  - `filename` string, required
  - `id` string, required
  - `mimeType` string, required
  - `name` string, required: The display name. Falls back to the filename.
  - `sizeBytes` number, required: Read off the stored object at finalize, never from the client.
  - `targetId` string, required
  - `targetType` string, required: What the Document is attached to. `brand` today.
  - `url` string, required

## Other responses

- `400`: The request does not match the schema of this operation: a field is missing or has the wrong type, or the body is not valid JSON. `error` is `invalid_request`, and `issues` names each field. Nothing was changed.
- `401`: No API key, or one that does not resolve. See the security scheme. `error` is `unauthorized`.
- `402`: The organization has no active subscription. An owner subscribes at `paywallUrl`. `error` is `organization_unentitled`.
- `403`: The caller does not hold `brand:write`. `error` is `forbidden`.
- `404`: No reservation with that id on this Brand. `error` is `not_found`.
- `409`: The reservation exists but no bytes have arrived. `error` is `no_object`. PUT to the `uploadUrl` first.
- `413`: The stored object is over the limit. `error` is `too_large`.
- `415`: The **stored** object is not an accepted type, whatever was declared at reservation. `error` is `unsupported_type`, the `message` names what the object turned out to be, and the object has been discarded. Reserve again to retry.

---

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