Pengine Store API
Guides

Errors

What a failure looks like, and which calls are safe to retry.

Most failures return the same three-field JSON envelope.

404 Not Found
{
  "message": "Order not found",
  "error": "Not Found",
  "statusCode": 404
}
FieldMeaning
messageWhat went wrong, written for a human. A string, or an array of strings when several fields failed validation at once.
errorThe name of the status code.
statusCodeThe HTTP status code, repeated in the response body.

Branch on the status code, not the message

Message text is not part of the API contract and can change without a new version. Use statusCode for programmatic error handling.

Rate-limit responses are the exception: they include statusCode and message but omit error.

Validation failures

When a request body or a query string does not validate, message is an array with one entry per problem, naming the field path.

400 Bad Request
{
  "message": [
    "lineItems.0.quantity must not be less than 1",
    "shippingAddress.lastName should not be empty",
    "shippingAddress.address should not be empty"
  ],
  "error": "Bad Request",
  "statusCode": 400
}

Query parameters are validated the same way:

400 Bad Request
{
  "message": ["limit must not be greater than 100"],
  "error": "Bad Request",
  "statusCode": 400
}

Unrecognized fields are ignored rather than rejected. The API does not store them.

Status codes

CodeMeansWhat to do
400The request is malformed, fails validation, or asks for something that cannot be ordered.Fix the request. Retrying it unchanged will fail again.
401The key is missing or wrong for this store, or the store is inactive.Check the key and store ID. Do not retry automatically.
404No such route, or no such resource in this store.Check the path and resource ID. Resources from another store also return 404.
409An order already exists with this externalOrderId.Fetch the existing order instead of creating another.
429You have gone past the rate limit.Wait for the Retry-After header, then retry. See Rate limits.
500Something broke on our side.Retry with backoff. If it persists, contact support with the time and the path.

The API does not return 403. Resources outside the authenticated store return 404.

Requests that never matched a route

A path that is not served, including a version that does not exist, is a plain 404:

404 Not Found
{
  "message": "Cannot GET /store-api/2025-01/stores/ovy3u54frpsl4sd963aja0h1/products",
  "error": "Not Found",
  "statusCode": 404
}

If a whole integration starts returning this, check the version segment in your base URL first.

What is safe to retry

GET requests are safe to retry after a timeout, 429, or 500. Apply exponential backoff and honor the Retry-After header for 429 responses.

An order request that times out may still have succeeded. Send externalOrderId with every order to make retries safe:

  • The retry succeeds with 201. The first attempt never landed.
  • The retry fails with 409. The first attempt did land, and the order exists.

After a 409, find the order you already have rather than creating another:

curl "https://api.pengine.io/store-api/2026-08/stores/$STORE_ID/orders?filter[externalOrderId]=web-10482" \
  -H "X-API-Key: $PENGINE_API_KEY"

Without an external order ID there is no protection

Without externalOrderId, each request creates a distinct order. A retry after a timeout can create and bill the same order twice. Always use your own order number as the external ID.

On this page