# Creative uploads

Upload an image once and reference its owner-bound file ID.

## Initialize the upload

Use a live campaigns:write key. PNG, JPEG, and WebP images up to 10 MiB are accepted. The uploaded creative is public media, so upload only material the owner intends to advertise.

```bash
curl "$BASE_URL/api/v1/assets" \
  -H "Authorization: Bearer $MR_API_KEY" \
  -H 'Idempotency-Key: launch-image-001' \
  -H 'Content-Type: application/json' \
  -d '{"filename":"launch.png"}'
```

The response contains data.file_id, upload_url, upload_headers, max_bytes, and complete_url. The upload_url is a temporary signed destination. Treat it as a secret capability and never send it to unrelated services. Preserve the same idempotency key on uncertain initialization.

## Transfer and complete

PUT the raw image bytes to the returned HTTPS upload_url, using exactly the returned upload_headers. Do not attach your MarketingRouter bearer token to this storage request. The JSON API's 16 KiB body limit does not apply to this direct upload.

Then POST /api/v1/assets/{file_id}/complete with your MarketingRouter bearer token. upload_pending means processing has not finished: retry completion with backoff. Successful completion verifies the provider file, MIME type, size, HTTPS preview URL, and workspace ownership before marking it ready.

Only a ready file can be used in a live campaign. GET /api/v1/assets requires campaigns:read and lists your files with preview_url and upload_status. There is a 100-upload workspace limit. Upload initialization retries expire after 23 hours; an expired signed URL needs a new upload.

## Creative review

The owner sees the exact image, headline, primary text, destination, schedule, geography, and budget before approval. Meta still reviews the ad after submission. A verified upload does not certify ad-policy compliance. Existing image uploads and [AI creative generation](/docs-markdown/creatives) are separate workflows. Generated images stay private until explicitly published as an owned advertising asset. Neither workflow automatically replaces campaign creative.