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

# Start a document upload

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

## Request

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

Reserves a document on a Brand, and is the first of the three steps of an upload. The answer gives a URL with a short life. `PUT` the bytes to that URL with their `Content-Type`, then call finalize. The bytes do not go through this API. AdCrunch accepts PDF, GIF, JPEG, PNG and WebP. It refuses SVG, because a stored document is served from an adcrunch.dev host and an SVG carries script.

## Path parameters

- `slug` string, required

## Request body

- object
  - `content_type` string, required: The type you are about to upload. Re-checked against the stored object at finalize — this is only a declaration.
  - `filename` string, required

## Response `201`

A reserved destination, valid for `expiresInSeconds`. PUT the bytes to `uploadUrl`, then call finalize with `documentId`. The URL itself gives write access: anybody holding it can write that one object until it lapses. The Document does not exist for any reader until finalize succeeds.

- object
  - `documentId` string, required: Pass this to the finalize call.
  - `expiresInSeconds` number, required: How long `uploadUrl` stays valid. Reserve again if it lapses.
  - `uploadUrl` string, required: A short-lived presigned URL. PUT the bytes here.

## 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 Brand with that slug. `error` is `not_found`.
- `415`: That media type is not accepted. `error` is `unsupported_type`, and `allowed` names every type that is. This is the declared type; the stored object is checked again at finalize.

---

[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)
