Artworks
How to upload your artwork and reuse it across orders.
An artwork is an image stored in your Pengine store for use on a custom item. Upload it once, then reference its ID across orders.
Provide an HTTPS URL for the image. Pengine downloads and stores its own copy.
Create an artwork
curl -X POST https://api.pengine.io/store-api/2026-08/stores/$STORE_ID/artworks \
-H "X-API-Key: $PENGINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Northbound logo",
"image": { "url": "https://cdn.example.com/art/northbound.png" }
}'Prop
Type
{
"id": "sm22mjuo3dk36g1ejurbawjx",
"name": "Northbound logo",
"image": {
"id": "gskts87l21rh1g4lsrmqmcuz",
"url": "https://cdn.pengine.io/files/gskts87l21rh1g4lsrmqmcuz/Northbound.png"
},
"createdAt": "2026-08-19T13:02:55.410Z",
"updatedAt": "2026-08-19T13:02:55.410Z"
}Store the returned id and send it as artworkId in a decoration.
Rules for the URL
| Rule | |
|---|---|
| Scheme | HTTPS only. |
| Credentials | The URL must not carry a username or password. |
| Host | Must resolve to a public address. Private ranges and loopback are refused. |
| Redirects | Not followed. Point at the file itself. |
| Formats | PNG and JPEG. |
| Size | Up to 50 MB. |
| Timeout | The download gives up after 30 seconds. |
The URL must be available when you create the artwork. After Pengine stores its copy, the source URL can go offline.
When a create fails
| Message | Cause |
|---|---|
The URL is not a valid URL | It could not be parsed. |
The URL must use HTTPS | Plain HTTP, or another scheme. |
The URL must not carry credentials | A username or password is embedded in the URL. |
The URL host could not be resolved | DNS lookup failed. |
The URL must not point to a private address | The host resolves to a private or reserved address. |
Could not download the artwork image from the URL | The download failed, timed out, was too large, redirected, or was not a PNG or JPEG. |
All of them are 400. Validation failures on name or a missing image come back as the usual array
of messages. See Errors.
Creating an artwork is not idempotent
There is no equivalent of externalOrderId for artworks. Retrying after a timeout can create a
second artwork with a different ID. Store the returned ID and check for it before
re-uploading.
The artwork object
Prop
Type
List artworks
| Parameter | |
|---|---|
sort[name] | asc or desc. |
sort[createdAt] | asc or desc. Defaults to desc, and is always applied last as a tiebreak. |
page, limit | Standard paging. See Lists. |
There are no filters on this endpoint.
curl "https://api.pengine.io/store-api/2026-08/stores/$STORE_ID/artworks?sort[createdAt]=desc&limit=50" \
-H "X-API-Key: $PENGINE_API_KEY"Items are full artwork objects in the standard list envelope.
Get one artwork
curl https://api.pengine.io/store-api/2026-08/stores/$STORE_ID/artworks/sm22mjuo3dk36g1ejurbawjx \
-H "X-API-Key: $PENGINE_API_KEY"An artwork from another store and an ID that does not exist return the same response:
{ "message": "Artwork not found", "error": "Not Found", "statusCode": 404 }Working with artworks
Upload once, use many times. An artwork is not consumed by an order. Reuse the same ID across line items, orders and decoration locations.
Store the ID with your design record. Artwork names are not unique, so do not use them for reconciliation.
Artworks cannot be deleted through this API. Manage them in the Pengine app.