# Update a campaign's activation flow

`PATCH https://api.tryscouty.com/v1/campaigns/{campaignId}/activation`

Adds, renames, removes or reorders the steps creators are walked through after they sign, and publishes the flow so creators who start it next get the change. With no changes and publish true, it publishes the draft as it stands. Creators already partway through keep the steps they started with. Read the step ids with scouty_get_activation first.

- Scope: `campaigns:write`
- Kind: write
- Safe to retry with the same idempotency key: yes
- MCP tool: `scouty_update_activation_flow`

## Authorization

Send `Authorization: Bearer $SCOUTY_TOKEN`. The token needs the `campaigns:write` scope.

## Path parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `campaignId` | `integer` | Required | The campaign whose activation flow to change. |

## Headers

| Name | Type | Required | Description |
|---|---|---|---|
| `Idempotency-Key` | `string` | Optional | The same key the body's idempotencyKey carries. Send one or the other, or both with the same value. |

## Body parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `idempotencyKey` | `string` | Required | A key you choose for this call, 8 to 128 characters of letters, digits, dot, underscore, colon or hyphen. Sending the same key with the same arguments replays the first answer and changes nothing, so a retry after a timeout is safe. |
| `changes` | `object \| object \| object \| object[]` | Required | The changes, applied in order, each to the flow the one before it left. Empty, with publish true, publishes the draft as it stands. |
| `publish` | `boolean` | Optional | Publish once saved, so creators who start the flow get it. True by default. False leaves the change in the draft. Default `true`. |

## Request

### cURL

```bash
curl -s -X PATCH https://api.tryscouty.com/v1/campaigns/42/activation \
  -H "Authorization: Bearer $SCOUTY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"idempotencyKey":"flow-42-1","changes":[{"op":"add_step","title":"Say hi in the welcome room","instructions":"Introduce yourself in #welcome."},{"op":"move_step","stepId":"0f1e2d3c4b5a","position":1}],"publish":true}'
```

### JavaScript

```js
const response = await fetch("https://api.tryscouty.com/v1/campaigns/42/activation", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.SCOUTY_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    idempotencyKey: "flow-42-1",
    changes: [
      {
        op: "add_step",
        title: "Say hi in the welcome room",
        instructions: "Introduce yourself in #welcome."
      },
      {
        op: "move_step",
        stepId: "0f1e2d3c4b5a",
        position: 1
      }
    ],
    publish: true
  }),
});
console.log(await response.json());
```

### Python

```python
import os

import requests

token = os.environ["SCOUTY_TOKEN"]
response = requests.patch(
    "https://api.tryscouty.com/v1/campaigns/42/activation",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "idempotencyKey": "flow-42-1",
        "changes": [{"op": "add_step", "title": "Say hi in the welcome room", "instructions": "Introduce yourself in #welcome."}, {"op": "move_step", "stepId": "0f1e2d3c4b5a", "position": 1}],
        "publish": True,
    },
)
print(response.json())
```

## Responses

### 200 OK

```json
{
  "status": "saved",
  "changed": true,
  "published": true,
  "stepCount": 3
}
```

### 400 Bad Request

```json
{
  "error": {
    "code": "invalid_request",
    "message": "Those arguments are not the shape this capability takes: idempotencyKey."
  }
}
```

### 401 Unauthorized

```json
{
  "error": {
    "code": "missing_token",
    "message": "This API needs an Authorization header carrying a bearer token."
  }
}
```

### 403 Forbidden

```json
{
  "error": {
    "code": "insufficient_scope",
    "message": "This token does not carry the campaigns:write scope. Ask the team for one that does."
  }
}
```

### 404 Not Found

```json
{
  "error": {
    "code": "not_found",
    "message": "No such campaign."
  }
}
```

### 409 Conflict

```json
{
  "error": {
    "code": "idempotency_conflict",
    "message": "That idempotency key was already used for a different request. Use a new key."
  }
}
```

### 429 Too Many Requests

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Please wait for the current minute to end."
  }
}
```

## Errors

| Status | `error.code` | Meaning |
|---|---|---|
| 400 Bad Request | `invalid_request` | The request was not the shape this capability takes, or its body was not JSON. |
| 401 Unauthorized | `missing_token`, `invalid_token`, `token_revoked`, `token_expired`, `token_orphaned` | No token, or one that is not recognized, revoked or expired. |
| 403 Forbidden | `insufficient_scope`, `wrong_principal` | The token does not carry the scope this capability needs. |
| 404 Not Found | `not_found` | No such route, or no such campaign for this client. |
| 409 Conflict | `idempotency_conflict` | That idempotency key was already used for a different request. Nothing was changed. |
| 429 Too Many Requests | `rate_limited` | Too many requests this minute. Retry-After says how long is left. |

Full reference: https://docs.tryscouty.com/reference
