Skip to content

Cascaded settings

Many PlusPlus behaviors — when enrollment opens, whether self check-in is allowed, whether AI summaries show — are settings, and settings cascade. A value set on the workspace applies everywhere. A channel can override it for the content it holds. An event series can override it for its events. An individual item can override it for itself. The nearest level that holds a value wins.

flowchart LR
    W[Workspace] --> C[Channel] --> S[Event series] --> E[Event]
    C --> A[Article, video, course, …]

Every resource that has settings exposes them on a /settings/ sub-resource that reads and writes in the same shape, so one client covers all of them.

Resource Settings Inherits from
Event GET/PATCH /events/{public_id}/settings/ its event series, then its channel, then the workspace
Event series GET/PATCH /event-series/{public_id}/settings/ its channel, then the workspace
Office hour series GET/PATCH /programs/{public_id}/settings/ its channel, then the workspace
Article, video, course, track, scheduled track, guide, link GET/PATCH /{articles,videos,courses,tracks,scheduled-tracks,guides,links}/{public_id}/settings/ its channel, then the workspace
Channel GET/PATCH /channels/{public_id}/settings/ the workspace
Workspace GET/PATCH /workspace/settings/ the platform default

The API reference lists each resource's settings, their allowed values and what they do.

Channel settings are grouped

A channel holds two kinds of settings, so its settings resource is grouped: general applies to the channel and everything in it, and one section per content type (event, article, video, course, track, scheduled_track, guide, link) holds what that type's items in the channel inherit. Each section reads and writes exactly like an item's settings:

curl -X PATCH https://acme.plusplus.app/api/v2/channels/9f3e2d1c-…/settings/ \
  -H "Authorization: Bearer pp_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "general": { "anyone_can_add_content": { "value": true } },
    "event":   { "enrollment_closes_offset": { "value": "-P1D" } },
    "article": { "content_feedback_is_public": { "inherited": true } }
  }'

That closes enrollment a day before every event in the channel that has no value of its own (or whose event series has none), without touching the channel's articles or videos. A section holds only the settings the platform lets a channel set for that type, so it can be a subset of the item's own settings.

Reading a setting

curl https://acme.plusplus.app/api/v2/event-series/5b1d9c2e-…/settings/ \
  -H "Authorization: Bearer pp_your_token_here"
{
  "self_checkin_enabled":   { "value": false, "inherited": false, "source": "event_series", "parent_value": true, "default": true },
  "ai_summary_enabled":     { "value": true,  "inherited": true,  "source": "channel",      "parent_value": true, "default": false },
  "enrollment_closes_offset": { "value": "PT0S", "inherited": true, "source": "workspace",  "parent_value": "PT0S", "default": "PT0S" }
}
Key What it tells you
value The value that applies to this resource right now.
inherited false when the resource holds its own value (an override).
source Which level supplied value: the resource itself (event, event_series, …), channel or workspace.
parent_value What value becomes if you clear the override: the value the next level up supplies.
default The platform default, before any level overrides it.

An override is sticky: while inherited is false, changing the level above does not change this resource. That is the field to check before you bulk-edit a channel or an event series and expect every item to follow.

Changing a setting

PATCH the same URL with only the settings you want to change. Each takes one of two shapes:

Send Means
{"value": ...} Give this resource its own value (an override).
{"value": null} On a setting that allows null, store an explicit "no value" (for example, no enrollment deadline). This is still an override.
{"inherited": true} Drop this resource's own value so it follows the level above again, including later changes to it.
omitted Leave the setting as it is.
curl -X PATCH https://acme.plusplus.app/api/v2/event-series/5b1d9c2e-…/settings/ \
  -H "Authorization: Bearer pp_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "self_checkin_enabled": { "value": true },
    "ai_summary_enabled": { "inherited": true }
  }'

The response is the full settings resource. Unknown settings, a bare value ("self_checkin_enabled": true) and a bare null are refused with 422, and nothing is written. Send If-Match with the ETag of your last read to refuse the write with 412 if the settings changed since — including a change further up the cascade.

A personal article, video or guide (one in its owner's personal library) keeps only its AI settings (ai_summary_enabled, ai_flashcards_enabled, ai_flashcards_count, ai_coach_enabled, ai_generated_covers_enabled) and, for a video, video_download_enabled. Giving it any other setting, on create or through /settings/, is refused with 400 validation_error and nothing is saved; {"inherited": true} is always accepted.

Writing settings requires permission to manage the resource itself; reading them requires only permission to see it.

Workspace defaults

/workspace/settings/ is the root of every cascade: change a value there and every channel, event series and item without its own value follows at once. On the workspace, {"inherited": true} restores the platform default, and parent_value is that default.

Workspace settings are admin-only. Both reading and writing need a token minted with the admin scope as well as content:read (to read) or content:write (to write), owned by a user with the Admin role; a token without either gets 403 insufficient_scope. A few settings exist only below the workspace (a channel's anyone_can_add_content, a video's ai_flashcards_count), so the workspace resource does not list them.

Setting values when you create a resource

The create endpoints (POST /events/, POST /event-series/, POST /programs/, POST /articles/, POST /videos/, POST /courses/, POST /tracks/, POST /guides/, POST /links/) accept the same object under settings, so a new resource never exists with the inherited values first. Each resource accepts only its own settings. This example creates an event series:

{
  "name": "Security basics",
  "settings": {
    "ai_summary_enabled": { "value": true },
    "content_feedback_is_public": { "value": false }
  }
}

Settings you leave out follow the cascade. After creation, change them on the /settings/ sub-resource; the resource's own PATCH refuses settings with a 422 that points you there.

Settings by type

Values follow the setting's type:

  • On/off settings take true or false.
  • Offsets (enrollment and check-in windows) take a signed ISO 8601 duration relative to the event's start: -PT1H is an hour before, PT30M 30 minutes after. See Events for how they resolve. The office hour series cancellation deadline is relative to each session's start instead; see Office hour series.
  • Choices take one of the values the API reference lists for that setting.
  • Numbers take a whole number within the bounds the API reference lists.