Skip to main content
SocialCutter

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 siteSocialCutter destinationSize
Main product imageinstagram post1080x1080 (1:1)
Portrait image or storyinstagram story1080x1920 (9:16)
Page or section headertwitter header1500x500 (3:1)
Wide bannerfacebook post1200x630 (1.91:1)
Video thumbnailyoutube thumbnail1280x720 (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:

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 200 on 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 memberId as 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

SymptomCauseFix
401 from the Wix APIKey mistyped or a stray BearerSend only the key in Authorization
403 when generating the URLMissing the Manage Media Manager permissionRecreate the key with that permission
The upload responds but the image is missingThe file is not ready yetWait for the File Ready event before using it
Wrong Content-TypeUploaded without the header or with a wrong mimeSend image/jpeg or image/png matching the file
The image looks oddly croppedYou uploaded the master and Wix cropped itUpload the SocialCutter size instead
413 from SocialCutterThe master is over 5 MBShrink the image before uploading it
429 from SocialCutterWallet quota exhaustedCheck your quota in the dashboard or upgrade

Next steps

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.