Topolo Docs Topolo Platform
Open workspace

Update a Socialize campaign

Edit campaign fields or replace intended draft variants while keeping lifecycle effects and partial-write recovery explicit.

Edit campaign details

Update supplied fields on an existing campaign. This endpoint edits stored records; it does not replace the dedicated scheduling or lifecycle actions.

Before you start

Read the campaign in the intended authorized brand, retain its current fields/variants, and use a credential with app_topolo_socialize.calendar:write and the workspace grant. Review every change, including any full variant replacement, before confirming the mutation.

Request

PUT /api/campaigns/{id}

id is required. Other fields are optional: name, description, status, goals, tags, platforms, window dates, timezone/cadence and variants. Resource binding stays outside the body.

  • name: non-empty after the route trim-check, up to 100 supplied characters; the value itself is stored as supplied.
  • platforms: records containing platform, enabled and settings, unlike the string list used by create.
  • Window dates can be strings or null. Editing them does not schedule posts; use the scheduling guide for actual operational constraints.
  • Empty goals/tags clear those lists. An empty description can be omitted from the subsequent optional response projection.

Worked examples

These examples are synthetic and unrun; the ids, content and timestamps do not identify live records.

Rename an existing campaign

Source-derived synthetic and unrun. Assumes the illustrated existing draft belongs to the verified workspace and only the approved name is changed. SQL CURRENT_TIMESTAMP formatting is illustrative, not a captured response.

Request

{
  "id": "campaign_example",
  "name": "Reviewed campaign title"
}

Response illustration

{
  "id": "campaign_example",
  "brandId": "ws_socialize_example",
  "name": "Reviewed campaign title",
  "createdBy": "user_example",
  "status": "draft",
  "windowStartDate": null,
  "windowEndDate": null,
  "paused": false,
  "pausedAt": null,
  "resumedAt": null,
  "variants": [],
  "createdAt": "2026-10-21T00:00:00.000Z",
  "updatedAt": "2026-10-21 13:00:00",
  "platforms": [
    {
      "platform": "linkedin",
      "enabled": true,
      "settings": {}
    }
  ],
  "timezone": "UTC"
}

Re-read the same campaign; check its owning brand, new name and preserved creator/status/variants. Do not infer a scheduling or publishing effect.

Replace content variants on an intended draft

Source-derived synthetic and unrun. Assumes the campaign is already an authorized intended draft and replacement of all variant links is approved; status=draft is deliberate, not an unapproved status workaround.

Request

{
  "id": "campaign_example",
  "status": "draft",
  "variants": [
    {
      "name": "Control",
      "weight": 100,
      "content": {
        "text": "A replacement draft example.",
        "hashtags": [
          "example"
        ]
      }
    }
  ]
}

Response illustration

{
  "id": "campaign_example",
  "brandId": "ws_socialize_example",
  "name": "Example campaign",
  "createdBy": "user_example",
  "status": "draft",
  "windowStartDate": null,
  "windowEndDate": null,
  "paused": false,
  "pausedAt": null,
  "resumedAt": null,
  "variants": [
    {
      "id": "campaign_example_Control",
      "name": "Control",
      "weight": 100,
      "postId": "post_new_draft_example",
      "hashtags": [
        "example"
      ]
    }
  ],
  "createdAt": "2026-10-21T00:00:00.000Z",
  "updatedAt": "2026-10-21 13:00:00",
  "platforms": [
    {
      "platform": "linkedin",
      "enabled": true,
      "settings": {}
    }
  ],
  "timezone": "UTC"
}

Verify the replacement variant id and newly created draft post in the same workspace. Prior draft posts are not deleted automatically. Do not replay after uncertainty; repetition can create another post.

Variant replacement

A non-empty variants array replaces all existing variant links. Content text creates new draft posts; old drafts are not automatically deleted. Empty or omitted variants leave existing links in place. A failure after link deletion can leave only some replacements, so preserve the before-state and inspect actual records before repair.

Variant names must be unique (at most 10), with weights totalling 100 within 0.01. Content-only variants without a post id require an explicitly intended status: draft in the request. Do not change an active campaign to draft just to satisfy that validator. Use content.hashtags for stored variant hashtags; this draft-post INSERT does not persist media URLs merely because the schema accepts those optional fields.

Lifecycle and verification

Changing a status string here does not run scheduling, activation, completion or cancellation hooks. It does not materialize occurrence posts or emit a lifecycle notification. Prefer the dedicated action when that is the intended operation.

Re-read the campaign and check its owning brand, changed fields, retained creator, current variant links and linked posts. The current caller and the stored creator are different facts. An id-only edit can return the unchanged record without a timestamp update; do not interpret that as a new content write.

Failure and recovery

Campaign field edits, old-link deletion and new draft/link inserts are sequential and have no enclosing rollback here. After a timeout/error, reconcile current state before another operation. Repeating content replacement can create extra drafts; cleanup is a separate reviewed mutation.

Name/variant validation uses HTTP400 problem details, access failures retain their actual refusal, and generic update failures can return HTTP500 with detail/debug fields. Preserve the actual request evidence; do not infer nothing changed or invent a uniform error.code envelope.

Change log

  • 2026-10-21: Added metadata and intended-draft replacement examples, create/update field differences, lifecycle distinctions, persistence limits and partial-write recovery.

Source

Reviewed route, brand access, campaign service and error source at f8e30bad6947f868302f24e9cb31b6a2bdd1fbf6, with the current declaration refreshed. No business request or provider test ran; serving-source association is unknown.