CMS and websites
Upload images to Wix with the Media Manager API
Generate exact sizes with SocialCutter and push them to Wix Media Manager: generate-upload-url, the binary upload, using the file and the real API limits.
- Wix
- Media Manager
- generate-upload-url
- API key
- multipart upload
- images
- Node
Why generate the sizes before uploading
Wix renders every image by cropping it to the slot it sits in: the page header, a product card, a gallery thumbnail, the blog post in the feed. If you upload the master, you leave that crop to the editor and the result changes between views.
The right flow is: one master goes in, SocialCutter returns every size, and Wix receives the file already cropped. The cover crop (the default mode) is centred: it scales and trims the excess evenly on both sides. There is no subject detection involved, so leave some air around the subject.
| Where it goes on the site | SocialCutter destination | Size |
|---|---|---|
| Main product image | instagram post | 1080x1080 (1:1) |
| Portrait image or story | instagram story | 1080x1920 (9:16) |
| Page or section header | twitter header | 1500x500 (3:1) |
| Wide banner | facebook post | 1200x630 (1.91:1) |
| Video thumbnail | youtube thumbnail | 1280x720 (16:9) |
The real sizes and formats come from GET /api/v1/platforms, which is public. The catalogue has no 4:5: square is 1:1 and portrait is 9:16.
Before you start: API key and permissions
The API key is generated in the Wix dashboard and sent in the Authorization header as-is, without the word Bearer:
export WIX_AUTH="IST.eyJra..." # API key from the dashboard
export SC_KEY="sc_your_key"
For the Media Manager the key needs the Manage Media Manager permission. The flow is documented here:
- Generate the upload URL: https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/generate-file-upload-url
- Upload with that URL: https://dev.wix.com/docs/api-reference/assets/media/media-manager/files/upload-api
Heads-up: Wix APIs are versioned and parameter names change. Always check the docs of the day before treating a flow as settled.
1. Generate the sizes with SocialCutter
curl -s -X POST "https://api.socialcutter.theboomer.dev/api/v1/images/process" \
-H "X-API-Key: *** \
-H "Content-Type: application/json" \
-H "Idempotency-Key: wix-home-2026-09" \
-d '{
"source": { "type": "url", "value": "https://your-cdn.com/master.jpg" },
"destinations": [
{ "platform": "instagram", "format": "post" },
{ "platform": "twitter", "format": "header" }
]
}' > sc.json
jq -r '.outputs[] | "\(.platform)/\(.format) \(.width)x\(.height) \(.url)"' sc.json
Every output carries url, width, height and size_bytes. For a local file use POST /api/v1/images/process/upload (multipart, file field, 5 MB max); for several masters, POST /api/v1/images/batch.
2. Ask for the upload URL and push the binary
The Media Manager does not take the file against its own endpoint: first you request a signed URL and upload there with PUT.
WIX_BASE="https://www.wixapis.com"
# 2a. Signed URL
UPLOAD_URL=$(curl -s -X POST "$WIX_BASE/site-media/v1/files/generate-upload-url" \
-H "Authorization: $WIX_AUTH" \
-H "Content-Type: application/json" \
-d '{"mimeType":"image/jpeg","fileName":"category.jpg"}' | jq -r '.uploadUrl')
# 2b. Upload the file (binary)
curl -s -X PUT "$UPLOAD_URL?filename=category.jpg" \
-H "Content-Type: image/jpeg" \
--data-binary "@category.jpg" | jq '.file | {id, url, displayName}'
The response carries file.id and file.url (a static.wixstatic.com/media/... link). That url is what you paste into the page element, the product or the post.
If your outputs already live behind a public URL you can skip the upload: POST /site-media/v1/files/import with {"url": ..., "mimeType": ...} pulls them in directly, and POST /site-media/v1/bulk/files/import-v2 imports several at once.
3. Node snippet
const WIX = 'https://www.wixapis.com'
const AUTH = process.env.WIX_AUTH // API key, no 'Bearer'
const SC_KEY = process.env.SC_KEY
async function upload(socialCutterUrl, name) {
// 1. Signed URL
const r1 = await fetch(`${WIX}/site-media/v1/files/generate-upload-url`, {
method: 'POST',
headers: { Authorization: AUTH, 'Content-Type': 'application/json' },
body: JSON.stringify({ mimeType: 'image/jpeg', fileName: name })
})
const { uploadUrl } = await r1.json()
// 2. Push the binary
const bin = await fetch(socialCutterUrl)
const r2 = await fetch(`${uploadUrl}?filename=${encodeURIComponent(name)}`, {
method: 'PUT',
headers: { 'Content-Type': 'image/jpeg' },
body: Buffer.from(await bin.arrayBuffer())
})
const { file } = await r2.json()
return file // { id, url, ... } — may not be ready yet
}
;(async () => {
const sc = await fetch('https://api.socialcutter.theboomer.dev/api/v1/images/process', {
method: 'POST',
headers: { 'X-API-Key': SC_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
source: { type: 'url', value: 'https://your-cdn.com/master.jpg' },
destinations: [{ platform: 'instagram', format: 'post' }]
})
}).then(r => r.json())
for (const out of sc.outputs) {
const f = await upload(out.url, `wix-${out.platform}-${out.format}.jpg`)
console.log(out.platform, out.format, '→', f.url)
}
})()
The Wix API’s real limits
Worth knowing before you promise an automation:
- The Media Manager is reachable with an API key and the right permission, to upload and import files.
- The file is not ready when the call returns. A
200on the upload does not mean you can use it: the docs ask you to wait for the File Ready event (or File Failed) before managing it. - Files over 10 MB go through the resumable URL (
generate-resumable-upload-url), not the regular one. - Publishing content through the API is not available on every plan or editor. The Blog API exists, but calling it requires authenticating as a Wix app or user with the matching permissions and, for a third-party app, supplying a
memberIdas the author. On many sites the practical path is to upload the image to the Media Manager and place it by hand in the editor, or to expose a Velo web method inside the site itself, which runs with the site’s own permissions. Reference: https://dev.wix.com/docs/api-reference/business-solutions/blog/introduction
That is why this guide covers the part that is genuinely programmable —the images— and leaves publishing to whatever route your plan allows.
Cost
- 1 use per destination (platform and format) per request; repeated destinations are not charged twice.
- Failed processing is refunded.
- Every plan includes API and MCP: Free 3 uses/day, Basic 10, Pro 30, Agency 100, from 0 / 3 / 9 / 29 EUR per month.
Typical errors
| Symptom | Cause | Fix |
|---|---|---|
401 from the Wix API | Key mistyped or a stray Bearer | Send only the key in Authorization |
403 when generating the URL | Missing the Manage Media Manager permission | Recreate the key with that permission |
| The upload responds but the image is missing | The file is not ready yet | Wait for the File Ready event before using it |
Wrong Content-Type | Uploaded without the header or with a wrong mime | Send image/jpeg or image/png matching the file |
| The image looks oddly cropped | You uploaded the master and Wix cropped it | Upload the SocialCutter size instead |
413 from SocialCutter | The master is over 5 MB | Shrink the image before uploading it |
429 from SocialCutter | Wallet quota exhausted | Check your quota in the dashboard or upgrade |
Next steps
- Terminal: Process images with the API from the terminal (curl)
- Node: Process images with the API from Node
- Webflow: Integrate SocialCutter with the Webflow API
- WordPress: Integrate SocialCutter with WordPress and WooCommerce
- Automation: Automate image resizing for social media
- Documentation: https://docs.socialcutter.theboomer.dev
Frequently asked questions
How do I authenticate against the Wix API?
With an API key from the Wix dashboard, sent in the Authorization header as-is (Authorization: <AUTH>), without the word Bearer. An OAuth token as a user or app identity also works. The key needs the Manage Media Manager permission.
Can I create blog posts through the API on any plan?
No. The Media Manager works with an API key, but publishing content is not uniform: the Blog API requires authenticating as a Wix app or user, and a third-party app must supply a memberId as the author. On many plans and editors there is no way to create the post through the API; there the practical path is to upload the image and place it in the editor.
Is the image usable as soon as the upload responds?
No. The docs themselves warn that a 200 on the upload does not mean the file is ready: processing takes time. Wait for the File Ready event, or poll the file until it stops being processed, before using it.
Do I upload the master, or the cropped version?
Upload it already cropped. Wix crops on its own when rendering the file, so if you upload the master and rely on that crop you end up with inconsistent framing between the editor, mobile and the app.
What does it cost to prepare the images?
1 use per destination, meaning per platform and format pair. One master turned into a square and a portrait version is 2 uses; repeated destinations in the same request are not charged twice.