Topolo Docs Topolo Platform
Open workspace

Create QR series

Persists a named series, applying an exact supported template and its dashboard defaults when supplied.

Outcome

Persists a named series, applying an exact supported template and its dashboard defaults when supplied.

Before you start

  • Verify identity, environment and the intended organization before discovery.
  • Discover the published series: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.series.create --detail --json
  • templateId: Exact id from series.templates.list. An unsupported template is refused before series creation.

Request

POST /series

Inspect parameters and test this action.

Input fields

FieldRequiredMeaning
nameNoHuman label for the code or series. Retain the returned identity separately; names need not be unique.
descriptionNoSeries description stored alongside its name.
statusNoDeclared series creation status, or series-list status filter. Completing a series does not disable its codes.
templateIdNoExact id from series.templates.list. An unsupported template is refused before series creation.

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.series.create --data @payload.json --json
topolo actions plan app_topolo_quro.series.create --resource-type workspace --resource-id "$WORKSPACE_ID" --data @payload.json --confirm --json
topolo actions call app_topolo_quro.series.create --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.series.create",
    "input": {
      "name": "Fixture campaign",
      "description": "Controlled documentation codes"
    },
    "resourceType": "workspace",
    "resourceId": "ws_quro_fixture",
    "confirm": true
  }
}
{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_quro.series.create",
    "input": {
      "name": "Fixture campaign",
      "description": "Controlled documentation codes"
    },
    "resourceType": "workspace",
    "resourceId": "ws_quro_fixture",
    "confirm": true,
    "detail": true
  }
}

Worked response 1 · HTTP 400 · Series name is required

Input · payload.json:

{}

Captured SDK response:

{
  "success": false,
  "error": "Series name is required"
}

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

Worked response 2 · HTTP 404 · Template not found

Input · payload.json:

{
  "templateId": "missing-fixture"
}

Captured SDK response:

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

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

Worked response 3 · HTTP 201

Input · payload.json:

{
  "name": "Fixture campaign",
  "description": "Controlled documentation codes"
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 1,
    "user_id": "user_quro_fixture",
    "name": "Fixture campaign",
    "description": "Controlled documentation codes",
    "status": "active",
    "created_at": "2026-10-06T11:16:12.166Z",
    "updated_at": "2026-10-06T11:16:12.166Z",
    "template_id": null,
    "dashboard_state": null,
    "counts": {
      "total": 0,
      "basic": 0,
      "standard": 0,
      "premium": 0
    }
  }
}

HTTP 201. Discover the returned series id through series.list and compare name, template_id, status and dashboard. Keep the id for subsequent series actions.

Worked response 4 · HTTP 201

Input · payload.json:

{
  "templateId": "marathon-runners",
  "status": "paused"
}

Captured SDK response:

{
  "success": true,
  "data": {
    "id": 3,
    "user_id": "user_quro_fixture",
    "name": "Marathon Runner Tracking",
    "description": "Track marathon participants with individual QR codes for timing, results, and spectator updates",
    "status": "paused",
    "created_at": "2026-10-06T11:16:12.855Z",
    "updated_at": "2026-10-06T11:16:12.855Z",
    "template_id": "marathon-runners",
    "dashboard_state": {
      "layout": "marathon",
      "title": "Marathon Runner Tracking",
      "metrics": [
        {
          "id": "total_participants",
          "label": "Total Participants",
          "value": 0,
          "icon": "🏃‍♂️",
          "type": "counter"
        },
        {
          "id": "active_runners",
          "label": "Active Runners",
          "value": 0,
          "icon": "⚡",
          "type": "counter",
          "color": "success"
        },
        {
          "id": "finished_runners",
          "label": "Finished",
          "value": 0,
          "icon": "🏁",
          "type": "counter",
          "color": "primary"
        },
        {
          "id": "avg_pace",
          "label": "Average Pace",
          "value": "0:00/km",
          "icon": "⏱️",
          "type": "text"
        }
      ],
      "sections": [
        {
          "id": "live_tracking",
          "title": "Live Tracking",
          "type": "timeline",
          "data": [
            {
              "id": "sample_1",
              "timestamp": "2026-10-06T11:16:11.435Z",
              "runner": "Sample Runner #001",
              "checkpoint": "Start Line",
              "time": "00:00:00",
              "status": "started"
            }
          ]
        },
        {
          "id": "leaderboard",
          "title": "Current Leaderboard",
          "type": "table",
          "headers": [
            "Position",
            "Runner",
            "Time",
            "Pace"
          ],
          "data": [
            [
              "1",
              "Sample Runner #001",
              "00:00:00",
              "0:00/km"
            ]
          ]
        },
        {
          "id": "checkpoints",
          "title": "Checkpoint Status",
          "type": "progress",
          "data": [
            {
              "name": "Start Line",
              "completed": 0,
              "total": 0
            },
            {
              "name": "5km Mark",
              "completed": 0,
              "total": 0
            },
            {
              "name": "10km Mark",
              "completed": 0,
              "total": 0
            },
            {
              "name": "21km Mark",
              "completed": 0,
              "total": 0
            },
            {
              "name": "Finish Line",
              "completed": 0,
              "total": 0
            }
          ]
        }
      ],
      "actions": [
        {
          "id": "add_checkpoint",
          "label": "Add Checkpoint",
          "icon": "📍",
          "type": "primary"
        },
        {
          "id": "export_results",
          "label": "Export Results",
          "icon": "📊",
          "type": "secondary"
        },
        {
          "id": "send_alerts",
          "label": "Send Alerts",
          "icon": "🚨",
          "type": "warning"
        }
      ]
    },
    "counts": {
      "total": 0,
      "basic": 0,
      "standard": 0,
      "premium": 0
    }
  }
}

HTTP 201. Discover the returned series id through series.list and compare name, template_id, status and dashboard. Keep the id for subsequent series actions.

Verify the result

  • Discover the returned series id through series.list and compare name, template_id, status and dashboard. Keep the id for subsequent series actions.

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

After an uncertain create, inspect series.list before creating another record; there is no caller idempotency key or published series delete action.

  • List QR series: Lists workspace series with code counts, optional template metadata and unassigned-code counts.
  • Get series dashboard: Reads the series identity and saved dashboard; supported templates can supply a default dashboard when no saved state exists.

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.