PrinterFlo

Developer documentation

PrinterFlo API reference

The PrinterFlo REST API gives you programmatic access to your shop's jobs, customers, invoices, and payments. It powers our Zapier integration and is available to every PrinterFlo account at no extra cost.

Base URL

https://app.printerflo.com/api/v1

All requests and responses are JSON. All timestamps are ISO-8601 with timezone (e.g. 2026-07-12T09:20:08.548+00:00). Money is in integer cents with a currency field.

Authentication

Create an API key in PrinterFlo under Settings → API & Zapier. Keys look like pfl_live_… and are shown once at creation. Send the key as a bearer token on every request:

curl https://app.printerflo.com/api/v1/me \
  -H "Authorization: Bearer pfl_live_YOUR_KEY"

Missing, unknown, or revoked keys get 401 with { "error": "Invalid or missing API key." }. Every key is scoped to one shop; you only ever see your own data. Keys can be revoked any time from the same settings screen.

Rate limits

120 requests per minute per key. Exceeding it returns 429 with a Retry-After: 60 header — back off and retry.

Common parameters

Endpoints

Method Path Purpose
GET /me Verify a key; returns your shop
GET /jobs List orders & quotes
POST /jobs Create a quote
GET /customers List / search customers
POST /customers Find-or-create a customer
GET /invoices List invoices
GET /payments List payments

GET /me

The cheapest auth check. Returns the shop the key belongs to.

{ "org": { "id": "…", "name": "Demo Shop", "currency": "cad" } }

GET /jobs

Orders and quotes, newest first. Filters: ?kind= (quote or sales_order), ?status= (your shop's own stage names), ?since=, and ?updated_since= (records updated at/after a timestamp — how our Zapier order-status trigger polls).

{
  "jobs": [
    {
      "id": "…",
      "number": 42,
      "title": "Banner 3ft x 6ft",
      "kind": "sales_order",
      "status": "processing",
      "source": "staff",
      "po_number": null,
      "total_cents": 36160,
      "currency": "cad",
      "created_at": "2026-07-12T09:20:08+00:00",
      "updated_at": "2026-07-12T10:27:06+00:00",
      "customer": { "id": "…", "name": "Reid Auto Group", "company": null, "email": "…", "phone": "…" },
      "url": "https://app.printerflo.com/jobs/…"
    }
  ]
}

POST /jobs

Creates a quote — the safe entry point for automations: your shop prices and confirms it before anything is billed or produced. The customer is deduped by email within your shop. Returns 201 with the created job.

POST /api/v1/jobs
{
  "title": "Storefront window decals",        // required
  "description": "From website lead form",     // optional
  "po_number": "PO-1234",                      // optional
  "customer": {
    "name": "Jane Smith",                      // required
    "email": "jane@example.com",               // used for dedupe
    "phone": "555-0101",
    "company": "Smith Realty"
  }
}

GET /customers

Filters: ?email= (exact match, case-insensitive), ?q= (searches name, company, and email), ?since=. Returns id, name, company, email, phone, payment_terms, created_at.

POST /customers

Find-or-create by email: if a customer with the given email exists, it's returned with "existing": true instead of creating a duplicate. Body: name (required), email, phone, company, notes.

{ "customer": { "id": "…", "name": "Jane Smith", … }, "existing": false }

GET /invoices

Filters: ?status=, ?since=. Each invoice includes its totals in cents (subtotal_cents, tax_cents, discount_cents, total_cents, amount_paid_cents), dates (issued_at, due_date, created_at), and the linked job and customer.

GET /payments

Filter: ?since=. Each payment has amount_cents, currency, method (e.g. stripe, cash, cheque, terminal), reference, paid_at, created_at, and the linked job with its customer.

Errors

Questions or a missing endpoint?

Email support@printerflo.com — we typically reply within one business day. Prefer no-code? The same API powers our Zapier integration.