Versioned, OpenAPI 3.1, rate-limited, signed webhooks. Built for the integrations the apparel industry actually needs.
All API requests use Laravel Sanctum personal access tokens. Create one in Settings → API tokens. Pass it as a bearer token in the Authorization header.
curl https://api.printersfriend.com/v1/me \
-H "Authorization: Bearer pfat_live_abcd1234..."
Tokens can be scoped to a subset of permissions (read-only, customers-only, orders-write). Rotate them any time. Revoking a token takes effect within 60 seconds.
Production: https://api.printersfriend.com/v1. Sandbox: https://sandbox.api.printersfriend.com/v1.
The API is versioned by URL prefix. Breaking changes ship in a new major version (v2) with at least 12 months of overlap. Additive changes (new fields, new endpoints) happen within a version with no notice.
Errors follow the standard Laravel JSON validation format. HTTP status codes match RFC 9110: 400 for malformed input, 401 unauthenticated, 403 forbidden, 404 not found, 422 validation, 429 rate limited, 5xx server.
// 422 example
{
"message": "The given data was invalid.",
"errors": {
"email": ["The email must be a valid email address."]
}
}
List endpoints are paginated with cursor-based pagination. Pass ?cursor=<cursor>&per_page=50. The response includes next_cursor and prev_cursor. Default page size is 25, max 100.
60 requests per minute per token on read endpoints. 20 per minute on write endpoints. Burst of 10. Webhooks and bulk endpoints have separate higher limits documented per endpoint. Hitting a limit returns 429 with Retry-After set in seconds.
List organisations.
| Param | Type | Description |
|---|---|---|
search | string | Filter by name or contact email |
price_list | string | Filter by price list slug |
cursor | string | Pagination cursor |
{
"data": [
{
"id": "org_abc123",
"name": "Bondi Surf Club",
"price_list": "club-rate",
"primary_contact": { "name": "Tess Walker", "email": "tess@bondisurf.au" },
"ytd_spend_cents": 184500
}
],
"next_cursor": "eyJpZCI6Im9yZ19hYmMxMjMifQ"
}
Get a single organisation with contacts, addresses, and pricing rules attached.
List orders with optional stage filter.
| Param | Type | Description |
|---|---|---|
stage | string | artwork, print_queue, in_production, qc_pack, dispatched |
customer_id | string | Filter to one customer |
due_before | iso date | Only orders due before this date |
Get a single order with lines, decoration spec, artwork versions and stage history.
Advance an order to the next production stage. Body: { "to_stage": "in_production" }. Fires order.stage_changed webhook.
List SKUs with live stock. Each SKU has on_hand, reserved, available, incoming, reorder_point.
Create a subscription in the admin (Settings → Webhooks) or via the API. Each subscription has a target URL, an event list, and a per-subscription signing secret.
order.createdorder.stage_changedorder.dispatchedartwork.uploadedartwork.approvedartwork.change_requestedinvoice.issuedinvoice.paidstock.lowquote.acceptedcustomer.createdEvery webhook POST includes:
X-PF-Event: the event nameX-PF-Signature: HMAC-SHA256 of the request body using the subscription's signing secret, prefixed with sha256=User-Agent: PrintersFriend-Webhooks/1.0Verify with:
// Node.js verification
const crypto = require('crypto');
const sig = req.headers['x-pf-signature'];
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(req.rawBody).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).end();
}
If your endpoint returns anything other than 2xx, we retry with exponential backoff: 1m, 5m, 30m, 2h, 12h. After 5 failed attempts we mark the subscription suspended and email the workspace owner. You can replay any failed delivery from the admin UI for 30 days.
Official SDKs (in alphabetical order):
npm install @printersfriend/sdkcomposer require printersfriend/sdkpip install printersfriendgem install printersfriendCommunity SDKs in Go and .NET are linked from the GitHub org. All SDKs are MIT-licensed and follow the same versioning scheme as the API.
API questions go to developers@printersfriend.com with response within 1 business day. Status and incidents live at status.printersfriend.com.