# POST Create an upload

Declares a file and returns a short-lived presigned target to send its bytes to. Requires `customisers:write` and an `Idempotency-Key`. The `purpose` selects the accepted file types and the size cap, so declare the purpose of the slot you intend to attach to. Both the filename extension and the content type must be ones the purpose accepts; a mismatch answers 422 with the accepted values, and an oversized declaration answers 422 with `max_byte_size`. Send the bytes with the `upload_target`: use its `method`, its `url`, and every header it lists, with the file as the raw request body. The target expires about ten minutes after it is issued and is returned only by this response, so do not cache or store it. An idempotent replay of this request returns the recorded body with `upload_target` set to null, which means a retry after the target expired needs a new upload rather than the same one. Poll `GET /api/v3/uploads/{upload_id}` to confirm the bytes landed. Nothing is verified here. The declared size and type are what the API will issue a target for; the actual bytes are checked when you attach the upload to a file slot, and a file that fails that check is refused then.

- Source URL: https://www.signcustomiser.com/help/api/v3-post-create-an-upload/
- Markdown URL: https://www.signcustomiser.com/help/api/v3-post-create-an-upload.md
- Group: Uploads
- Method: POST
- Path: /api/v3/uploads
- Auth: Bearer token
- Required scopes: `customisers:write`

## Body parameters

- purpose (string, optional): No description provided.
- filename (string, optional): No description provided.
- content_type (string, optional): No description provided.
- byte_size (integer, optional): No description provided.

## Request body example

```json
{
  "purpose": "font_ttf",
  "filename": "Signature.ttf",
  "content_type": "font/ttf",
  "byte_size": 184320
}
```

## cURL example

```bash
curl https://web.signcustomiser.com/api/v3/uploads \
  --request POST \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "purpose": "font_ttf",
  "filename": "Signature.ttf",
  "content_type": "font/ttf",
  "byte_size": 184320
}'
```

## Response examples

### 201 POST 201 example 1

```json
{
  "data": {
    "object": "upload",
    "id": "upl_9f2c4b7ad13e6058ba41cd",
    "purpose": "font_ttf",
    "filename": "Signature.ttf",
    "content_type": "font/ttf",
    "byte_size": 184320,
    "status": "pending",
    "verification_failure_code": null,
    "expires_at": "2026-07-23T00:00:00Z",
    "attached_at": null,
    "created_at": "2026-07-22T00:00:00Z",
    "upload_target": {
      "method": "PUT",
      "url": "https://uploads.example.invalid/staged-upload-target-example",
      "headers": {},
      "expires_at": "2026-07-22T00:10:00Z"
    }
  },
  "links": {
    "self": "https://web.signcustomiser.com/api/v3/uploads/upl_9f2c4b7ad13e6058ba41cd",
    "documentation": "https://www.signcustomiser.com/help/api/"
  },
  "meta": {
    "api_version": "v3",
    "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
  }
}
```

### 400 Missing idempotency key

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/missing_idempotency_key",
  "title": "Missing idempotency key",
  "status": 400,
  "code": "missing_idempotency_key",
  "detail": "Provide an Idempotency-Key header for this write.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 401 Missing API key

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/missing_api_key",
  "title": "Missing API key",
  "status": 401,
  "code": "missing_api_key",
  "detail": "Provide a store API key as a bearer token.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 403 Insufficient scope

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/insufficient_scope",
  "title": "Insufficient scope",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "This operation requires the customisers:write scope.",
  "required_scopes": [
    "customisers:write"
  ],
  "granted_scopes": [
    "customisers:read"
  ],
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 409 Idempotency conflict

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/idempotency_key_conflict",
  "title": "Idempotency key conflict",
  "status": 409,
  "code": "idempotency_key_conflict",
  "detail": "This Idempotency-Key was already used for a different request body on this operation.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 422 File type not allowed

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/upload_type_not_allowed",
  "title": "Upload type not allowed",
  "status": 422,
  "code": "upload_type_not_allowed",
  "detail": "The font_ttf purpose does not accept application/pdf files.",
  "errors": [
    {
      "pointer": "/content_type",
      "code": "unsupported_value",
      "detail": "The font_ttf purpose does not accept application/pdf files.",
      "allowed_values": [
        "font/ttf"
      ]
    }
  ],
  "purpose": "font_ttf",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```

### 429 Upload target budget exhausted

```json
{
  "type": "https://www.signcustomiser.com/help/api/problems/rate_limited",
  "title": "Too many requests",
  "status": 429,
  "code": "rate_limited",
  "detail": "You have exceeded the request limit for this API key.",
  "retry_after": 60,
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
```
