CMS and websites
Set the product image on BigCommerce with the v3 API
Add a product image on BigCommerce with the v3 Catalog API using the URL SocialCutter returns and mark it as the main one. curl and Python.
- BigCommerce
- Catalog API
- product image
- API v3
- image_url
- is_thumbnail
- OAuth scopes
- Python
Why generate the sizes before uploading
A product image shows up in the catalogue grid, on the product page, in the cart line and in the social posts that promote the product. Each slot wants a different ratio, and uploading one copy per slot leaves the catalogue full of near-identical files.
The flow is: one master goes in, SocialCutter returns one output per destination, and BigCommerce receives the right one in each slot. The cover fit mode (the default) is a centred crop: it scales the image and splits the excess evenly on both sides. There is no subject detection and no automatic step that decides what to crop.
| Use in BigCommerce | SocialCutter destination | Size |
|---|---|---|
| Product main image | instagram post | 1080x1080 (1:1) |
| Second product image | instagram story | 1080x1920 (9:16) |
| Category banner | facebook post | 1200x630 (1.91:1) |
| Store header | twitter header | 1500x500 (3:1) |
| Product video thumbnail | youtube thumbnail | 1280x720 (16:9) |
The full catalogue comes from GET /api/v1/platforms, which is public, and is summarised in the social media sizes guide.
Note: there is no 4:5 in the SocialCutter catalogue. Vertical is 9:16 (1080x1920) and square is 1:1 (1080x1080). Use 1:1 as the main image; if you need an exact 4:5, crop outside SocialCutter.
Before you start: credential and scopes
A BigCommerce API account is created in the control panel under Settings → API → API accounts. You pick the scope as you create it. Since every request in this guide hits the Catalog API v3, you need the products scope:
| Scope | What you need it for here |
|---|---|
store_v2_products | Creating and updating product images |
store_v2_products_read_only | Only if you just read the catalogue |
Scopes are granted when the credential is created and are not widened per request: if one is missing, regenerate the account. The current list and names live at https://developer.bigcommerce.com/docs/start/authentication/api-accounts — check it, because BigCommerce has been consolidating endpoints under a shared products scope.
Authentication uses two headers: X-Auth-Token with the access token and Accept: application/json. The store hash goes in the path:
export BC_STORE="your_store_hash"
export BC_TOKEN="your_access_token"
export SC_KEY="sc_your_key"
export BC_API="https://api.bigcommerce.com/stores/$BC_STORE/v3"
curl -s "$BC_API/catalog/products?limit=1" \
-H "X-Auth-Token: $BC_TOKEN" \
-H "Accept: application/json" | jq '.data[0] | {id, name}'
1. Process the master with SocialCutter
curl -s -X POST "https://api.socialcutter.theboomer.dev/api/v1/images/process" \
-H "X-API-Key: *** \
-H "Content-Type: application/json" \
-d '{
"source": { "type": "url", "value": "https://your-cdn.com/master.jpg" },
"destinations": [
{ "platform": "instagram", "format": "post" },
{ "platform": "instagram", "format": "story" }
]
}' > sc.json
jq '.image_id, (.outputs[] | {url, platform, format, width, height})' sc.json
Each output is a public URL. BigCommerce accepts URLs when creating an image, so there is nothing to download.
2. Create the product image
The creation endpoint lives under the product and takes one image per request. It has two mutually exclusive modes:
image_urlin JSON: you pass the SocialCutter URL and BigCommerce fetches it.image_filein multipart: you upload the binary. The header must then bemultipart/form-data.
MAIN_URL=$(jq -r '.outputs[] | select(.platform=="instagram" and .format=="post") | .url' sc.json)
curl -s -X POST "$BC_API/catalog/products/123/images" \
-H "X-Auth-Token: $BC_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d "{\"image_url\": \"$MAIN_URL\", \"is_thumbnail\": true, \"description\": \"Front view 1:1\"}" \
> image.json
jq '.data | {id, is_thumbnail, url_standard, url_thumbnail}' image.json
With is_thumbnail: true at creation the image is born as the main one. description is the alt text the storefront uses.
Reference: https://developer.bigcommerce.com/docs/store-operations/catalog
3. Python variant and multipart variant
With requests the flow is the same. The JSON goes through json= and the multipart through files=; mixing image_url with image_file is an error.
import os
import requests
SC_KEY = os.environ["SC_KEY"]
BC_API = f'https://api.bigcommerce.com/stores/{os.environ["BC_STORE"]}/v3'
BC_HEADERS = {
"X-Auth-Token": os.environ["BC_TOKEN"],
"Accept": "application/json",
}
sc = requests.post(
"https://api.socialcutter.theboomer.dev/api/v1/images/process",
headers={"X-API-Key": SC_KEY, "Content-Type": "application/json"},
json={
"source": {"type": "url", "value": "https://your-cdn.com/master.jpg"},
"destinations": [{"platform": "instagram", "format": "post"}],
},
timeout=30,
)
sc.raise_for_status()
main_url = sc.json()["outputs"][0]["url"]
product_id = 123
created = requests.post(
f"{BC_API}/catalog/products/{product_id}/images",
headers=BC_HEADERS,
json={"image_url": main_url, "is_thumbnail": True, "description": "Front view 1:1"},
timeout=30,
)
created.raise_for_status()
image = created.json()["data"]
print(image["id"], image["is_thumbnail"], image["url_standard"])
# Multipart variant, when the image only exists on disk:
with open("story.jpg", "rb") as fh:
up = requests.post(
f"{BC_API}/catalog/products/{product_id}/images",
headers=BC_HEADERS, # requests sets the multipart Content-Type itself
files={"image_file": ("story.jpg", fh, "image/jpeg")},
data={"is_thumbnail": "false"},
timeout=60,
)
up.raise_for_status()
Form fields carry no types: is_thumbnail travels as the string "false" or "true".
4. Changing the main image afterwards
If the image already exists and you want it promoted to main, update it by its id. A product can only have one thumbnail at a time, so the previous one stops being it implicitly.
IMAGE_ID=$(jq -r '.data.id' image.json)
curl -s -X PUT "$BC_API/catalog/products/123/images/$IMAGE_ID" \
-H "X-Auth-Token: $BC_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"is_thumbnail": true}' | jq '.data.is_thumbnail'
To change the order the images are shown in, use sort_order (higher numbers lose priority). Endpoint reference: https://developer.bigcommerce.com/docs/store-operations/catalog
Cost
- 1 use per destination (platform and format) per request; duplicates are not charged twice.
- Failed processings are refunded.
- Plans 0/3/9/29 EUR, all with API and MCP.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
401 from BigCommerce | Access token missing or from another store | Check X-Auth-Token and that the store hash in the path is the right one |
403 from BigCommerce | The credential lacks the products scope | Regenerate the API account with store_v2_products |
422 with image_url | The URL is not public, exceeds 255 characters, or the format is unsupported | Pass the SocialCutter URL and use JPEG, PNG, GIF, WEBP, BMP, WBMP or XBM |
413/image rejected | The file is over 8 MB | Generate a smaller master with SocialCutter and retry |
400 when sending both fields | image_url and image_file were sent together | Pick one: JSON with a URL or multipart with a file |
413 from SocialCutter | The master is over 5 MB | Shrink the master before processing it |
No code and next steps
An automation tool chains the same steps with nodes: a trigger, an HTTP node to /api/v1/images/process and an HTTP node to the Catalog API with the output URL. The general pattern is in the automating social media images guide.
- Shopify: Integrate SocialCutter with the Shopify Admin API
- WordPress and WooCommerce: Integrate SocialCutter with WordPress and WooCommerce
- Python: Process images with the API from Python
- Terminal: Process images with the API from the terminal (curl)
- Documentation: https://docs.socialcutter.theboomer.dev
Frequently asked questions
Can I hand BigCommerce the URL SocialCutter returns?
Yes. The image creation endpoint accepts image_url in a JSON request, so the SocialCutter output can be passed straight through without downloading and re-uploading it. If you would rather send the binary, there is a multipart variant with the image_file field.
How do I mark the image as the main one?
With the is_thumbnail field set to true. You can include it in the creation body, or update an existing image with PUT to that image's endpoint. A product can only have one thumbnail at a time, and if it has a single image that image acts as both the main image and the thumbnail.
Which scopes does the credential need?
The products scope of the API account (store_v2_products; store_v2_products_read_only if you only read). It is granted when the API account is created and cannot be widened per request: if it is missing, regenerate the credential with the scope ticked.
What is the size limit and which formats are accepted?
8 MB per image, both by URL and by file upload, and one file per request. The types BigCommerce documents are BMP, GIF, JPEG, PNG, WBMP, XBM and WEBP.
What does it cost to process one product image?
1 use per destination, meaning per platform and format pair. Instagram post and Instagram story from the same master spend 2 uses.