Topolo Docs Topolo Platform
Open workspace

Pause a Socialize campaign

Pause an active or scheduled campaign while retaining its campaign status.

Outcome

Pause an active or scheduled campaign while retaining its campaign status.

Before you start

  • Use the intended environment and the same verified organization throughout. This guide grants no access.
  • Discover granted canonical Socialize workspaces through supported Auth/resource discovery. A brand uses the Auth workspace id; display names and provider account ids are not substitutes.
  • Select resource context separately from action input. Application permission and workspace access are both required; organization ownership alone does not establish access.
  • Published application permission: app_topolo_socialize.calendar:write. Validate and plan the exact input, then confirm the intended campaign mutation before executing. Permission and examples are not approval.
  • The campaign must be active or scheduled and not already paused. The domain rejects a repeated pause.
  • If stored start/end dates are both present, reconstruction calls SchedulingWindow.create again: start must precede end, duration must be at least one hour and no more than 365 days, and end must be in the future. Historical or invalid windows can fail before the operation-specific state check.

Find the campaign

  • Use campaigns.list/get to discover the exact campaign and verify its owning brand in the intended organization before mutation. Supply only the campaign id in input; workspace resource binding is separate.
  • The handler loads the campaign’s stored brand and verifies the original caller’s grant and API-key binding; a caller-supplied context cannot transfer ownership.

Request

POST /api/campaigns/{id}/pause

FieldRequiredMeaning
idYesNon-empty existing campaign id. No extra properties; resource binding is separate.

Effects

  • Authorization can insert/update an app-local brands mirror for the verified workspace; this is separate from the campaign mutation.
  • Sets paused=true and persists paused_at/updated_at using database time. Campaign status is unchanged. The domain response clears resumedAt, but the SQL pause helper does not clear an earlier resumed_at value; read-back can retain it.
  • This endpoint does not delete, recall or independently unschedule provider content.

Verify the result

  • Read campaigns.get; verify paused true and unchanged campaign status. Compare timestamps semantically: the immediate domain response uses ISO timestamps while the SQL helper stores database datetime values. Do not require resumedAt to be null on persisted read-back.
  • The immediate mutation response is a domain projection: optional brand/profile/metadata fields are omitted and variants without a postId are excluded from the returned array. This does not prove those stored variants were deleted. Use campaigns.get for the full persisted projection.
  • No idempotency guarantee is established. After a lost response, read current campaign state in the same authorized context before considering any separately approved next action.

Worked examples

These are synthetic, unrun illustrations. They do not grant execution approval. The example clock is 2026-10-21T12:00Z; stored state, dates, access and actual current time must be checked for a real operation.

Authorized pause illustration

Source-derived synthetic and unrun. Assume the illustration clock is 2026-10-21T12:00Z, the campaign is active, unpaused, access is already granted and value/window invariants are valid. No live approval or provider outcome.

Request

{
  "id": "campaign_example"
}

Response illustration

{
  "id": "campaign_example",
  "name": "Example campaign",
  "createdBy": "user_example",
  "status": "active",
  "paused": true,
  "pausedAt": "2026-10-21T12:00:00.000Z",
  "resumedAt": null,
  "windowStartDate": "2026-10-21T00:00:00.000Z",
  "windowEndDate": "2026-10-22T00:00:00.000Z",
  "variants": [
    {
      "id": "campaign_example_default",
      "name": "default",
      "weight": 100,
      "postId": "post_example"
    }
  ],
  "createdAt": "2026-10-20T12:00:00.000Z",
  "updatedAt": "2026-10-21T12:00:00.000Z"
}

Read campaigns.get; verify paused true and unchanged campaign status. Compare timestamps semantically: the immediate domain response uses ISO timestamps while the SQL helper stores database datetime values. Do not require resumedAt to be null on persisted read-back.

State-precondition refusal illustration

Source-derived synthetic and unrun; assumes the stated failing precondition, otherwise valid entity data and successful earlier access checks. This is the handler’s problem-details response, not a captured production error.

Request

{
  "id": "campaign_example"
}

Response illustration

{
  "type": "/problems/internal-server-error",
  "title": "Internal Server Error",
  "status": 500,
  "detail": "Campaign is already paused"
}

The domain throws a plain Error before the campaign state UPDATE. The reviewed route serializes it as HTTP500, not an invented409/422. Earlier authorization mirror writes may still have occurred.

Errors and recovery

The reviewed application uses RFC-style problem details (type, title, status, detail) for these domain/lookup errors, not an error.code envelope. The errors below retain that distinction. Catalogue generic error metadata is not a captured application response.

  • 500 /problems/internal-server-error: Inspect the problem-details detail and request context. Domain state/window errors are plain Error values serialized as500 in the reviewed implementation. Re-read state; do not blindly retry, alter timestamps or bypass preconditions.
  • 403 workspace_forbidden: Check the original credential’s exact existing workspace grant. Stop rather than probe other campaigns or automatically widen scope.
  • 404 /problems/not-found: Reconcile the intended existing campaign id using authorized discovery; a missing campaign is not a reason to create a substitute.

No transactional rollback is published for this state change. Preserve the before-state and actual request/error; after uncertainty read campaigns.get rather than replaying. Any later pause/resume/cancel/update is a separate reviewed mutation with current preconditions and new timestamps, not an automatic inverse or provider recall.

Change log

  • 2026-10-21: Added source-specific state/window prerequisites, persistence and response-projection limits, verification and recovery, plus schema-valid synthetic success/refusal illustrations. Source f8e30bad6947f868302f24e9cb31b6a2bdd1fbf6; no business action, provider call or application test executed.

Source

Reviewed immutable campaign route, service, domain and error/storage source. Current catalogue input/permission/structural output declarations were refreshed; current serving-source association is unknown.