> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getqr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Files

> Upload PDFs, images, videos and logos for your QR codes.

> [!NOTE]
>
> The GetQR API is in beta and is available to selected workspaces. Details may change before the general release.

PDF, image and video QR codes point at a file, and a custom logo is a file too. Uploading takes two steps: register the file to get a URL, then send the bytes to that URL.

| Method | Path | Description |
| - | - | - |
| `POST` | `/api/v1/files` | [Register a file upload](#register-a-file-upload) |

## Upload a file

**1. Register the file**

Call [Register a file upload](#register-a-file-upload) with the file's `target`, `contentType` and `size`. The `target` decides the accepted content types and the size limit. You get a `fileId` and an `uploadUrl`.

**2. Send the file**

Send the file with a `PUT` request to `uploadUrl`. Its `Content-Type` and `Content-Length` must exactly match the `contentType` and `size` you registered: anything else is rejected. The URL is pre-signed, so don't add your API key. It expires after 10 minutes.

```bash theme={null}
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  --data-binary @menu.pdf
```

**3. Use the file ID**

Pass `fileId` when you [create a QR code](https://docs.getqr.com/api/endpoints/qr-codes.md):

* As `fileId` for a `pdf`, `image` or `video` QR code. Upload with the matching target.
* As `fileId` for the profile image of a `vcard`, `social`, `multilink` or `event` QR code. Upload with the `logo` target.
* As `logoOptions.fileId`, with `logoOptions.type` set to `uploaded`, for a custom logo. Upload with the `logo` target. See [Customization](https://docs.getqr.com/api/guides/customization.md).

## Limits

| `target` | Accepted content types | Maximum size |
| - | - | - |
| `pdf` | `application/pdf` | 20 MB (20,971,520 bytes) |
| `image` | `image/*` | 5 MB (5,242,880 bytes) |
| `video` | `video/*` | 50 MB (52,428,800 bytes) |
| `logo` | `image/*` | 5 MB (5,242,880 bytes) |

* **Bare MIME type.** Send a single lowercase type and subtype, such as `image/png`. Parameters such as `;charset=` and lists are rejected.
* **No SVG.** XML-based types such as `image/svg+xml` aren't accepted. Upload a raster image such as `image/png` or `image/jpeg`.

## Headers

**Authorization** `string` *required*

`Bearer` followed by your API key. See [Authentication](https://docs.getqr.com/api/authentication.md).

**Content-Type** `string` *required*

`application/json`.

## Register a file upload

`POST /api/v1/files`

Registers a file and returns a pre-signed URL to upload it to. This call doesn't upload the file itself.

**target** `string` *required*

What the file is for: `pdf`, `image`, `video` or `logo`. Sets the accepted content types and the size limit. See [Limits](#limits).

**contentType** `string` *required*

MIME type of the file, for example `application/pdf`, without parameters. The upload request must send exactly this `Content-Type`.

**size** `integer` *required*

Exact size of the file in bytes, a positive whole number. Checked against the limit for the target. The upload request must send exactly this `Content-Length`.

**name** `string`

Original file name, up to 255 characters. Kept for display in the dashboard. A path with `/` or `\` is rejected.

**fileId** `string`

ID to pass as `fileId` or `logoOptions.fileId`.

**uploadUrl** `string`

Pre-signed URL to `PUT` the file to.

**expiresIn** `integer`

Seconds until `uploadUrl` expires: `600`.

**method** `string`

HTTP method for the upload: `PUT`.

```bash cURL theme={null}
curl -X POST "https://getqr.com/api/v1/files" \
  -H "Authorization: Bearer $GETQR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "pdf",
    "contentType": "application/pdf",
    "size": 248000,
    "name": "menu.pdf"
  }'
```

```json 200 theme={null}
{
  "fileId": "file_7bQ2xR9mKp",
  "uploadUrl": "https://storage.getqr.com/qrs-content/pdf/file_7bQ2xR9mKp?X-Amz-...",
  "expiresIn": 600,
  "method": "PUT"
}
```

## Common issues

> [accordion] 422 "Content type … is not allowed for target"
>
> The content type doesn't match the target. For example, `pdf` accepts only `application/pdf`. See [Limits](#limits).

> [accordion] 422 "must be a single lowercase type/subtype"
>
> Send the content type in lowercase and without parameters: `image/png`, not `Image/PNG` or `image/png; charset=utf-8`.

> [accordion] 422 "File is too large for target"
>
> The declared `size` is over the limit for the target. Compress the file before you register it.

> [accordion] The upload to uploadUrl fails
>
> The URL expires 10 minutes after you register the file, and the request must send exactly the registered `Content-Type` and `Content-Length`. Register the file again to get a new URL.

> [accordion] 422 "is registered but its content was never uploaded" when creating a QR code
>
> You registered the file but the `PUT` to `uploadUrl` didn't complete. Upload the file, then create the QR code.

> [accordion] 422 "was uploaded to …" when creating a QR code
>
> The file was registered with a different target, for example an `image` file used for a `pdf` QR code. Register a new upload with the matching target.

> [accordion] 404 "File … was not found" when creating a QR code
>
> The `fileId` doesn't exist. Take it from the response of [Register a file upload](#register-a-file-upload).

## What's next

> [card] [QR codes](https://docs.getqr.com/api/endpoints/qr-codes.md)

> [card] [QR types](https://docs.getqr.com/api/guides/qr-types.md)

> [card] [Customization](https://docs.getqr.com/api/guides/customization.md)

> [card] [Errors](https://docs.getqr.com/api/errors.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.