-
Notifications
You must be signed in to change notification settings - Fork 0
Grocy Integration
Print product, storage, and chore labels from Grocy — both interactively and automatically when Grocy triggers a print.
Status: design specification. Implementation tracked in issue #16.
Grocy supports both pull and push:
- Pull: open the hub UI, scan a product barcode in the Grocy tab, label is printed
- Push: Grocy sends a label-print webhook to the hub when you click a print action in Grocy → label prints automatically
PULL MODE PUSH MODE
───────── ─────────
You / phone Hub Grocy Grocy Hub Printer
───────────── ─── ───── ───── ─── ───────
1. Hub UI ────────►
2. Switch to Grocy tab
3. Scan barcode ──► /api/lookup/grocy/<barcode>
─────► GET /api/objects/products
?query=barcode
◄───── product
◄── LabelData
4. Click Print ───► /api/print/<printer>
1. User clicks a print action in Grocy
2. Grocy → POST hub webhook ──► /api/webhook/grocy
──► render layout + queue + print
──► 200 OK
Grocy ships with label printing disabled by default. You have to enable the feature flag in your data/config.php:
Setting('FEATURE_FLAG_LABEL_PRINTING', true);After restart, the Print label action appears on supported entities (products, stock entries, batteries, etc.) and on the External services settings page.
If the print action isn't visible in your Grocy, check the feature flag. The hub's webhook endpoint won't be called until Grocy itself believes label printing is on.
Per ADR 0012, every label is rendered through a layout — a saved recipe. Choose a default per (integration, tape_mm), override per print job if needed.
Available Grocy fields you can put on a layout:
| Field path | Example value | Source |
|---|---|---|
title |
"Tomatoes (canned)" |
product name
|
primary_id |
"4006381333931" |
product barcode (or product ID if no barcode) |
qr_payload |
https://<your-host>/product/<id> |
hub-built URL |
secondary[0] |
best-before date | from stock entry |
secondary[1] |
location name | from stock |
extras.unit |
unit of measure | product unit |
extras.amount |
stock amount | from stock |
extras.due_date |
best-before date | parsed |
Seed layouts shipped:
-
grocy-product-12mm(default for 12mm) — QR + name + barcode -
grocy-product-24mm(default for 24mm) — QR + name + barcode + best-before -
grocy-location-12mm— QR + location name (for storage labels) -
grocy-location-24mm— QR + location name + description
Create your own via POST /api/layouts — see the API reference at /redoc on a running hub.
In Grocy:
-
Manage API keys (
/api/manageapikeys) - Click Add → name it
label-printer-hub - Copy the key
In .env:
GROCY_URL=https://grocy.example.com
GROCY_API_KEY=<your-key>Restart backend.
Hub UI → switch to Grocy tab → scan a product barcode → see preview in 1-2 s.
This adds automatic printing triggered from Grocy.
The hub uses WEBHOOK_API_KEY (already set in your .env if you followed Getting Started). Make sure it's a strong random value:
openssl rand -hex 32In Grocy → Settings → External services → Label printer (only visible when FEATURE_FLAG_LABEL_PRINTING=true):
| Field | Value |
|---|---|
| Label printer webhook URL | https://<your-host>/api/webhook/grocy |
| Label printer params | { "X-API-Key": "<your-WEBHOOK_API_KEY>" } |
| Run server | (leave empty) |
Save.
Open any product in Grocy → click Print label. The hub UI should show a new job in the printer's queue within 1-2 s, then print and announce completion via SSE / browser notification.
By default the hub picks the integration's default layout for the tape size in DEFAULT_TAPE_PT_SERIES / DEFAULT_TAPE_QL_SERIES. To override per-print, the webhook payload may include a layout_id field:
{
"product_id": 42,
"layout_id": "grocy-product-with-best-before-24mm"
}Whether you can add this field from Grocy depends on Grocy's webhook payload customisation — at the time of writing Grocy sends a fixed payload. The hub-side default-layout flow handles this for you.
- Grocy must have
FEATURE_FLAG_LABEL_PRINTING=true(Grocy default is off) - Bulk-print of all products — out of scope for MVP
- Grocy doesn't expose tape size in the webhook — the hub uses your default tape size from
.env
| Symptom | Likely cause | Fix |
|---|---|---|
| Print label action missing in Grocy | Feature flag not set | Add Setting('FEATURE_FLAG_LABEL_PRINTING', true); to Grocy data/config.php and restart Grocy |
| 401 on webhook | API key mismatch | Verify X-API-Key in Grocy matches WEBHOOK_API_KEY in hub .env
|
| Webhook 200 but nothing printed | Job queued but worker stuck | Check printer status page; ensure printer reachable |
| Hub never receives the webhook | Grocy can't reach the hub URL | From the Grocy host: curl https://<your-host>/healthz
|
| Wrong layout chosen | Default doesn't match the product type | Set a different layout as default for (grocy, <tape_mm>) via the hub UI / API |
| Webhook URL has SSO wall | Pangolin/Authelia is blocking it | The webhook subroute (/api/webhook/) must bypass auth — see compose.traefik.yml / compose.pangolin.yml for the configured exception |
Getting Started
Integrations
Workflows
Help
Repo