POST /open-api/v1.0/products) by setting type: "design".
Looking to sell downloadable files instead? See Create digital products.
OAuth scope:
offer_write for creating products, plus media_write for the image upload steps below.API keys have full access to these endpoints. See Authentication for API keys or OAuth for multi-shop apps.front and back), each rendered from an image you supply. You don’t pass an image URL directly — instead you upload the image, register it in your media library to obtain an imageId, and reference that id per region when you create the product.
Pick a product template
Each design product renders onto a product template (the blank tee, mug, etc.). List the available templates with
GET /open-api/v1.0/product-templates and note the id you want — you’ll pass it as productTemplateId.Request a pre-signed upload URL
Call
POST /open-api/v1.0/media/upload-url with the file’s metadata. The response contains a short-lived uploadUrl to PUT the bytes to, and the fileUrl you’ll register in the next step.size is the file’s exact length in bytes — read it from the file rather than hardcoding it, and hold on to the value: you must send the same number again in the x-goog-content-length-range header when you PUT the bytes (step 3). Compute it from whatever you’re uploading:- Node (Buffer):
fileBytes.byteLength(or(await fs.promises.stat("my-design.png")).sizewithout reading the file) - Browser (
File/Blob):file.size - Shell:
wc -c < my-design.png
Response
Upload the image bytes
PUT the raw image bytes to the uploadUrl. This request goes directly to Google Cloud Storage, not to Fourthwall — do not send your Fourthwall credentials with it.The URL is signed with two conditions you must match exactly, or GCS rejects the upload with 403 SignatureDoesNotMatch:Content-Type— must equal thecontentTypeyou sent in step 2 (here,image/png).x-goog-content-length-range: 0,<size>— must use the samesize(byte count) you sent in step 2. Reuse the exact value; don’t recompute it a different way.
Register the image to get an imageId
Now persist the uploaded image in your media library with
POST /open-api/v1.0/media/images. Pass the fileUrl from step 2 along with the image’s pixel dimensions. The response’s id is the imageId you’ll reference per region.Response
Create the design product
Finally, call
POST /open-api/v1.0/products with type: "design". Each entry in regions pairs a product region with the imageId you just registered.Response
Placement strategies
By default each region usesplacementStrategy: "AUTO", which lets the renderer apply the product’s automation defaults. Set it explicitly to control how the image is placed:
| Strategy | Behavior |
|---|---|
AUTO | Let the renderer decide using the product’s defaults (preferred placement, or fill-all for items like mugs and stickers). |
FILL_ALL | Apply the image to every placement in the region. |
FULL_REGION | Render the image across the full region, skipping the preferred placement. |
PLACEMENT_ID | Target a single placement named by placementId (required for this strategy). |
colors and sizes are rendered, and set a profitMargin (a USD amount, e.g. 10.00) on top of the base cost. Products are created hidden unless you set publishOnCreate: true.
Next steps
Create a product reference
Full request and response schema for
POST /products.Media library
Upload and register images to reference by
imageId.Product templates
Browse templates to find a
productTemplateId.Create digital products
Sell downloadable files with a creator-set price.