> For the complete documentation index, see [llms.txt](https://docs.shoplift.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.shoplift.ai/api-reference/public-api/complete-campaign.md).

# Complete campaign

Completes the campaign: ends its active, paused, suspended and incompatible tests (significant ones become completed, the rest cancelled), unschedules its scheduled tests, and locks it. Ended tests cannot be restarted.

When the campaign has live or scheduled tests, completing takes two calls:

1. Call with no body. Nothing changes; the response is 409 with a `confirmationToken` and the affected `activeTestIds` and `scheduledTestIds`.
2. Call again with `{ "confirmationToken": "..." }`. The response is 200 with the ids of the tests that were ended or unscheduled.

If a test was launched or scheduled in the campaign after the token was issued, step 2 returns a new 409 with a fresh token instead of ending a test you were not shown — repeat step 2 with the new token. A campaign with no live or scheduled tests completes on the first call, and an already-completed campaign returns 200 with empty lists.

```json
{"openapi":"3.1.1","info":{"title":"Shoplift Public API","version":"1.0.0"},"tags":[{"name":"Public API"}],"servers":[{"url":"https://app.shoplift.ai"}],"security":[{"ApiKey":[]}],"components":{"securitySchemes":{"ApiKey":{"type":"http","description":"All requests require `Authorization: Bearer sl_live_<your_api_key>`. Generate a key from the Shoplift admin's API Keys settings page.","scheme":"bearer"}},"schemas":{"CompleteCampaignRequest":{"type":"object","properties":{"confirmationToken":{"type":["null","string"]}},"additionalProperties":false},"ExternalCompleteCampaignResponse":{"required":["campaign","completedTestIds","cancelledTestIds","unscheduledTestIds"],"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/ExternalCampaignItem"},"completedTestIds":{"type":"array","items":{"type":"string","format":"uuid"}},"cancelledTestIds":{"type":"array","items":{"type":"string","format":"uuid"}},"unscheduledTestIds":{"type":"array","items":{"type":"string","format":"uuid"}}}},"ExternalCampaignItem":{"required":["id","name","objective","goal","status","createdAt","progress"],"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"objective":{"type":["null","string"]},"goal":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/NullableOfCampaignGoal"}]},"status":{"$ref":"#/components/schemas/CampaignStatus"},"createdAt":{"type":"string","format":"date-time"},"progress":{"$ref":"#/components/schemas/ExternalCampaignProgress"}}},"NullableOfCampaignGoal":{"enum":["aov","cvr","rpv","ctr","atc",null]},"CampaignStatus":{"enum":["active","completed"]},"ExternalCampaignProgress":{"required":["total","live","paused","draft","ended"],"type":"object","properties":{"total":{"type":"integer","format":"int32"},"live":{"type":"integer","format":"int32"},"paused":{"type":"integer","format":"int32"},"draft":{"type":"integer","format":"int32"},"ended":{"type":"integer","format":"int32"}}},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}}}}},"paths":{"/api/public/v1/campaigns/{id}/complete":{"post":{"tags":["Public API"],"summary":"Complete campaign","description":"Completes the campaign: ends its active, paused, suspended and incompatible tests (significant ones become completed, the rest cancelled), unschedules its scheduled tests, and locks it. Ended tests cannot be restarted.\n\nWhen the campaign has live or scheduled tests, completing takes two calls:\n\n1. Call with no body. Nothing changes; the response is 409 with a `confirmationToken` and the affected `activeTestIds` and `scheduledTestIds`.\n2. Call again with `{ \"confirmationToken\": \"...\" }`. The response is 200 with the ids of the tests that were ended or unscheduled.\n\nIf a test was launched or scheduled in the campaign after the token was issued, step 2 returns a new 409 with a fresh token instead of ending a test you were not shown — repeat step 2 with the new token. A campaign with no live or scheduled tests completes on the first call, and an already-completed campaign returns 200 with empty lists.","operationId":"completeCampaign","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteCampaignRequest"}}}},"responses":{"200":{"description":"Campaign completed. Lists the public ids of the tests this call completed, cancelled or unscheduled; empty when it was already completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalCompleteCampaignResponse"}}}},"400":{"description":"The confirmationToken is invalid or belongs to another campaign, or a price test with subscription plans needs Recharge reconnected. Nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"The store's plan does not include Campaigns.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No campaign with this id in this store.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Confirmation required. Nothing was changed. Resend the request with the confirmationToken from this response; activeTestIds and scheduledTestIds list what confirming will end or unschedule.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Too Many Requests","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}}}}
```
