GraphQL Queries (Read)

Fetch data with type-safe GraphQL queries

5 min read
Print this section

The GraphQL endpoint at /api/v1/graphql exposes 16 read queries: whoami, workOrders, workOrder(id | reference), assets, asset(id), assetDowntimes, meters(assetId), parts (with lowStock filter), part (by id or barcode), stockMovements, floorPlans(locationId), locations, vendors, customers, purchaseOrders, purchaseOrder(id | reference | erpReference). Every list can be paged to the end with limit (1-200) plus offset — except stockMovements, which pages with afterId.

Endpoint

POST https://freemaint.com/api/v1/graphql with Content-Type: application/json. Each query consumes 1 from your daily quota.

Example: list work orders

query { workOrders(limit: 10, status: "OPEN") { id title priority status assetId assetName locationId locationName dueDate } } Returns up to 200 rows; the default limit is 50.

Fetch one part (by id or barcode)

Fetch a single part by id or barcode, with part(id: N) or part(barcode: "CODE"). barcode matches the barcode, the QR code, the part number and the reference (case-insensitive, active parts only) — the same matching the in-app scanner uses — and returns null when nothing matches. Example: query { part(barcode: "ABC-123") { id name description partNumber quantity minQuantity maxStockLevel unitOfMeasure imageUrl area location { name } vendor { name website } } } The part also returns description, minQuantity, maxStockLevel, imageUrl and the nested location and vendor — enough to fill a kiosk item screen in a single query. It also matches your own customReference, so an integration can find a part by the code it carries in your own system.

Available filters

  • workOrders(limit, offset, status, updatedSince) — newest first; page with limit (1-200, default 50) plus offset; status string filter; updatedSince returns only work orders modified since that moment; work orders in the recycle bin are never returned
  • workOrder(id:) / workOrder(reference:) — one work order, found by its id or by the reference your team quotes (WO-2026-11-016, case-insensitive); pass exactly one. Every work order also returns assetName and locationName, the names a form or a permit prints
  • assets(limit, offset, updatedSince) — newest first; page with limit (1-200, default 50) plus offset; updatedSince returns only assets modified since that moment
  • assetDowntimes(assetId, openOnly, since, limit, offset) — machine stops, newest first; page with limit (1-200, default 50) plus offset; openOnly=true returns stops that have not ended yet; since (ISO 8601) returns stops that STARTED at or after a timestamp, which is the cheap way to catch up after a missed delivery
  • parts(limit, offset, lowStock, updatedSince) — page with limit (1-200) plus offset; updatedSince returns only parts modified since that moment; lowStock=true returns only stocked items at or below minQuantity
  • locations, vendors, customers (limit, offset, updatedSince) — ordered by name; page with limit (1-200, default 200) plus offset; updatedSince returns only rows modified since that moment
  • part(id, barcode) — single-part lookup; barcode matches barcode, QR code, part number, reference and custom reference, ideal for scanners
  • floorPlans(locationId) — floor plans of a location, with their markers (percentage x/y coordinates); lets a kiosk render where a part is stored
  • meters(assetId, limit, offset) — meters (running hours, counters, odometers, gauges), newest first; page with limit (1-200, default 50) plus offset; assetId narrows to one machine; lastReadingValue and lastReadingDate give the latest reading
  • purchaseOrders(limit, offset, status, vendorId, updatedSince) — purchase orders with their lines (each with receivedQuantity), their deliveries (receipts) and vendor, newest first; page with limit (1-200, default 50) plus offset; status is one of PENDING, APPROVED, ORDERED, PARTIALLY_RECEIVED, RECEIVED, CANCELLED; updatedSince returns only orders modified since that moment
  • purchaseOrder(id, reference, erpReference) — one purchase order, found by its id, its FreeMaint reference (PO-12) or the erpReference your ERP wrote back; pass exactly one
  • stockMovements(limit, afterId, since, partId, workOrderId, type) — the stock ledger, oldest first; page with limit (1-200, default 50) and afterId: pass the id of the last movement you received to get the next page, which stays exact while new movements are being written; since (ISO 8601) starts from a date; type is one of ADJUSTMENT, PURCHASE, WORK_ORDER, TRANSFER, RETURN, SCRAP, INITIAL, CORRECTION, INSPECTION

Schema introspection

Introspection is enabled. To explore the full schema interactively — every query, mutation and input type with its fields — point a desktop GraphQL client (Altair, Insomnia or Postman) at POST /api/v1/graphql with your Bearer token. Browser-hosted explorers such as Apollo Sandbox or online GraphiQL are refused by our CORS policy.

Tip

Combine several queries in one request: { workOrders(limit:5){ id } assets(limit:5){ id } } — it counts as a single quota hit.

Tip

Meter custom fields: meters { id name customFields { name label fieldType value } } returns one entry per field defined for meters, in display order; value is text, or null when that meter has no value. Values are read-only through the API.

Was this page helpful?