# Change a campaign's Discord settings

`PATCH https://api.tryscouty.com/v1/campaigns/{campaignId}/discord-ops`

Changes how Scouty runs one campaign's Discord server, as the campaign builder does: any of the setup, the posting schedule, the time zone, reminders, digests, view tracking and the quiet days before a creator is flagged. Fields left out keep what is saved. Saving a posting schedule confirms it, and counting starts from today. Only campaigns Discord ops is on for.

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

## 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 Discord settings these are. |

## 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. |
| `setupMode` | `string` | Optional | How the server is set up: none (just add Scouty), bot (Scouty builds it) or template. One of `none`, `bot`, `template`. |
| `cadence` | `object` | Optional | How many videos each creator posts. Saving one confirms it and starts the counting. |
| `cadence.count` | `integer` | Required | Videos each creator posts, 1 to 1000. |
| `cadence.period` | `string` | Required | Per day, week or month. One of `day`, `week`, `month`. |
| `timezone` | `string` | Optional | The time zone reminders and digests follow, from the builder's list. One of `America/New_York`, `America/Chicago`, `America/Denver`, `America/Los_Angeles`, `America/Phoenix`, `America/Anchorage`, `Pacific/Honolulu`, `America/Toronto`, `America/Vancouver`, `Europe/London`, `Europe/Dublin`, `Europe/Berlin`, `Europe/Paris`, `Australia/Sydney`, `Australia/Melbourne`, `Australia/Perth`, `Pacific/Auckland`. |
| `remindersEnabled` | `boolean` | Optional | Whether creators get reminders. |
| `digestsEnabled` | `boolean` | Optional | Whether the team gets the morning and night digests. |
| `inactivityDays` | `integer` | Optional | Quiet days before a creator is flagged to the team, 1 to 30. |
| `viewTrackingEnabled` | `boolean` | Optional | Whether views on posted videos are checked. |

## Request

### cURL

```bash
curl -s -X PATCH https://api.tryscouty.com/v1/campaigns/42/discord-ops \
  -H "Authorization: Bearer $SCOUTY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"idempotencyKey":"ops-42-1","cadence":{"count":3,"period":"day"},"remindersEnabled":true}'
```

### JavaScript

```js
const response = await fetch("https://api.tryscouty.com/v1/campaigns/42/discord-ops", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.SCOUTY_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    idempotencyKey: "ops-42-1",
    cadence: {
      count: 3,
      period: "day"
    },
    remindersEnabled: 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/discord-ops",
    headers={"Authorization": f"Bearer {token}"},
    json={
        "idempotencyKey": "ops-42-1",
        "cadence": {"count": 3, "period": "day"},
        "remindersEnabled": True,
    },
)
print(response.json())
```

## Responses

### 200 OK

```json
{
  "status": "saved",
  "campaignId": 42,
  "settings": {
    "available": true,
    "setupMode": "bot",
    "setupCompletedAt": "2026-09-16T10:00:00.000Z",
    "setupError": null,
    "cadenceStatus": "confirmed",
    "cadenceCount": 3,
    "cadencePeriod": "day",
    "cadencePerDay": 3,
    "cadenceQuote": null,
    "cadenceSource": "client",
    "cadenceStartsOn": "2026-09-16",
    "timezone": "America/New_York",
    "remindersEnabled": true,
    "teamUpdatesAvailable": true,
    "digestsEnabled": true,
    "inactivityDays": 3,
    "viewTrackingEnabled": true
  }
}
```

### 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
