Skip to content

REST API ​

Read your customers, orders and inventory, create orders, and advance an order's stage, over HTTPS with a bearer token. Everything the API returns belongs to the workspace the token was created in.

Plan requirement

The API is included on the Premium and Enterprise plans. The plan is checked on every request, so a downgrade stops access immediately, even for existing tokens.

Common Uses ​

WantUse
Push orders from your own websitePOST /v1/orders
Advance stages from a warehouse systemPOST /v1/orders/{order}/advance
Stock levels on another siteGET /v1/inventory
Look up a customer or an order from your own systemGET /v1/customers/{id} and GET /v1/orders/{order}
React to what happens in the shopWebhook events

For anything event driven, subscribe to webhooks. Polling /v1/orders every minute uses your rate limit and still tells you late.

Base URL and Authentication ​

https://yourshop.printersfriend.com/api/v1

Create a token under Insight, then API tokens, and pass it as a bearer token:

bash
curl -H "Authorization: Bearer {token}" \
     -H "Accept: application/json" \
     https://yourshop.printersfriend.com/api/v1/me

The API tokens page listing each token with its name and expiryInsight, then API tokens. Every token shows the date it expires.

The API tokens page after Create token, with the Token created notice and the one-time Your new token box above the token listThe token is shown once, under Your new token, with the notice "Token created. Copy it now, it will not be shown again." Copy it before leaving the page.

Every request is checked for a valid token, an active user, the workspace the token belongs to, and whether the plan includes the API. Tokens expire after 365 days by default; the API tokens page shows the date next to each one.

Rate Limits ​

Endpoint groupLimit
Reads60 requests per minute
Writes20 requests per minute

Keyed per user. A request over the limit answers 429; wait before retrying.

Endpoints ​

MethodPathPurpose
GET/v1/meThe authenticated user: id, name, email
GET/v1/customersList customers
GET/v1/customers/{id}One customer, with contacts
GET/v1/ordersList orders
GET/v1/orders/{order}One order, with lines, stage history, invoices and artwork
POST/v1/ordersCreate an order
POST/v1/orders/{order}/advanceAdvance an order's stage
GET/v1/inventoryList SKUs with stock

{id} and {order} are the numeric ids the list and create responses return. Document numbers such as ORD-2026-0001 are not accepted in a path.

GET /v1/customers ​

Query parameterEffect
searchCase-insensitive name match

Paginated, 50 per page. Each row:

json
{
  "id": 1,
  "name": "Northside Football Club",
  "slug": "northside-fc",
  "price_list": "Club rate",
  "discount": "12.00",
  "orders_count": 4,
  "open_orders": 2
}

GET /v1/customers/ ​

Adds lifetime value, payment terms, default carrier, the price list and contacts:

json
{
  "id": 1,
  "name": "Northside Football Club",
  "slug": "northside-fc",
  "lifetime_value_cents": 924000,
  "price_list": { "name": "Club rate", "discount_percent": "12.00" },
  "payment_terms": "net_30",
  "default_carrier": "Australia Post",
  "contacts": [
    { "name": "Megan Cole", "email": "megan@northsidefc.au", "phone": "+61408221559", "is_primary": true }
  ]
}

GET /v1/orders ​

Query parameterEffect
stageFilter by stage code, for example in_production
customerFilter by customer slug

Paginated, 50 per page. Each row:

json
{
  "id": 12,
  "number": "ORD-2026-0012",
  "stage": "in_production",
  "substage": "Press 2",
  "due_by": "2026-10-20T00:00:00+00:00",
  "dispatched_at": null,
  "carrier": null,
  "tracking_number": null,
  "totals": { "subtotal_cents": 100000, "tax_cents": 10000, "total_cents": 110000, "currency": "AUD" },
  "customer": { "id": 1, "name": "Northside Football Club", "slug": "northside-fc" },
  "lines": [
    { "description": "Gildan 5000 black L, front print 1 colour", "quantity": 120, "unit_price_cents": 833, "line_total_cents": 100000 }
  ]
}

GET /v1/orders/ ​

The same shape plus stage_history (each move with from, to and at), invoices (number, status, total) and artwork.

POST /v1/orders ​

json
{
  "customer_id": 1,
  "due_by": "2026-10-20",
  "notes": "Rush job, confirmed with Megan",
  "lines": [
    { "description": "Gildan 5000 black L, front print 1 colour", "quantity": 120, "unit_price_cents": 833 }
  ]
}
FieldRules
customer_idRequired. An existing customer id
linesRequired, at least one
lines[].descriptionRequired, up to 255 characters
lines[].quantityRequired, 1 to 10,000
lines[].unit_price_centsRequired, 0 or more
due_byOptional date
notesOptional, up to 2,000 characters, stored as internal notes

The order is created in the Artwork stage with the next order number, and tax is applied from your tax scheme.

API orders are priced by you

unit_price_cents is taken as given. The pricing rules that price a quote built in the workspace do not re-price an API line. For engine pricing, build a quote in the workspace and convert it; use the API for orders whose prices the calling system has already decided.

A create that would exceed your plan's open order limit answers 422 with the reason in message.

POST /v1/orders/{order}/advance ​

json
{ "to_stage": "in_production" }

to_stage is one of artwork, print_queue, in_production, qc_pack or dispatched. Cancelling is not available through the API. The move fires the same side effects as the workspace: customer messages, stock consumption, the invoice on dispatch, outbound webhooks and stage history. A move the workspace would refuse answers 422 with the reason.

GET /v1/inventory ​

Query parameterEffect
lowOnly SKUs at or under their reorder point
searchCase-insensitive code match

Paginated, 100 per page:

json
{
  "code": "GIL-5000-BLK-L",
  "style": "5000 Heavy Cotton Tee",
  "brand": "Gildan",
  "colour": "Black",
  "colour_hex": "#000000",
  "size": "L",
  "on_hand": 145,
  "reserved": 24,
  "available": 121,
  "reorder_point": 60,
  "status": "ok"
}

Errors ​

CodeMeaning
401Missing, invalid or expired token
403The user behind the token has been deactivated
404Not found, or belongs to another workspace
422Validation failed, a plan limit was hit, or the plan does not include the API. Read message
429Rate limited. Back off
  • API tokens: create and revoke tokens, and the one year expiry
  • Webhook events: the five signed events and how to verify a delivery
  • Plans and limits: which plans include the API, and the open order limit a create counts against

Printer's Friend - software for apparel print shops