# Upload a file

```http
POST https://secure.yoprint.com/v1/api/store/{team_slug}/async_upload
```

- API version: v1
- Operation ID: `v1_public_async_upload_store`
- Section: Imports and exports › [Uploads](https://developer.yoprint.com/reference/uploads.md)
- Web page: https://developer.yoprint.com/reference/uploads/v1-async-upload-store/
- Authentication: `Authorization: Bearer YOUR_API_KEY`

Uploads one file that does not belong to anything yet, and returns its id. Then attach it with the operation for its destination, passing the id as `attachment[].id`: a job's mockups and production files, a sales order, a purchase order or a customer.

Send `multipart/form-data` with the file in `media`. Choose `collection` `mockup` for mockup images (images only) or `production_file` for production files; leave it out for other files (`default`).

## Permission

Any member of the team.

## Business rules

- `media` is required and must be a file.
- On the Free plan a file can be at most 5,240 KB. On paid plans the whole request (the file and the form around it) can be at most 100 MB.
- `location` (text) and `show_mockup` (a boolean) are checked but not saved here; set them with the update operation.

## Side effects

- Stores the file. It stays until you attach or delete it; unattached uploads are not cleaned up automatically.

## Path parameters

- `team_slug` (string, required): Your team slug, shown as Team ID next to your API key in Profile. Example `your-team`.

## Request body

Content type `multipart/form-data`, required.

Fields:

- `media` (string (binary), required): The file. With `collection=mockup` it must be an image a preview can be made of: PNG, JPG (JPE, JFIF), GIF, TIFF, BMP, WebP, SVG, HEIC or AVIF, and at most 120 megapixels.
- `collection` (string, optional): What the file is for. One of: `"default"`, `"mockup"`, `"production_file"`. Default `"default"`.

### Example request

```bash
curl -X POST 'https://secure.yoprint.com/v1/api/store/your-team/async_upload' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "collection": "mockup",
    "media": "(binary file)"
  }'
```

## Response

`200` Successful response.

Fields:

- `data` (object, required): A file attached to a record has extra fields for it: `job_id` (with `job_service` and the current approval fields), `job_preset_id` (a job preset's file, with `job_service`: the preset's service ids), `order_id`, `po_id` or `customer_id`.
  - `assetUrl` (string, optional): Images that are unattached uploads or job mockups only: a signed link the mockup editor uses. It expires; don't store it.
  - `collection` (string, optional): An upload is `default`, `mockup` or `production_file`. A file attached to a record can be in another collection of that record.
  - `created_at` (string (date-time), optional)
  - `custom_properties` (object | array, optional): Saved properties such as `location` and `show_mockup`. An empty list `[]` when there are none.
  - `dimensions` (object | null, optional): Pixel size of an image, read from its header; null for other files and for images uploaded before the size was recorded.
    - `height` (integer, optional)
    - `width` (integer, optional)
  - `file_name` (string, optional)
  - `id` (string, optional): The upload id. Pass it as `attachment[].id` to attach the file.
  - `is_image` (boolean, optional)
  - `mime_type` (string, optional)
  - `name` (string, optional): The original file name without its extension.
  - `position` (integer | null, optional): The file's place in its list.
  - `preview` (object | null, optional): Preview links `small`, `medium` and `large` (250, 800 and 1200 px). Images up to 10 MB are their own preview, so they have these at once; a larger image has them once `preview_state` is `ready`. Other files have null while they are unattached uploads; once attached, some records (such as jobs) give them links to a converted preview.
    - `large` (string, optional)
    - `medium` (string, optional)
    - `small` (string, optional)
  - `previewUrl` (string, optional): Same images only: a signed preview link for the mockup editor. It expires; don't store it.
  - `preview_state` (string, optional): `ready`: the preview links work. `processing`: an image over 10 MB whose stored preview a worker is still making (seconds); read the file again, or in the web app wait for `media.preview_state_changed` on the team channel. `too_large`: an image over 120 megapixels; it never gets a preview. `failed`: the worker gave up, or the converter could not read the original (missing, broken or unsupported); it is not retried. `none`: not an image. One of: `"ready"`, `"processing"`, `"too_large"`, `"failed"`, `"none"`.
  - `show_in_pdf` (boolean | null, optional)
  - `size` (integer, optional): Bytes.
  - `source_media_id` (string | null, optional): The file this one was copied from, when it is a copy. Always null on job and job preset files.
  - `url` (string, optional): A signed download link. It expires; don't store it.
  - `view_url` (string, optional): A signed link to view the file. It expires; don't store it.
- `status` (integer, required)
- `success` (boolean, required)

Example response:

```json
{
  "data": {
    "assetUrl": "https://secure.yoprint.com/api/store/your-team/mockup-design-asset/b0l2VJxwa3ppc7/view",
    "collection": "mockup",
    "created_at": "2026-11-03T09:30:00+00:00",
    "custom_properties": [],
    "file_name": "front-logo.png",
    "id": "b0l2VJxwa3ppc7",
    "is_image": true,
    "mime_type": "image/png",
    "name": "front-logo",
    "position": 1,
    "preview": {
      "large": "https://example.com/media/front-logo-1200.png",
      "medium": "https://example.com/media/front-logo-800.png",
      "small": "https://example.com/media/front-logo-250.png"
    },
    "previewUrl": "https://secure.yoprint.com/api/store/your-team/mockup-design-asset/b0l2VJxwa3ppc7/preview?size=preview",
    "show_in_pdf": null,
    "size": 182044,
    "source_media_id": null,
    "url": "https://example.com/media/front-logo.png?download=1",
    "view_url": "https://example.com/media/front-logo.png"
  },
  "status": 200,
  "success": true
}
```

## Errors

- `401` The API key is missing or wrong (`unauthenticated`).
- `403` You are not allowed to do this. `api_access_not_in_plan`: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only `{"message": "Insufficient Permission"}`. Other refusals use the error envelope, with `unauthorized` or `user_is_not_authorized`.
- `404` Not found. `page_not_found`: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. `code: null`, with a message that starts "No query results for": there is no record with that id.
- `413`
  - When: The request is over 100 MB. The web server refuses it before YoPrint reads it, so the body is not JSON. Fix: Keep files under 100 MB. Don't retry the same file.
- `422` Validation failed, or the image was refused by the media rules: a mockup that is not an image a preview can be made of (`mockup_type_not_allowed`), or an image over a size limit (`image_not_allowed`), or a file that is a web page, a script or a program (`validation_failed` on `media`, or `upload_not_allowed`: "This type of file cannot be uploaded."); `error.message` is one sentence naming the limit.
  - When: `media` is missing or not a file, `collection` is not allowed, or the file is over the Free plan limit (`validation_failed`, with the field under `error.fields`). Fix: Send the file as `media` in a multipart form.
  - When: A mockup is not one of the image formats above (`error.code` `mockup_type_not_allowed`), or an image is over 120 megapixels (`error.code` `image_not_allowed`); `error.message` is one sentence naming the limit. Fix: Send the file as a production file instead, or a smaller image.
  - When: The file is a web page, a script or a program, judged by its extension and by its detected type (for example .html, .js, .php, .py, .sh, .exe, .bat, .jar, .apk, .app, .dmg). `error.fields.media` says "This type of file cannot be uploaded." (`validation_failed`). Fix: Put the file in a .zip, or send a different file type.

## Notes

- The `url` and `view_url` links are signed and expire. Keep the `id`, not the links.
- Attach the upload soon after uploading it. An upload can be attached once; after that, it belongs to its record.

## Related

- [Get an uploaded file](https://developer.yoprint.com/reference/uploads/v1-async-upload-show.md): `GET /v1/api/store/{team_slug}/async_upload/{hash_id}`
- [Delete an uploaded file](https://developer.yoprint.com/reference/uploads/v1-async-upload-destroy.md): `DELETE /v1/api/store/{team_slug}/async_upload/{hash_id}`
- [Attach uploaded files to an order](https://developer.yoprint.com/reference/sales-order-files/v2-order-media-attach.md): `PUT /v2/api/store/{team_slug}/v2/sales_order/{hash_id}/media/attach`
