Topolo Docs Topolo Platform
Open workspace

Update a campaign batch — Campaigns

Changes stored batch name, status or plannedCount. The source accepts the declared status set without an active-only transition guard. An update advances updatedAt even when no effective field changes.

Update a campaign batch

Changes stored batch name, status or plannedCount. The source accepts the declared status set without an active-only transition guard. An update advances updatedAt even when no effective field changes.

Outcome and boundaries

Changes stored batch name, status or plannedCount. The source accepts the declared status set without an active-only transition guard. An update advances updatedAt even when no effective field changes.

A transition into complete schedules a background completion-notification attempt; success does not prove delivery.

Before you start

  • Confirm the intended environment and current credential organization using whoami; discover the exact application/action before any call.
  • Required application permission: app_topolo_campaigns.campaigns:write. Catalog discoverability is not permission to execute.
  • Discover an authorized canonical workspace and bind resourceType workspace/resourceId separately from action input.
  • All worked cases in this guide are hypothetical source-reviewed illustrations; no business action, live fixture, customer data or provider request was executed.
  • Canonical workspace minimum access is read_write in addition to the application permission. After grant verification, the first request may create an app-local identity/recipient mirror even before the later app-permission check; this is not campaign-domain completion.

Discover the intended identifiers

  • Read batches.list and retain the batch id belonging to the selected campaign.

Action: app_topolo_campaigns.batches.update · PATCH /api/campaigns/{id}/batches/{batchId}.

Input fields

FieldRequiredMeaning and validation
idYesCampaign identifier from campaigns[].id; scoped to the selected organization/workspace. It is not a batch/code/placement id. string; minLength=1
batchIdYesBatch record id from batches.list for this campaign. string; minLength=1
nameNoHuman-readable stored name. Whitespace can pass a schema string check yet fail a required-string domain check. string
statusNoOnly the enum values declared below are valid at the action-schema layer; read current state before a separately authorized transition. string; enum=["draft", "active", "paused", "complete", "archived"]
plannedCountNoOmit to retain the current planned count; a supplied integer must be 0–1000. This is intended volume, not codes issued, completed distribution or delivery evidence. integer; minimum=0; maximum=1000

Safe call sequence

Write the reviewed input to payload.json; fixture identifiers below are unusable examples. Validate before planning, bind the discovered resource separately, and execute only within actual authority.

topolo actions validate app_topolo_campaigns.batches.update --data @payload.json --json
topolo actions plan app_topolo_campaigns.batches.update --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json

The published action requires confirmation. Only after the exact mutation is authorized, use that same payload/context with --confirm on plan/call; no operation in this guide has been executed.

Worked cases

Every response below is synthetic and source-reviewed, not captured. HTTP status and body are explained independently; a structurally valid body alone never proves successful execution. Middleware may add a different error envelope.

Activate a draft batch · HTTP 200

Input:

{
  "id": "campaign_example",
  "batchId": "batch_example",
  "status": "active"
}

Illustrative response:

{
  "batch": {
    "id": "batch_example",
    "name": "Illustrative print run",
    "status": "active",
    "plannedCount": 20,
    "createdAt": "2026-10-20T00:00:00.000Z",
    "updatedAt": "2026-10-20T00:00:00.000Z"
  }
}

Identity-only update still refreshes metadata · HTTP 200

Input:

{
  "id": "campaign_example",
  "batchId": "batch_example"
}

Illustrative response:

{
  "batch": {
    "id": "batch_example",
    "name": "Illustrative print run",
    "status": "draft",
    "plannedCount": 20,
    "createdAt": "2026-10-20T00:00:00.000Z",
    "updatedAt": "2026-10-20T00:00:00.000Z"
  }
}

The illustrative timestamps stand for a new update time; no transition is implied.

Missing batch · HTTP 404

Input:

{
  "id": "campaign_example",
  "batchId": "batch_absent",
  "status": "active"
}

Illustrative response:

{
  "error": "batch_not_found"
}

Verify the outcome

  • Re-read batches.list; compare the exact batch and intended fields. Notification delivery requires separate owning evidence.

Refusals and recovery

  • HTTP 404 batch_not_found: Correct the named input or retain the authoritative refusal in the same context.
  • HTTP 400 invalid_status: Correct the named input or retain the authoritative refusal in the same context.
  • HTTP 400 invalid_planned_count: Correct the named input or retain the authoritative refusal in the same context.
  • HTTP 403 forbidden: Raw handler permission refusal. SDKs can normalize it to permission_denied. Keep the same intended resource; do not widen access.
  • HTTP 403 workspace_forbidden: The canonical workspace grant refused the selected resource. Resolve it with the access owner, not a guessed workspace.

Snapshot the prior fields. A separately authorized update can restore their values; it cannot retract already-attempted notifications or history.

Source and catalog limits

The catalog batch_not_running/409 claim for this update is unsupported by the reviewed updateBatch implementation. Do not present it as an enforced source guard.

Exact schemas and provenance

Input schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    },
    "batchId": {
      "type": "string",
      "minLength": 1
    },
    "name": {
      "type": "string"
    },
    "status": {
      "type": "string",
      "enum": [
        "draft",
        "active",
        "paused",
        "complete",
        "archived"
      ]
    },
    "plannedCount": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    }
  },
  "required": [
    "id",
    "batchId"
  ],
  "additionalProperties": false
}

Output schema:

{
  "type": "object",
  "title": "batches update response",
  "description": "Operation result returned by batches.update.",
  "properties": {
    "success": {
      "type": "boolean"
    },
    "id": {
      "type": "string"
    },
    "data": {
      "anyOf": [
        {
          "type": "object",
          "title": "batch record",
          "properties": {
            "id": {
              "type": "string",
              "description": "Stable identifier when the batch exposes one."
            }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "additionalProperties": true
        }
      ]
    },
    "result": {
      "type": "object",
      "additionalProperties": true
    },
    "message": {
      "type": "string"
    }
  },
  "additionalProperties": true,
  "x-topolo-contract-source": "derived-action-metadata",
  "x-topolo-contract-precision": "structural"
}

Reviewed immutable source: TopoloCampaigns@cacbb8b12b4e19a662cf82d03a927aef3c3a35e8, apps/api/src/campaign-orchestration-store.ts. 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.

  • List campaign batches — Campaigns: 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.
  • Record a batch failure — Campaigns: For an active batch, records a failure row and changes that batch to paused. It does not pause or archive the campaign.

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_example",
  "batchId": "batch_example",
  "status": "active",
  "__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 accepts an empty object, a partial success marker, a partial data object and a refusal body. It therefore establishes only broad structure. Require the documented HTTP/domain result and source-shaped fields; missing fields or a schema-valid error are not success.

These observations come from pure checks of the exact published schema; they are not server responses or production captures.