Campus One

Programmatic Notifications

Learn how to programmatically dispatch secure, real-time push notifications to Campus One users from your connected applications.

Programmatic Notifications API

Connected applications can dispatch transactional notifications directly to their authorized users' Campus One app shell in real-time. This guide details the integration flow, required authentication scopes, REST API specifications, and standard code examples.


Architectural Flow

The notifications mechanism follows a secure OAuth/OIDC authorization model. Connected apps must be granted the notifications scope by the user during sign-in to dispatch messages.

Loading diagram...

Authentication & Authorization

All notification requests require standard OIDC User Access Tokens.

  • Required Scope: notifications
  • Method: Bearer Token Authentication
  • Header format: Authorization: Bearer <access_token>
  • Admin prerequisite: The permNotifications flag must be enabled for your app (it is on by default) under Permissions in the developer dashboard.

When a connected app sends a notification, the recipient user and origin app are securely resolved from the OIDC Access Token record (userId is mapped to the token's authenticated owner, and appId is mapped to the registered client application). Therefore, connected apps do not need to supply a userId in the body payload—preventing any unauthorized spoofing of notifications.

[!WARNING] Access tokens are verified in real-time against active sessions. If the token is expired, revoked, or does not contain the notifications scope, the gateway immediately returns 401 Unauthorized or 403 Forbidden.


REST API Reference

Send Notification

Send a push notification to a specific user.

POST /api/apps/notifications

Headers

HeaderTypeDescription
AuthorizationstringRequired. Bearer <access_token> containing the notifications scope.
Content-TypestringRequired. Must be application/json.
Idempotency-KeystringOptional. Supply a unique key to make retries safe — a repeated key returns the original notification instead of creating a duplicate. Scoped per app, expires after 24 hours.

Request Payload

FieldTypeRequiredDescription
titlestringYesThe notification title (Maximum 128 characters).
bodystringYesDetailed notification body message (Maximum 512 characters).
typestringNoColor theme identifier. Can be info, success, warning, or action_required. (Default: info).
targetUrlstringNoDestination deep-link/URL. Opens in a new secure tab when the user clicks the notification's primary action button.

[!NOTE] action_required surfaces the notification prominently in the student dashboard's Action Required carousel — use it for time-sensitive items that need the student to take an explicit action (e.g. clearance steps, outstanding fees, consent forms). All other types (info, success, warning) appear only in the Recent Activity feed.


Example Integration

curl -X POST https://auth.campusone.com.ng/api/apps/notifications \
  -H "Authorization: Bearer c1_act_abc123xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Assignment Graded",
    "body": "Your submission for CSC 401 has been reviewed. Grade: A-",
    "type": "success",
    "targetUrl": "https://portal.nileuniversity.edu.ng/courses/csc401"
  }'
const sendNotification = async () => {
  const response = await fetch('https://auth.campusone.com.ng/api/apps/notifications', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer c1_act_abc123xyz',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      title: 'Assignment Graded',
      body: 'Your submission for CSC 401 has been reviewed. Grade: A-',
      type: 'success',
      targetUrl: 'https://portal.nileuniversity.edu.ng/courses/csc401'
    })
  });

  if (!response.ok) {
    const err = await response.json();
    throw new Error(`Failed to send notification: ${err.message}`);
  }

  const result = await response.json();
  console.log('Notification dispatched:', result.id);
};
import requests

headers = {
    "Authorization": "Bearer c1_act_abc123xyz",
    "Content-Type": "application/json"
}

payload = {
    "title": "Assignment Graded",
    "body": "Your submission for CSC 401 has been reviewed. Grade: A-",
    "type": "success",
    "targetUrl": "https://portal.nileuniversity.edu.ng/courses/csc401"
}

res = requests.post(
    "https://auth.campusone.com.ng/api/apps/notifications",
    json=payload,
    headers=headers
)

if res.status_code == 200:
    print("Notification sent successfully! ID:", res.json()["id"])
else:
    print("Failed to dispatch:", res.status_code, res.text)

Response Schemas

[!NOTE] The live, always-accurate schemas are published at the interactive API reference. The examples below are illustrative.

200 OK

Returned when the notification is created. The response body is the full created Notification record (the id, unread state and timestamps are server-generated).

{
  "id": "clh83kf1a0001st09k4m2p9zx",
  "userId": "clx8z2abc1230009ab12cd34",
  "appId": "clw7a1def4560002gh56ij78",
  "title": "Assignment Graded",
  "body": "Your submission for CSC 401 has been reviewed. Grade: A-",
  "type": "success",
  "unread": true,
  "targetUrl": "https://portal.nileuniversity.edu.ng/courses/csc401",
  "createdAt": "2026-05-28T10:00:00.000Z",
  "updatedAt": "2026-05-28T10:00:00.000Z"
}

Error responses

A 401 (authentication) is rejected at the gateway and returns { "error": "..." }. A 400 (validation) or 403 (authorization) comes from the endpoint and returns the richer { code, status, message } object. See Status Codes & Errors for the canonical reference.

{ "defined": false, "code": "FORBIDDEN", "status": 403, "message": "Token lacks 'notifications' scope" }
StatusBodyCause
400{ code, status, message, data }Payload fails validation (missing field, string too long, invalid type or targetUrl).
401{ error }Bearer token missing, malformed, expired, revoked, or not bound to a user.
403{ code, status, message }Token lacks the notifications scope, or the app's permNotifications flag is disabled.

On this page