/v1/qr-tags/execute
Run a scanned tag's action
Runs one action from a POST /v1/qr-tags/resolve response, for the same one or two tags. Needs qr.scan, the QR Workflows add-on and the action's own permission (for example printer.control for Pause, printer.edit for Move). Send the choice an action's param asks for in params (see resolve); a missing one is a 400 with code: "param_required". The live state is checked again before anything is sent, so an action that was available at resolve time can still be refused here. A move or swap writes both slots in one transaction: if either write fails, neither slot changes, and the printers are only told about the new filament once both are written. Each action is recorded in the audit log with source mobile_scan (or web for a blank set up with a target) and the caller as the actor. The response carries the tag's refreshed display and its actions evaluated again after this one ran, so a client can redraw without calling resolve (which would count another scan). Live printer status can lag the command by a few seconds. If the printer can't be read back after the action ran, the action still counts as done: tags is empty and actions is left out, so resolve again with refresh: true to redraw.
To set a blank up for a target from a resolve (something with no tag to scan), send the blank's id alone in tagIds with that target and one of the actions that set a blank up. Any other action, or more tags, is a 400; a target that isn't in the store is a 404 with code: "target_not_found". A blank isn't saved until it is set up, so its ID, read from its QR code, has no tag yet: an action that sets a blank up takes one ID with no tag as that blank. Setting it up saves the tag, only when no tag with that ID exists yet. When two phones set up the same blank at once, one wins and the other gets a 409 with code: "tag_already_set_up"; resolve the tag again to see what it became. Registering a spool with a blank (pair.bindBlankAsNewSpool) sets the blank up first, in the same transaction as the new spool, so the phone that loses creates no spool. After a blank is set up the response's tags holds just that tag, as what it is now, with its own actions. Loading a spool that sits in another slot moves it and frees that slot; loading it into the slot it is already in changes nothing and says so. A spool registered with a blank takes the blank's code as its label code; with the Filament Stock spool tracking add-ons it comes out of the filament's bulk stock when bulk holds its weight, and the result message says so.
Errors carry a machine-readable code next to message:
| Status | code | Meaning |
|---|---|---|
403 |
no_permission |
The caller lacks the action's permission. |
404 |
unknown_tag |
A tag ID isn't in this store. An action that sets a blank up takes one ID with no tag, the blank's, so for it this means neither ID has a tag. |
404 |
target_not_found |
The target a blank is being set up for isn't in this store. |
400 |
param_required |
The action needs a choice (a slot, a job, a macro, a weight, ...) and params doesn't carry it. |
400 |
bad_grams |
grams isn't a number from the action's min to 50,000. |
409 |
state_changed |
The printer or slots no longer allow the action (it went offline, finished printing, the slots filled up, ...). message says why. Resolve again. |
409 |
slot_gone |
The picked slot (or printer) is no longer there. Printago never falls back to another slot. Resolve again. |
409 |
tag_revoked, tag_orphaned |
The tag was revoked, or its target was deleted. |
409 |
tag_already_set_up |
Another request set this blank tag up first. Nothing was changed by this one. |
409 |
tag_id_taken |
Another store's tag already has this blank's ID. Print a new blank. |
409 |
idempotency_in_progress |
A request with this Idempotency-Key is still running. |
422 |
action_not_offered |
The action is unknown, runs in the app (printer.open), or isn't one these tags offer: a printer action sent with a slot tag is refused, never run on the slot's printer. |
422 |
idempotency_mismatch |
This Idempotency-Key was already used for a different request. |
Send an Idempotency-Key header (any string up to 128 characters) and reuse it when you retry the same tap. A key that already finished returns its first response without running the action again; a key whose attempt failed is freed so the retry runs. Keys expire after 24 hours. Without the header every call runs the action.
Header Parameters
Request Body
The tag IDs, the action ID and its parameters
Example Request
{
"tagIds": [
"string"
],
"action": "string",
"params": {},
"target": {
"entityType": "printer",
"entityId": "string"
}
}
Examples
Pause a print
POST /v1/qr-tags/execute
Idempotency-Key: 6f1c9a52-0d3e-4a7b-9b8e-3f2d1c0a9e87
{ "tagIds": ["k3q9x2m8v7c1n4b6z0w5y2ta"], "action": "printer.pause" }
{
"action": "printer.pause",
"result": {
"status": "done",
"message": "Pause sent to X1C-01"
},
"tags": [
{
"id": "k3q9x2m8v7c1n4b6z0w5y2ta",
"status": "active",
"entityType": "printer",
"entityId": "p7h2j4k6m8n0q2r4s6t8v0wa",
"label": "X1C-01",
"printer": {
"id": "p7h2j4k6m8n0q2r4s6t8v0wa",
"name": "X1C-01",
"provider": "Bambu",
"state": "Busy",
"statusLabel": "Printing 42%",
"printing": true,
"paused": false,
"progress": 42,
"jobName": "bracket.3mf"
}
}
],
"actions": [
{
"id": "printer.stop",
"label": "Stop",
"kind": "builtin",
"runs": "server",
"permission": "printer.control",
"default": false,
"destructive": true,
"confirm": true,
"confirmMessage": "Stop the print on X1C-01? It can't be resumed.",
"available": true
},
{
"id": "printer.open",
"label": "Open printer",
"kind": "builtin",
"runs": "app",
"permission": "printer.view",
"default": true,
"destructive": false,
"confirm": false,
"available": true
}
]
}
Assign a variant to the slot picked in the sheet
{
"tagIds": [
"u8qaisrqkwr6ib1p1jfjeiov",
"nvioxp9s1d7o3van7wqhkmtp"
],
"action": "pair.assignVariantToPrinter",
"params": {
"amsIndex": 0,
"slotIndex": 1
}
}
{
"action": "pair.assignVariantToPrinter",
"result": {
"status": "done",
"message": "Assigned PLA Matte Ivory White to A1/2 on X1C-01"
},
"tags": [
"…"
],
"actions": [
"…"
]
}
Send the next job
{
"tagIds": [
"u8qaisrqkwr6ib1p1jfjeiov"
],
"action": "printer.sendJob",
"params": {
"jobId": "tbb93f18fxpfa86eerjcnnq5"
}
}
{
"action": "printer.sendJob",
"result": {
"status": "done",
"message": "Sent Single Plate Sample to X1C-01"
},
"tags": [
"…"
],
"actions": [
"…"
]
}
Register a spool with a blank tag
POST /v1/qr-tags/execute
Idempotency-Key: 3c0f2e9a1b7d4e6f8a2c5b9d1e3f7a0c
{ "tagIds": ["v61yt345k7x9a5eaw1tuw1vy", "r4vydpzb0g2gq0a3yq8kkxjm"], "action": "pair.bindBlankAsNewSpool", "params": { "grams": 1000 } }
{
"action": "pair.bindBlankAsNewSpool",
"result": {
"status": "done",
"message": "Registered a spool of PLA Basic Jade White with 1,000 g"
},
"tags": [
{
"id": "v61yt345k7x9a5eaw1tuw1vy",
"status": "active",
"entityType": "material_instance",
"entityId": "z5y7mec4haa3tnu7xzqbwamd",
"label": "PLA Basic · Jade White",
"printer": null,
"spool": {
"id": "z5y7mec4haa3tnu7xzqbwamd",
"remainingGrams": 1000,
"nominalGrams": null,
"labelCode": "Q9FJ-2JA4",
"empty": false,
"location": null,
"variant": {
"name": "Jade White",
"materialName": "PLA Basic",
"…": "…"
}
}
}
],
"actions": [
"…"
]
}
Set a blank up for a printer from its web page
POST /v1/qr-tags/execute
Idempotency-Key: 9d1e3f7a0c3c0f2e9a1b7d4e6f8a2c5b
{ "tagIds": ["qvq9w2cmd8j16ijv05rjgq5z"], "action": "pair.bindBlankToPrinter", "target": { "entityType": "printer", "entityId": "p7h2j4k6m8n0q2r4s6t8v0wa" } }
{
"action": "pair.bindBlankToPrinter",
"result": {
"status": "done",
"message": "Set up as the tag for X1C-01"
},
"tags": [
{
"id": "qvq9w2cmd8j16ijv05rjgq5z",
"status": "active",
"entityType": "printer",
"entityId": "p7h2j4k6m8n0q2r4s6t8v0wa",
"label": "X1C-01",
"printer": {
"…": "…"
}
}
],
"actions": [
"…"
]
}
The same blank set up by another phone a moment earlier
{
"statusCode": 409,
"code": "tag_already_set_up",
"message": "This tag was set up a moment ago. Scan it again to see what it's for."
}
A slot the printer no longer has
{
"tagIds": [
"u8qaisrqkwr6ib1p1jfjeiov",
"nvioxp9s1d7o3van7wqhkmtp"
],
"action": "pair.assignVariantToPrinter",
"params": {
"amsIndex": 1,
"slotIndex": 0
}
}
{
"statusCode": 409,
"code": "slot_gone",
"message": "X1C-01 doesn't have slot A2/1 anymore"
}
The printer changed since the scan
{
"tagIds": [
"k3q9x2m8v7c1n4b6z0w5y2ta"
],
"action": "printer.pause"
}
{
"statusCode": 409,
"code": "state_changed",
"message": "Nothing is printing"
}
Response Schema
Example Response
{
"action": "printer.confirmReady",
"result": {
"status": "done",
"message": "string"
},
"tags": [
{
"id": "string",
"status": "blank",
"entityType": "blank",
"entityId": "string",
"label": "string",
"printer": {
"id": "string",
"name": "string",
"provider": "string",
"state": "Offline",
"statusLabel": "string",
"statusUnknown": true,
"printing": true,
"paused": true,
"progress": 1,
"jobName": "string"
},
"slot": {
"amsIndex": 1,
"slotIndex": 1,
"ref": "string",
"exists": true,
"assigned": {
"name": "string",
"brand": "string",
"color": "string",
"instanceId": "string",
"remainingGrams": 1
},
"loaded": true
},
"variant": {
"id": "string",
"name": "string",
"materialId": "string",
"materialName": "string",
"brand": "string",
"type": "string",
"color": "string"
},
"spool": {
"id": "string",
"variant": {
"id": "string",
"name": "string",
"materialId": "string",
"materialName": "string",
"brand": "string",
"type": "string",
"color": "string"
},
"remainingGrams": 1,
"nominalGrams": 1,
"labelCode": "string",
"empty": true,
"location": {
"printerId": "string",
"printerName": "string",
"amsIndex": 1,
"slotIndex": 1,
"ref": "string"
}
},
"blank": {
"code": "string"
}
}
],
"actions": [
{
"id": "printer.confirmReady",
"label": "string",
"kind": "webhook",
"runs": "server",
"permission": "organization.owner",
"default": true,
"destructive": true,
"confirm": true,
"confirmMessage": "string",
"available": true,
"reasonCode": "printing",
"reason": "string",
"detail": "string",
"param": {
"kind": "slot",
"options": [
{
"amsIndex": 1,
"slotIndex": 1,
"ref": "string",
"group": "string",
"assigned": {
"name": "string",
"brand": "string",
"color": "string",
"instanceId": "string",
"remainingGrams": 1
},
"loaded": true
}
],
"default": {
"amsIndex": 1,
"slotIndex": 1
}
}
}
]
}