Retained immutable local-fixture guide, refreshed against current production catalog metadata. No examples were rerun by this author; no production action was invoked.
List campaign batches
Outcome
Lists batch metadata for the selected campaign, newest updates first. An empty array can also mean that the campaign id is absent or outside the bound workspace; this read does not verify campaign existence.
After authentication and the canonical workspace grant succeed, a first workspace request may initialize the app-local identity mirror and recipient setting before the application permission check. These reads do not modify campaign-domain records or execute notifications.
Before you start
- Verify the intended environment, authenticated identity and organization before discovery.
- Discover the published campaigns:read application permission and inspect the credential-scoped action contract.
- Discover and bind the granted canonical Campaigns workspace separately from the action input.
- Fixture identifiers and simulated responses confer no live access. Replace identifiers through granted resource discovery.
Discover the target
topolo whoami --json
topolo workspaces list topolo-campaigns --json
topolo actions get app_topolo_campaigns.batches.list --json
- Read app_topolo_campaigns.campaigns.list in this same authorized context and select campaigns[].id. Do not derive ids from display names.
- Inspect app_topolo_campaigns.campaigns.get in the same credential and resource context before reading it.
- Inspect app_topolo_campaigns.campaigns.dashboard.get in the same credential and resource context before reading it.
Request
GET /api/campaigns/{id}/batches
Input fields
| Field | Required | Meaning and constraints |
|---|---|---|
id | Yes | Campaign identifier returned by campaigns.list in the same authorized organization and workspace. Type: string. minLength: 1 |
Worked examples
populated resource · HTTP 200
Input · payload.json:
{
"id": "campaign_docs_fixture"
}
CLI:
topolo actions validate app_topolo_campaigns.batches.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_campaigns.batches.list",
"input": {
"id": "campaign_docs_fixture"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by granted resource discovery>"
}
}
Captured local response · HTTP 200:
{
"batches": [
{
"id": "batch_docs_fixture",
"name": "Fixture batch",
"status": "active",
"plannedCount": 2,
"createdAt": "2026-10-07T00:00:00.000Z",
"updatedAt": "2026-10-07T00:00:00.000Z"
}
]
}
populated resource: HTTP 200.
empty workspace · HTTP 200
Input · payload.json:
{
"id": "campaign_docs_fixture"
}
CLI:
topolo actions validate app_topolo_campaigns.batches.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_campaigns.batches.list",
"input": {
"id": "campaign_docs_fixture"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by granted resource discovery>"
}
}
Captured local response · HTTP 200:
{
"batches": []
}
empty workspace: HTTP 200.
campaign absent · HTTP 200
Input · payload.json:
{
"id": "campaign_unknown_fixture"
}
CLI:
topolo actions validate app_topolo_campaigns.batches.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_campaigns.batches.list",
"input": {
"id": "campaign_unknown_fixture"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by granted resource discovery>"
}
}
Captured local response · HTTP 200:
{
"batches": []
}
campaign absent: HTTP 200.
workspace grant denied · HTTP 403
Input · payload.json:
{
"id": "campaign_docs_fixture"
}
CLI:
topolo actions validate app_topolo_campaigns.batches.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_prepare_action",
"arguments": {
"actionId": "app_topolo_campaigns.batches.list",
"input": {
"id": "campaign_docs_fixture"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by granted resource discovery>"
}
}
Captured local response · HTTP 403:
{
"error": "workspace_forbidden"
}
workspace grant denied: HTTP 403; SDK code permission_denied.
permission denied · HTTP 403
Input · payload.json:
{
"id": "campaign_docs_fixture"
}
CLI:
topolo actions validate app_topolo_campaigns.batches.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_prepare_action",
"arguments": {
"actionId": "app_topolo_campaigns.batches.list",
"input": {
"id": "campaign_docs_fixture"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by granted resource discovery>"
}
}
Captured local response · HTTP 403:
{
"error": "forbidden"
}
permission denied: HTTP 403; SDK code permission_denied.
authentication missing · HTTP 401
Input · payload.json:
{
"id": "campaign_docs_fixture"
}
CLI:
topolo actions validate app_topolo_campaigns.batches.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_prepare_action",
"arguments": {
"actionId": "app_topolo_campaigns.batches.list",
"input": {
"id": "campaign_docs_fixture"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by granted resource discovery>"
}
}
Captured local response · HTTP 401:
{
"error": "Authentication required"
}
authentication missing: HTTP 401; SDK code auth_error.
Verify the result
- First verify campaigns.get. Retain batches[].id and inspect status and plannedCount. Planned count describes intended production; it does not prove codes were issued or a batch completed.
Errors and recovery
permission_denied(HTTP 403): Preserve the refusal. Verify the exact application permission and canonical workspace grant, or the organization boundary for export. Do not widen context or retry with a different resource to evade a denial.auth_error(HTTP 401): Authenticate again in the intended environment and pinned organization, then repeat identity and resource discovery.
Authentication, input validation or resource middleware can refuse a request before these handlers. Preserve the actual refusal and request id.
Recovery boundary
These reads do not change campaign-domain records and require no domain rollback. A permission or privacy refusal is authoritative; preserve its context and request id.
Related actions
- Get campaign — Campaigns: Reads one non-deleted campaign in the bound organization and workspace. An absent or differently scoped campaign returns HTTP 404 campaign_not_found.
- Get campaign dashboard — Campaigns: Reads stored batch, code, placement and redemption counts plus counts for each journey event type. Resource identity is the request id; the dashboard response contains counts. Stored events do not establish a live provider outcome.
Evidence
Actual Campaigns handleRequest, permission checks, store queries and replayed SQLite migrations. Credential verification and canonical workspace grants are simulated at the Auth package boundary; egress is sealed. No deployed/provider outcome, live redemption, outbound communication or live access is demonstrated.
Current field meanings and contract
| Field | Required | Meaning and validation |
|---|---|---|
id | Yes | Campaign identifier from campaigns[].id; scoped to the selected organization/workspace. It is not a batch/code/placement id. string; minLength=1 |
Exact schemas and provenance
Input schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1
}
},
"required": [
"id"
],
"additionalProperties": false
}
Output schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"batches": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"status": {
"type": "string"
},
"plannedCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"createdAt": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
},
"required": [
"id",
"name",
"status",
"plannedCount",
"createdAt",
"updatedAt"
],
"additionalProperties": false
}
}
},
"required": [
"batches"
],
"additionalProperties": false
}
Reviewed immutable source: TopoloCampaigns@cacbb8b12b4e19a662cf82d03a927aef3c3a35e8, docs/action-read-records.json. Fresh production catalog was read on 2026-10-20. Its publication metadata is not proof that this source is loaded. Output examples are not widened or rewritten to force schema success; the accompanying validation record classifies exact success, refusal, no-body and structural-schema limits.
Related actions
app_topolo_campaigns.campaigns.get: Read one campaign with its offer, codes, status and redemption totals.app_topolo_campaigns.campaigns.dashboard.get: Read a campaign's dashboard: codes issued, redemptions and their total value.
Local input rejection example
This deliberately invalid input belongs to a pure schema check; it is never a planned or executed request. The closed action input schema must reject the extra field. It has no HTTP status or server response.
{
"id": "campaign_docs_fixture",
"__unsupported_field": true
}
The hidden companion labels this as ILLUSTRATIVE_LOCAL_SCHEMA_CHECK; its validation representation is not an action output.
Published output validation limits
Current published output qualification: the output schema rejects the empty-object, partial-success-marker, partial-data-object and refusal-body probes. A schema-valid success body still does not establish execution, live permission, selected context or a provider outcome.
These observations come from pure checks of the exact published schema; they are not server responses or production captures.