/v1/printers/{id}/snapshot
Get latest camera snapshot URL
Returns a short-lived signed URL for the most recent camera snapshot Fuse uploaded for this printer. Use it to embed the latest frame anywhere — dashboards, status pages, Slack unfurls, alert emails — without going through the cloud app.
Snapshots are captured by Fuse on a printing-aware cadence:
- ~30 seconds while the printer is actively printing
- ~10 minutes while the printer is idle
- Not at all while the printer is offline or for printer models without a camera (Klipper, PrusaLink, etc.)
The URL is valid for 60 minutes. After that, call this endpoint again to mint a fresh one.
The endpoint signs the URL based only on the bucket path — it does not check whether a snapshot has actually been uploaded yet. If no snapshot exists (brand-new pairing, snapshots disabled for the store, the printer model has no camera, or the printer has been offline since pairing), this endpoint still returns 200 with a URL, and the URL itself returns 404 from Firebase Storage when fetched. Treat a 404 on the URL as "no snapshot available yet," not an error.
To know when a fresh snapshot is available, watch data.camera.lastSnapshotAt on the printer's stat object. Fuse updates this to the upload time on every successful snapshot, so a change in that timestamp is your cue to re-mint the URL or re-fetch the JPEG. Related fields in the same data.camera namespace tell you whether snapshots are even flowing (snapshotsAvailable) and the expected cadence (snapshotCadenceMs).
Prefer MQTT over polling. Printer stats are published to your MQTT broker in real time, so you'll see lastSnapshotAt change the moment Fuse uploads — no polling loop needed. The REST equivalents (GET /v1/printers/stats, GET /v1/printers/stats/{ids}) are available as a fallback but always lag the MQTT stream by your polling interval. Subscribe to the printer-stats topic and treat REST as a backstop for clients that can't hold a long-lived connection.
Path Parameters
Response Schema
Example Response
{
"url": "string",
"expiresAt": 1
}