Introduction
Connect a Pengine custom store to any storefront you build.
The Store API is available only for Pengine custom stores. It connects a custom store to any website or application you build. Use it to read products, create orders, and receive webhooks when products or orders change.
In these docs, custom storefront means the website or application you connect to the custom store through the Store API.
It is a REST API over HTTPS. Requests and responses are JSON, and every request is authenticated with the store's API key.
Base URL
https://api.pengine.io/store-api/2026-08/stores/:storeIdThe path includes the API version (2026-08) and your store ID (:storeId). After a version ships,
it does not receive breaking changes. Breaking changes use a new dated version, while existing
versions remain available according to the support policy. See
Versioning.
Authentication
Send the store's API key in the X-API-Key header with every request. The key must belong to the store
ID in the path. Keep it on your server: the key can read every product and create billable orders.
See Authentication to create, store, and rotate a key.
Endpoints
The API exposes products, printable blanks, uploaded artwork, and orders. Products and catalog products are read-only. You can upload artwork and create or read orders. Use the Pengine app to edit, cancel, or hold an order.
There are two ways to order: sell a product you built in advance, or send a custom item assembled at order time from a blank, an artwork and a placement.
See Endpoints for the full list, with fields, filters and status codes.
Webhooks
Pengine sends product and order events to an endpoint you register. Each payload identifies the resource that changed. Fetch the resource through the API to get its current state.
See Webhooks for the events, registration, signature verification and retries.
Conventions
| Convention | What to expect |
|---|---|
| Format | JSON in, JSON out, UTF-8. Send Content-Type: application/json on requests with a body. |
| IDs | Opaque 24-character strings, like saryo4m9p6ki3u1558m6h56j. Store them as text and do not parse them. |
| Timestamps | ISO 8601 in UTC, like 2026-08-19T12:37:20.897Z. |
| Money | Decimal numbers in US dollars, like 279.25. Round to cents before displaying or storing a total. |
| Absent values | An empty field is left out of the response rather than sent as null. Treat missing and empty as the same. |
| Unknown fields | Unrecognized fields in a request body are ignored, not rejected. |
| Lists | Page numbers, not cursors. See Lists. |
| Errors | One envelope for every failure. See Errors. |
| Rate limit | Ten requests at once, then two a second, per store. See Rate limits. |