---
title: "Create an upload link"
method: POST
path: "/projects/{project_id}/upload-links"
tags: ["Uploads"]
---

# Create an upload link

`POST /projects/{project_id}/upload-links`

## Request

- Base URL: `https://api.propertypixel.app/v1`
- URL: `https://api.propertypixel.app/v1/projects/{project_id}/upload-links`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://llflgtovnkrsjqydycyu.supabase.co/auth/v1/oauth/authorize`, token URL `https://llflgtovnkrsjqydycyu.supabase.co/auth/v1/oauth/token`)

Create a private link (with a QR code) the user opens on their phone or computer to add photos to a project, with no login. Use it when the user needs to send photos you can't receive directly, such as photos on their phone. Share the url, or show the QR code, and tell the user the link works for 2 hours. Photos appear in the project as they upload. To follow progress, call get_project and read upload_link.status and upload_link.photos_received until status is done (the user tapped Done), or simply ask the user to tell you when they've finished.

Requires a connection with edit access.

## Path parameters

- `project_id` string, uuid, required: The project the photos go into.

## Headers

- `Idempotency-Key` string: A unique key (for example a UUID) that makes retries safe. A retry with the same key and body returns the stored response; the same key with a different body returns 422. Keys last 24 hours.

## Response `201`

Create an upload link

- UploadLink
  - `object` 'upload_link', required
  - `id` string, uuid, required
  - `url` string, uri, required: Share this with the user. It opens a page that adds photos to the project, with no login. Treat it like a password.
  - `qr_svg` string, required: The same URL as a QR code (SVG markup), for scanning with a phone.
  - `expires_at` string, date-time, required
  - `status` 'waiting' | 'receiving' | 'done' | 'expired', required
  - `photos_received` integer, required
  - `max_photos` integer, required: How many photos this link accepts (the project's free space).
  - `project_id` string, uuid, required

## Other responses

- `400`: The request is invalid. Codes: `validation_failed`.
- `401`: Missing, invalid or revoked credential. Codes: `unauthorized`.
- `403`: The credential can't do this. View-only connections get forbidden_scope on writes. Codes: `forbidden_scope`, `forbidden`.
- `404`: The resource doesn't exist in this workspace. Codes: `not_found`.
- `409`: The request conflicts with the current state. Codes: `conflict`, `idempotency_in_progress`.
- `422`: An Idempotency-Key was reused with a different body, or an upload was rejected. Codes: `idempotency_conflict`, `upload_rejected`.
- `429`: Too many requests for this connection. Codes: `rate_limited`.
- `500`: Something failed on our side. Retry later. Codes: `internal`.

---

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