Campus One

Channels & Audiences

Define named audiences (clubs, cohorts, sections) and target events and notifications at the users who have joined them.

Channels & Audiences

By default, every event and notification your app sends goes to the single user whose access token you used. Channels let you instead target a named group — a club, a cohort, a course section — so one request reaches everyone who has joined it.

This is how a club-style app reaches only its associated members: a user becomes a member of a channel only by opting in through your app under their own token. Your app cannot add arbitrary users, so channel messages never reach people who haven't joined.

Need to reach every Campus One user instead? That's the "all" audience, gated by the admin-only broadcast capability — you don't need a channel for it.


Concepts

TermMeaning
ChannelA named audience you define, identified by a stable key unique within your app (e.g. chess-club).
MembershipA user's opt-in to a channel. Created/removed only for the token's own user.
TargetingPass audience: { "channel": "<key>" } when sending an event or notification to reach the channel's members.

All channel endpoints require the events or notifications scope (the same capability used to send).


Typical flow

  1. Your app creates a channel once (idempotent): POST /api/apps/channels.
  2. When a user joins the club/section in your app, you enrol them: POST /api/apps/channels/{key}/join using that user's access token.
  3. You send to the channel: POST /api/apps/events (or /notifications) with audience: { "channel": "<key>" }.
  4. Only members see it — on their dashboard, calendar, or notification inbox.

REST API Reference

Create or update a channel

POST /api/apps/channels — idempotent on key.

FieldTypeRequiredDescription
keystringYesStable identifier, unique within your app (max 64 chars).
namestringYesHuman-readable name (max 120 chars).
descriptionstringNoOptional description (max 500 chars).

List your channels

GET /api/apps/channels — returns every channel your app has defined.

Join / leave (acts on the token's user)

POST /api/apps/channels/{key}/join — subscribes the authenticated user. Idempotent.

POST /api/apps/channels/{key}/leave — unsubscribes the authenticated user. Idempotent (succeeds even if they weren't a member).

Both return { "channelKey": "<key>", "joined": true | false }.


Example

# 1. Define the channel (once)
curl -X POST https://auth.campusone.com.ng/api/apps/channels \
  -H "Authorization: Bearer c1_act_abc123xyz" \
  -H "Content-Type: application/json" \
  -d '{ "key": "chess-club", "name": "Chess Club" }'

# 2. Enrol the signed-in user (their token)
curl -X POST https://auth.campusone.com.ng/api/apps/channels/chess-club/join \
  -H "Authorization: Bearer c1_act_user_token"

# 3. Notify the whole channel
curl -X POST https://auth.campusone.com.ng/api/apps/notifications \
  -H "Authorization: Bearer c1_act_abc123xyz" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Ladder night", "body": "7pm in the JCR", "audience": { "channel": "chess-club" } }'
const base = 'https://auth.campusone.com.ng/api/apps';
const headers = (token) => ({
  Authorization: `Bearer ${token}`,
  'Content-Type': 'application/json',
});

// Define once
await fetch(`${base}/channels`, {
  method: 'POST',
  headers: headers(APP_TOKEN),
  body: JSON.stringify({ key: 'chess-club', name: 'Chess Club' }),
});

// Enrol the current user (their token)
await fetch(`${base}/channels/chess-club/join`, {
  method: 'POST',
  headers: headers(userToken),
});

// Send to the channel
await fetch(`${base}/events`, {
  method: 'POST',
  headers: headers(APP_TOKEN),
  body: JSON.stringify({
    title: 'Ladder night',
    startsAt: '2026-06-15T18:00:00Z',
    audience: { channel: 'chess-club' },
  }),
});

Errors

StatusCause
403Token lacks both the events and notifications scopes.
404join/leave/targeting referenced a channel key that doesn't exist for your app — create it first.

How membership scopes delivery

Because join/leave always act on the token's own user, your app can only ever enrol people who have signed in through it and chosen to join. Combined with channel targeting, this guarantees a club app's messages reach only that club's members — Campus One enforces it, so you don't have to maintain a separate allow-list of who may be messaged.

On this page