Campaigns
A campaign is a plan: a name, a cadence, a length, and a mix of content types. Creating one does not create posts — content is generated asynchronously by the internal engine once the campaign is launched.
List campaigns
Section titled “List campaigns”GET /api/v1/campaignsQuery parameters:
| Name | Type | Notes |
|---|---|---|
limit | integer | 1 to 100, default 25. |
cursor | string | See Pagination. |
There is no status filter on this endpoint — filter client-side on the returned status field. Results are newest first by created_at.
Retrieve
Section titled “Retrieve”GET /api/v1/campaigns/{id}{ "id": "4b7f2a91-c3d8-4e56-9a07-1f2b3c4d5e6f", "object": "campaign", "name": "Product launch week", "description": "Announce v2 with a mix of feature posts and customer quotes.", "status": "active", "content_mix": { "ugc": 25, "talkingHead": 25, "videoHookDemo": 50 }, "posts_per_day": 2, "campaign_length_days": 5, "start_date": "2026-08-01T00:00:00Z", "total_posts": 10, "generated_posts": 4, "created_at": "2026-07-19T12:15:00Z", "updated_at": "2026-07-19T12:20:31Z"}Campaign ids are UUIDs, like every other id in the API.
Create
Section titled “Create”POST /api/v1/campaignscurl -X POST https://app.nativpost.com/api/v1/campaigns \ -H "Authorization: Bearer $NATIVPOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Product launch week", "description": "Announce v2 with a mix of feature posts and customer quotes.", "posts_per_day": 2, "campaign_length_days": 5, "start_date": "2026-08-01T00:00:00Z", "content_mix": { "ugc": 25, "talkingHead": 25, "videoHookDemo": 50 } }'| Field | Type | Notes |
|---|---|---|
name | string | Required. 1 to 160 characters. |
description | string | Up to 1000 characters. |
posts_per_day | integer | 1 to 50, default 3. |
campaign_length_days | integer | 1 to 365, default 7. |
start_date | string | ISO 8601 date-time. |
content_mix | object | Content type → percentage weight. |
name is the only required field.
There is no platforms field on a campaign. Targeting is set per content item via target_platforms — see Content.
content_mix keys are camelCase engine names, not the snake_case content types: ugc, slideshow, talkingHead, videoHookDemo, greenScreen, videoHook, carousel.
The campaign is created with status: "draft" and generated_posts: 0. total_posts is computed on create as posts_per_day × campaign_length_days and is not recomputed when you later patch either input.
Launch
Section titled “Launch”POST /api/v1/campaigns/{id}/launchFlips the campaign to active, sets start_date to now, and returns 202 Accepted with the serialized campaign:
{ "id": "4b7f2a91-c3d8-4e56-9a07-1f2b3c4d5e6f", "object": "campaign", "status": "active", "start_date": "2026-07-19T12:31:00Z", "total_posts": 10, "generated_posts": 0}The response carries no scheduled_posts or skipped_posts counts — generation happens asynchronously after the call returns. Poll the campaign and watch generated_posts climb toward total_posts.
Only draft and paused campaigns can be launched. Anything else returns 409 with code invalid_state:
{ "error": { "code": "invalid_state", "message": "Cannot launch a campaign in status \"active\". Only draft or paused campaigns can be launched.", "docs_url": "https://docs.nativpost.com/errors" }}Fires the campaign.launched webhook.
Update
Section titled “Update”PATCH /api/v1/campaigns/{id}Editable fields: name, description, status, posts_per_day, campaign_length_days, start_date, content_mix. Send only what changes; a body with no recognised field returns 400 no_updates.
status accepts draft, active, paused, completed, and archived. Setting it here bypasses the launch endpoint’s state check, so prefer /launch for the draft → active transition.
Delete
Section titled “Delete”DELETE /api/v1/campaigns/{id}Hard-deletes the campaign row. Content items generated by it are not deleted — their campaign_id is cleared and the posts remain in the workspace.
{ "id": "4b7f2a91-c3d8-4e56-9a07-1f2b3c4d5e6f", "object": "campaign", "deleted": true }No webhook fires on campaign deletion.