---
title: "Remove a creator from a campaign"
method: POST
path: "/campaigns/creators/{creator_id}/remove"
tags: ["Campaigns"]
---

# Remove a creator from a campaign

`POST /campaigns/creators/{creator_id}/remove`

Removes the creator from ONE campaign (terminal `removed` status). The campaign lives in the `x-shop-id` shop; pass its id in the body. Removed creators disappear from the creator's portal views.

**Paid/completed creators are blocked (409)** — their payout ledger is preserved and never overwritten.

**Idempotent:** removing an already-`removed` creator returns 200 with `code='already_removed'` (no error). Combined with the `Idempotency-Key` replay, repeated calls are always safe.

`X-Dry-Run: true` validates + echoes the intended action without writing or sending the optional SMS.

## Path parameters

- `creator_id` integer, required

## Headers

- `Idempotency-Key` string, nullable
- `X-Dry-Run` string, nullable

## Request body

- RemoveCreatorRequest — ``POST /public/v1/campaigns/creators/{creator_id}/remove``. Removes the creator from ONE campaign (terminal ``removed`` status). The campaign's shop is the request's ``x-shop-id``; the campaign id is the only required body field. Paid/completed creators are blocked (409) to preserve their payout ledger.
  - `campaign_id` integer, required — Campaign (in the x-shop-id shop) to remove the creator from.
  - `message` string, nullable — Optional SMS sent to the creator on removal. Removal is otherwise silent (no email, no default SMS). Length capped at 320 to match the service's SMS limit. SKIPPED on X-Dry-Run.

## Response `200`

Removed (or idempotent already-removed).

- RemoveCreatorResponse — 200 response for ``POST /campaigns/creators/{creator_id}/remove``. Mirrors the service envelope. ``code`` is ``"ok"`` on a real removal and ``"already_removed"`` when the call was a no-op idempotent replay of an already-``removed`` mapping (the service's internal "invalid transition" 409 is translated to this 200 — see the route). ``data`` carries ``campaign_creator_mapping_id`` + ``status`` (always ``"removed"``).
  - `success` boolean
  - `code` string — `ok` on a real removal; `already_removed` on an idempotent no-op replay of an already-removed mapping.
  - `data` object — `{campaign_creator_mapping_id, status='removed'}`.

## Other responses

- `400` — Invalid request / missing single shop.
- `403` — API key lacks `read_write` scope.
- `404` — Mapping/campaign not in this shop, or shop not owned by the key's customer.
- `409` — Paid/completed creator (ledger preserved), or Idempotency-Key conflict.
- `422` — Validation Error
- `429` — Write rate limit exceeded.

---

[API](https://skmtc.dev/reacherapp/apis/reacher-data-api.md) · [All operations](https://skmtc.dev/reacherapp/apis/reacher-data-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/reacherapp/reacher-data-api/revisions/3ea20a9f734b/schema)
