---
title: "Store an image or video permanently for a site"
method: POST
path: "/api/v1/sites/{id}/assets"
tags: ["Assets"]
---

# Store an image or video permanently for a site

`POST /api/v1/sites/{id}/assets`

## Request

- Base URL: `https://app.mondovo.com`
- URL: `https://app.mondovo.com/api/v1/sites/{id}/assets`
- Auth: HTTP bearer

Fetch-by-URL rehosting: pass an HTTPS URL (including expiring signed URLs) and Mondovo downloads the file, stores it permanently on its CDN, registers it in the site’s asset library, and returns a stable URL. Allowed types: images (JPG, PNG, WebP, GIF; max 20 MB) and video (MP4, WebM, MOV; max 80 MB — videos are optimized for the web after upload). Requires scope `assets:write` or `sites:refine`.

## Request body

- UploadAssetInput
  - `url` string, uri, required: HTTPS URL of the image or video to store permanently (a generated image, stock URL, or expiring signed URL). Mondovo downloads it and returns a stable CDN URL.
  - `alt_text` string: Optional label / alt text kept on the asset.
  - `filename` string: Optional display name for the asset library. The stored file name is always derived from the validated content type.

## Response `200`

Stored. Use `url` — it never expires.

- object
  - `site_id` string, uuid, required
  - `asset_id` string, uuid: Asset-library record ID (may be omitted).
  - `url` string, uri, required: Permanent CDN URL.
  - `type` 'image' | 'video', required
  - `mime_type` string, required
  - `bytes` integer, required: Stored size in bytes.
  - `message` string

## Other responses

- `400`: Error codes: `invalid_json`, `validation_error`, `invalid_input`, `invalid_url` (non-HTTPS or blocked host), `fetch_failed` (source unreachable/expired), `unsupported_type`, `empty_asset`.
- `401`: Authentication failed. Error codes: `invalid_api_key` (missing/unknown key), `key_revoked`, `key_expired`.
- `403`: Authenticated but not allowed. Error codes: `addon_required` (the API key’s workspace no longer has the Agency add-on — checked on every request, not just at key creation) and `missing_scope` (the key lacks the scope this endpoint needs).
- `404`: `site_not_found`.
- `413`: `file_too_large` — over the 20 MB (image) / 80 MB (video) cap.
- `429`: Rate limit exceeded (`rate_limit_exceeded`). The body includes `retry_after_seconds`, `limit`, and `window` ("minute" or "hour"); a `Retry-After` header is also set.
- `500`: Error codes: `upload_failed`, `internal_error`.

---

[API](https://skmtc.dev/mondovo/apis/mondovo-public-api.md) · [All operations](https://skmtc.dev/mondovo/apis/mondovo-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mondovo/apis/mondovo-public-api/revisions/1baa3e2865ba?raw)
