POST /open-api/v1.0/products) by setting type: "digital".
Selling printed merch from your own artwork instead? See Create design products.
OAuth scope:
offer_write for creating the product and managing its digital files. Attaching product images also needs media_write, since the image bytes are uploaded through the media library first.API keys have full access to these endpoints. See Authentication for API keys or OAuth for multi-shop apps.Create the product
Sendtype: "digital" with a creator-set price (a USD amount). Products default to hidden. Set publishOnCreate: true to make the product visible on the storefront as soon as it’s created; otherwise it stays hidden and can only be published from the Fourthwall admin.
Response
Attach downloadable files
These are the files your buyers download after purchase. Unlike media-library images — which are shop-wide and reusable across products byimageId — a digital file belongs to the one product you upload it against. The upload URL is scoped to a productId, the bytes are stored under that product, and confirming links the file to it.
The flow mirrors the media upload used for design artwork — request a pre-signed URL, PUT the bytes to Google Cloud Storage, then confirm — but it’s a product-scoped endpoint and the confirm step links the file to the product instead of registering a reusable image.
Digital files are size-limited per shop: 25 MB on free plans, up to 1 GB otherwise. The
size you send is enforced both when the URL is issued and by the signed URL itself — sending more bytes than declared fails the upload.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 2). Compute it from whatever you’re uploading:- Node (Buffer):
fileBytes.byteLength(or(await fs.promises.stat("my-ebook.pdf")).sizewithout reading the file) - Browser (
File/Blob):file.size - Shell:
wc -c < my-ebook.pdf
Request a pre-signed upload URL
Call
POST /open-api/v1.0/products/{productId}/digital-files/upload-url with the file’s metadata. The response is the same { uploadUrl, fileUrl } shape as the media flow: a short-lived uploadUrl to PUT the bytes to, and the fileUrl you’ll confirm in the last step.Response
expiresAt is when the pre-signed uploadUrl stops accepting PUTs; request a new one if it lapses.Upload the file bytes
PUT the raw bytes to the uploadUrl. This goes directly to Google Cloud Storage, not to Fourthwall — do not send your Fourthwall credentials with it.The URL is signed with the same two conditions as the media upload, and missing either fails with 403 SignatureDoesNotMatch:Content-Type— must equal thecontentTypeyou sent in step 1 (here,application/pdf).x-goog-content-length-range: 0,<size>— must use the samesize(byte count) you sent in step 1. Reuse the exact value; don’t recompute it a different way.
Confirm the upload
Link the uploaded file to the product with
POST /open-api/v1.0/products/{productId}/digital-files. Pass the fileUrl from step 1 and the fileName buyers will see. The response is the full, updated product.Attach product images
Product images are the showcase thumbnails shown on the storefront — separate from the downloadable files above. They are not uploaded through the digital-files endpoint. Instead, upload the image through the shop-wide media library (POST /open-api/v1.0/media/upload-url, then PUT the bytes — exactly as in Create design products), then attach the resulting URL to the product by its pixel dimensions:
cURL
fileUrl you uploaded as url; width and height are the image’s pixel dimensions.
Next steps
Create a product reference
Full request and response schema for
POST /products.Digital files
Upload and confirm the downloadable files customers receive.
Attach product images
Add showcase images to a digital product.
Create design products
Render your artwork onto tees, mugs, and more.