Topolo Docs Topolo Platform
Open workspace

Update QR code

Updates supported fields on the selected code and its redirect/design cache. A destination change affects existing printed redirect codes. The slug is set at creation and is not an update input. Basic codes ignore name, category and status updates; usage limits and validity windows apply only to premium redirect codes. Static and redirect QR types cannot be converted in place. Verify returned fields rather than assuming every supplied field changed.

Outcome

Updates supported fields on the selected code and its redirect/design cache. A destination change affects existing printed redirect codes. The slug is set at creation and is not an update input. Basic codes ignore name, category and status updates; usage limits and validity windows apply only to premium redirect codes. Static and redirect QR types cannot be converted in place. Verify returned fields rather than assuming every supplied field changed.

Before you start

  • Verify identity, environment and the intended organization before discovery.
  • Discover the published codes:write permission and the target policy.
  • Select an accessible canonical Auth workspace and set WORKSPACE_ID to its returned id. Workspace binding is separate from input.
  • Review and confirm the exact unchanged plan before execution. Example identifiers grant no live authority.

Discover the target

topolo whoami --json
topolo workspaces list topolo-quro --json
topolo actions get app_topolo_quro.qurocodes.update --detail --json
  • id_or_slug: Exact id converted to a string, or exact slug. Numeric strings are interpreted as ids; a human display name is not an identifier.
  • status_id: Status id discovered through metadata.get with type=statuses.
  • category_id: Category id discovered through metadata.get with type=categories.
  • series_id: Series id from series.list, or null when allowed to detach a code. Series membership does not determine workspace access.

Request

PUT /qurocodes/{id_or_slug}

Inspect parameters and test this action.

Input fields

FieldRequiredMeaning
id_or_slugYesExact id converted to a string, or exact slug. Numeric strings are interpreted as ids; a human display name is not an identifier.
urlNoDestination URL. Creating or changing it stores a redirect target; separately verify reachability and printed-code behavior.
status_idNoStatus id discovered through metadata.get with type=statuses.
category_idNoCategory id discovered through metadata.get with type=categories.
series_idNoSeries id from series.list, or null when allowed to detach a code. Series membership does not determine workspace access.
nameNoHuman label for the code or series. Retain the returned identity separately; names need not be unique.
max_usageNoPositive scan threshold for a code; null clears it where the update schema permits. Verify the returned value and scan policy separately.
valid_fromNoStart of a code validity window, or null to clear it where permitted by the update schema.
valid_toNoEnd of a code validity window, or null to clear it where permitted by the update schema.
designNoDiscriminated plain/custom/brand design. Plain uses defaults; custom accepts colors and finder/module styles; Brand requires an immutable published kit bound to the workspace. Inspect the returned design and version.

Worked examples

Actual exported Quro Worker with local Miniflare D1/KV and every committed app/analytics migration. Auth, service tokens, Nexus, destination probes and platform archival are synthetic responses; outbound fetch is sealed. Notifications remain in the local outbox. No live redirect propagation, QR scan, destination health, provider delivery, archival or production erasure is established.

Save reviewed input as payload.json, replacing fixture identifiers through discovery.

topolo actions validate app_topolo_quro.qurocodes.update --data @payload.json --json
topolo actions plan app_topolo_quro.qurocodes.update --resource-type workspace --resource-id "$WORKSPACE_ID" --data @payload.json --confirm --json
topolo actions call app_topolo_quro.qurocodes.update --resource-type workspace --resource-id "$WORKSPACE_ID" --data @payload.json --confirm --detail --json

MCP uses the same reviewed input and separately discovered resource binding:

{
  "tool": "topolo_prepare_action",
  "arguments": {
    "actionId": "app_topolo_quro.qurocodes.update",
    "input": {
      "id_or_slug": "1",
      "url": "https://example.com/updated",
      "name": "Updated fixture QR"
    },
    "resourceType": "workspace",
    "resourceId": "ws_quro_fixture",
    "confirm": true
  }
}
{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_quro.qurocodes.update",
    "input": {
      "id_or_slug": "1",
      "url": "https://example.com/updated",
      "name": "Updated fixture QR"
    },
    "resourceType": "workspace",
    "resourceId": "ws_quro_fixture",
    "confirm": true,
    "detail": true
  }
}

Worked response 1 · HTTP 200

Input · payload.json:

{
  "id_or_slug": "1",
  "url": "https://example.com/updated",
  "name": "Updated fixture QR"
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 1,
    "slug": "quro-fixture",
    "url": "https://example.com/updated",
    "status_id": 1,
    "category_id": 1,
    "created_by": "user_quro_fixture",
    "tier": "standard",
    "series_id": 1,
    "organization_id": "org_quro_fixture",
    "workspace_id": "ws_quro_fixture",
    "name": "Updated fixture QR",
    "description": null,
    "max_usage": null,
    "valid_from": null,
    "valid_to": null,
    "created_at": "2026-10-06T11:16:12.268Z",
    "updated_at": "2026-10-06T11:16:12.380Z",
    "deleted_at": null,
    "design_version": 1,
    "design": {
      "version": 1,
      "source": "plain",
      "foreground": "#000000",
      "background": "#ffffff",
      "moduleStyle": "square",
      "finderStyle": "square",
      "brand": null
    },
    "delivery_mode": "redirect",
    "supports_publishing_state": true,
    "supports_tier_selection": true,
    "management_model": "standard"
  }
}

HTTP 200. Read the exact returned identity and compare the edited fields, current slug and design version. Resolve or scan the distributed URL separately.

Worked response 2 · HTTP 400 · No fields to update

Input · payload.json:

{
  "id_or_slug": "1"
}

Captured SDK response:

{
  "success": false,
  "error": "No fields to update"
}

HTTP 400. Correct the reviewed payload using inputSchema and the returned handler message.

Worked response 3 · HTTP 404 · QURO code not found

Input · payload.json:

{
  "id_or_slug": "missing-fixture",
  "name": "Missing fixture"
}

Captured SDK response:

{
  "success": false,
  "error": "QURO code not found"
}

HTTP 404. Discover the exact record id or slug in the same workspace before retrying.

Worked response 4 · HTTP 200

Input · payload.json:

{
  "id_or_slug": "premium-fixture",
  "series_id": 3,
  "name": "Reviewed premium",
  "status_id": 2,
  "category_id": 2,
  "design": {
    "source": "plain"
  }
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 14,
    "slug": "premium-fixture",
    "url": "https://example.com/item/premium",
    "status_id": 2,
    "category_id": 2,
    "created_by": "user_quro_fixture",
    "tier": "premium",
    "series_id": 3,
    "organization_id": "org_quro_fixture",
    "workspace_id": "ws_quro_fixture",
    "name": "Reviewed premium",
    "description": null,
    "max_usage": 10,
    "valid_from": "2020-01-01",
    "valid_to": "2020-12-31",
    "created_at": "2026-10-06T11:16:13.017Z",
    "updated_at": "2026-10-06T11:16:13.041Z",
    "deleted_at": null,
    "design_version": 2,
    "design": {
      "version": 1,
      "source": "plain",
      "foreground": "#000000",
      "background": "#ffffff",
      "moduleStyle": "square",
      "finderStyle": "square",
      "brand": null
    },
    "delivery_mode": "redirect",
    "supports_publishing_state": true,
    "supports_tier_selection": true,
    "management_model": "premium"
  }
}

HTTP 200. Read the exact returned identity and compare the edited fields, current slug and design version. Resolve or scan the distributed URL separately.

Worked response 5 · HTTP 200

Input · payload.json:

{
  "id_or_slug": "14",
  "series_id": null,
  "name": "",
  "max_usage": null,
  "valid_from": null,
  "valid_to": null
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 14,
    "slug": "premium-fixture",
    "url": "https://example.com/item/premium",
    "status_id": 2,
    "category_id": 2,
    "created_by": "user_quro_fixture",
    "tier": "premium",
    "series_id": null,
    "organization_id": "org_quro_fixture",
    "workspace_id": "ws_quro_fixture",
    "name": null,
    "description": null,
    "max_usage": null,
    "valid_from": null,
    "valid_to": null,
    "created_at": "2026-10-06T11:16:13.017Z",
    "updated_at": "2026-10-06T11:16:13.064Z",
    "deleted_at": null,
    "design_version": 2,
    "design": {
      "version": 1,
      "source": "plain",
      "foreground": "#000000",
      "background": "#ffffff",
      "moduleStyle": "square",
      "finderStyle": "square",
      "brand": null
    },
    "delivery_mode": "redirect",
    "supports_publishing_state": true,
    "supports_tier_selection": true,
    "management_model": "premium"
  }
}

HTTP 200. Read the exact returned identity and compare the edited fields, current slug and design version. Resolve or scan the distributed URL separately.

Worked response 6 · HTTP 404 · Series not found

Input · payload.json:

{
  "id_or_slug": "14",
  "series_id": 999999
}

Captured SDK response:

{
  "success": false,
  "error": "Series not found"
}

HTTP 404. Discover the exact record id or slug in the same workspace before retrying.

Worked response 7 · HTTP 400 · Static and redirect QR types cannot be converted in place. Create a new Quro with the target type instead.

Input · payload.json:

{
  "id_or_slug": "14",
  "url": "mailto:operator@example.com"
}

Captured SDK response:

{
  "success": false,
  "error": "Static and redirect QR types cannot be converted in place. Create a new Quro with the target type instead."
}

HTTP 400. Correct the reviewed payload using inputSchema and the returned handler message.

Worked response 8 · HTTP 400 · No fields to update

Input · payload.json:

{
  "id_or_slug": "basic-fixture",
  "name": "Ignored basic",
  "category_id": 2,
  "status_id": 2
}

Captured SDK response:

{
  "success": false,
  "error": "No fields to update"
}

HTTP 400. Correct the reviewed payload using inputSchema and the returned handler message.

Worked response 9 · HTTP 200

Input · payload.json:

{
  "id_or_slug": "15",
  "url": "https://example.com/updated",
  "name": "Ignored basic",
  "category_id": 2,
  "status_id": 2
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 15,
    "slug": "basic-fixture",
    "url": "https://example.com/updated",
    "status_id": 1,
    "category_id": 1,
    "created_by": "user_quro_fixture",
    "tier": "basic",
    "series_id": null,
    "organization_id": "org_quro_fixture",
    "workspace_id": "ws_quro_fixture",
    "name": "Original basic",
    "description": null,
    "max_usage": null,
    "valid_from": null,
    "valid_to": null,
    "created_at": "2026-10-06T11:16:13.109Z",
    "updated_at": "2026-10-06T11:16:13.146Z",
    "deleted_at": null,
    "design_version": 1,
    "design": {
      "version": 1,
      "source": "plain",
      "foreground": "#000000",
      "background": "#ffffff",
      "moduleStyle": "square",
      "finderStyle": "square",
      "brand": null
    },
    "delivery_mode": "redirect",
    "supports_publishing_state": true,
    "supports_tier_selection": true,
    "management_model": "basic"
  }
}

HTTP 200. Read the exact returned identity and compare the edited fields, current slug and design version. Resolve or scan the distributed URL separately.

Worked response 10 · HTTP 400 · Static and redirect QR types cannot be converted in place. Create a new Quro with the target type instead.

Input · payload.json:

{
  "id_or_slug": "16",
  "url": "https://example.com/item/redirect"
}

Captured SDK response:

{
  "success": false,
  "error": "Static and redirect QR types cannot be converted in place. Create a new Quro with the target type instead."
}

HTTP 400. Correct the reviewed payload using inputSchema and the returned handler message.

Worked response 11 · HTTP 200

Input · payload.json:

{
  "id_or_slug": "16",
  "url": "mailto:reviewed@example.com",
  "status_id": 2,
  "name": "Reviewed static"
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 16,
    "slug": "6df2of7g",
    "url": "mailto:reviewed@example.com",
    "status_id": 1,
    "category_id": 1,
    "created_by": "user_quro_fixture",
    "tier": "standard",
    "series_id": null,
    "organization_id": "org_quro_fixture",
    "workspace_id": "ws_quro_fixture",
    "name": "Reviewed static",
    "description": null,
    "max_usage": null,
    "valid_from": null,
    "valid_to": null,
    "created_at": "2026-10-06T11:16:13.167Z",
    "updated_at": "2026-10-06T11:16:13.197Z",
    "deleted_at": null,
    "design_version": 1,
    "design": {
      "version": 1,
      "source": "plain",
      "foreground": "#000000",
      "background": "#ffffff",
      "moduleStyle": "square",
      "finderStyle": "square",
      "brand": null
    },
    "delivery_mode": "static_payload",
    "supports_publishing_state": false,
    "supports_tier_selection": false,
    "management_model": "managed_static_record"
  }
}

HTTP 200. Read the exact returned identity and compare the edited fields, current slug and design version. Resolve or scan the distributed URL separately.

Verify the result

  • Read the exact returned identity and compare the edited fields, current slug and design version. Resolve or scan the distributed URL separately.

Errors and recovery

  • HTTP 400 · http_error: Correct the reviewed payload using inputSchema and the returned handler message.
  • HTTP 404 · http_error: Discover the exact record id or slug in the same workspace before retrying.
  • HTTP 401 · auth_error: Authenticate again in the intended environment and organization.
  • HTTP 403 · action_permission_required: Inspect the actual refusal. The action permission and the verified workspace access are both required; a caller cannot name an ungranted workspace.

Inspect the original handler body as well as the SDK error code. These are observed local refusals, not an exhaustive provider-failure list.

Recovery boundary

Read and retain the reviewed prior destination/design before changing them. Restore approved prior fields with qurocodes.update if appropriate; requests already redirected elsewhere cannot be undone. No fields yields a refusal.

  • Get QR code: Reads one code by exact numeric id or slug within the verified workspace, including its design, scan count and series. Exact reads can return soft-deleted records.

Evidence

Actual exported Quro Worker with local Miniflare D1/KV and every committed app/analytics migration. Auth, service tokens, Nexus, destination probes and platform archival are synthetic responses; outbound fetch is sealed. Notifications remain in the local outbox. No live redirect propagation, QR scan, destination health, provider delivery, archival or production erasure is established.