Create a campaign
Start with a draft, optionally creating local draft posts from variant content. Scheduling can be reviewed separately once those records are verified.
Before you start
Select an authorized Socialize brand/workspace and use a credential with app_topolo_socialize.calendar:write. The creator is the signed-in user; do not supply a replacement creator or a workspace id in the body. Review and confirm the campaign, content, target platforms and write effects before execution.
Request
POST /api/campaigns
| Field | Required | Meaning |
|---|---|---|
name | Yes | Trimmed campaign name, 1–100 characters. |
platforms | Yes | At least one supported platform name. |
description | No | Up to 1,000 characters. |
variants | No | Up to 10 unique names with weights totalling 100; content can create draft posts. |
goals, tags | No | String arrays. |
status | No | draft by default; scheduled adds scheduling effects. |
windowStartDate, windowEndDate | No for draft | UTC date-time strings; both required for scheduled creation. |
timezone | No | Defaults to UTC; scheduling validates the time zone. |
scheduleDays, scheduleTimes | No | Weekday names and HH:MM cadence; configure both together. |
Each variant needs a name (1–100 characters) and weight (0–100). Content text is limited to 63,206 characters; optional media URLs must be URLs. The implementation validates non-empty variant weights, duplicate names and the 10-variant limit in addition to JSON Schema. A content variant creates a draft post and replaces a supplied postId for that variant. Use existing post ids only after verifying their workspace.
Worked examples
These examples are synthetic and unrun. HTTP201 indicates campaign creation in the reviewed handler; it is not a provider publication receipt.
Create an empty draft campaign
Request
{
"name": "Example campaign",
"platforms": [
"linkedin"
]
}
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": [],
"createdAt": "2026-10-21T00:00:00.000Z",
"updatedAt": "2026-10-21T00:00:00.000Z",
"platforms": [
{
"platform": "linkedin",
"enabled": true,
"settings": {}
}
],
"timezone": "UTC"
}
Persist the returned campaign id, verify brandId and read the campaign. Empty variants are valid for a draft; no scheduled/provider post is implied.
Create a draft with one content variant
Request
{
"name": "Example campaign",
"platforms": [
"linkedin"
],
"variants": [
{
"name": "Control",
"weight": 100,
"content": {
"text": "A source-derived example post."
}
}
]
}
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_example",
"hashtags": []
}
],
"createdAt": "2026-10-21T00:00:00.000Z",
"updatedAt": "2026-10-21T00:00:00.000Z",
"platforms": [
{
"platform": "linkedin",
"enabled": true,
"settings": {}
}
],
"timezone": "UTC"
}
Read the returned campaign and linked draft post in the same authorized workspace. Retain both identities before scheduling or any later mutation.
Scheduled creation
Setting status: scheduled additionally invokes scheduling after persistence. Supply both window dates, at least one content variant, enabled platforms and a valid cadence. The route creates occurrence posts and attempts a best-effort notification. An error at this stage can follow earlier writes; the create catch does not roll them back.
Verify and recover
Read the returned campaign id in the same workspace. Verify its brand, original creator, status, variants and linked draft or occurrence posts. Keep campaign status, queued posts and provider delivery as separate facts.
Creation has no qualified idempotency guarantee. After a timeout or other uncertain response, reconcile same-workspace list/get results and request evidence before attempting another create. Cleanup is a separate destructive decision; do not delete or replay merely to discover what happened.
Errors
Route shape errors return HTTP400 validation_error with details. Additional application validation uses problem details, for example an invalid non-empty weight sum produces HTTP400 with type: /problems/validation-error and detail Total variant weights must equal 100. These carriers differ; preserve the actual response. Domain/runtime failures can return HTTP500 after some records have already been persisted.
Change log
- 2026-10-21: Added draft and content-variant examples, creator/workspace boundaries, optional scheduling effects, verification and partial-write recovery from reviewed source.
Source
Reviewed immutable route/service/domain/scheduling/notification source at f8e30bad6947f868302f24e9cb31b6a2bdd1fbf6; examples were checked against the refreshed declaration. No business action was run, and serving-source association remains unknown.