Rostering API
The Rostering API provides OneRoster v1.2-compatible endpoints for managing the full roster hierarchy: users, courses, classes, enrollments, organizations, and terms. All endpoints require Authorization: Bearer <token>. See the Curriculum API for units, lessons, and resources that build on courses created here.
Base prefix: https://api.alpha-1edtech.ai/rostering/1.0
GET /rostering/1.0/users
Returns a paginated list of users (students and staff). Supports filtering, sorting, and field selection.
Filter examples:
filter=email='alice@school.edu'— find a user by exact emailfilter=status='active'— only active usersfilter=familyName~'Smi'— last name contains "Smi"filter=status='active' AND role='student'— active students only
Scope: roster.readonly
Query params
| Name | Description | Required |
|---|---|---|
limit | Maximum records per page (default 100, max 1000) | no |
offset | Number of records to skip (default 0) | no |
filter | OneRoster filter expression. Operators: =, !=, >, >=, <, <=, ~ (contains), @ (regex). Combine with AND / OR. | no |
sort | Field to sort by | no |
orderBy | Sort direction: asc or desc | no |
search | Free-text search term | no |
fields | Comma-separated list of fields to include | no |
Response
200 OK — { "users": [...], "offset": 0, "limit": 100, "total": N }
Each user object includes: sourcedId, givenName, familyName, email, enabledUser, roles, grades, primaryOrg.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/users?filter=status%3D'active'&limit=10" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/users/:sourcedId
Returns a single user by their sourcedId.
Scope: roster.readonly
Path params
| Name | Description |
|---|---|
sourcedId | User UUID |
Response
200 OK — User object. 404 if not found.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/users/11111111-1111-1111-1111-111111111111" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
PUT /rostering/1.0/users/:sourcedId
Create or update a user using a standard OneRoster v1.2 User payload. If the user exists, it is updated; otherwise a new user is created.
The sourcedId in the URL path must match the sourcedId in the request body. You generate the UUID.
Required fields: sourcedId, status, dateLastModified, enabledUser, givenName, familyName, email, roles (at least one with org reference).
Get your org sourcedId from GET /rostering/1.0/orgs.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | User UUID (must match body) |
Request body
Wrapped as { "user": { ... } }.
| Field | Type | Required | Description |
|---|---|---|---|
sourcedId | string (UUID) | yes | Must match the URL path parameter |
dateLastModified | string (ISO 8601) | yes | Timestamp of this update |
givenName | string | yes | First name |
familyName | string | yes | Last name |
email | string | yes | Email address — used as identifier when sending events |
enabledUser | string | no | "true" or "false" (defaults to "true") |
roles | array | no | Role assignments; each entry has role, org.sourcedId |
grades | string[] | no | Grade levels (e.g., ["5"]) |
primaryOrg | { sourcedId } | no | Primary school/org reference |
username | string | no | Login username |
metadata | object | no | Free-form metadata blob |
Response
201 Created or 200 OK — { "status": "...", "sourcedId": "..." }
403 Forbidden — User not owned by your client application.
Example
curl -X PUT "https://api.alpha-1edtech.ai/rostering/1.0/users/22222222-2222-2222-2222-222222222222" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"user": {
"sourcedId": "22222222-2222-2222-2222-222222222222",
"dateLastModified": "2026-01-15T00:00:00.000Z",
"givenName": "Alice",
"familyName": "Smith",
"email": "alice@school.edu",
"roles": [{ "role": "student", "org": { "sourcedId": "ORG_SOURCED_ID" } }]
}
}'
DELETE /rostering/1.0/users/:sourcedId
Soft-deletes a user. Returns HTTP 204 with an empty body on success.
Ownership: partners may only delete users they created (i.e. metadata.createdByApp matches the caller) or sandbox-scoped users (primary org partner-sandbox). Cross-tenant DELETE is rejected with HTTP 403. Alpha-owned / Alpha-synced students are not partner-deletable.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | User UUID |
Response
204 No Content on success. 403 Forbidden — ownership violation. 404 — not found.
Example
curl -X DELETE "https://api.alpha-1edtech.ai/rostering/1.0/users/22222222-2222-2222-2222-222222222222" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/users/:sourcedId/enrollments
Returns all enrollments for a user.
Scope: roster.readonly
Path params
| Name | Description |
|---|---|
sourcedId | User UUID |
Query params
Standard pagination query params (limit, offset, filter, sort, orderBy, search, fields).
Response
200 OK — { "enrollments": [...], "offset": 0, "limit": 100, "total": N }
Each enrollment includes: sourcedId, role, user, class, course, school, beginDate, endDate.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/users/22222222-2222-2222-2222-222222222222/enrollments" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/users/:sourcedId/agents
Returns all agents (parents, guardians) linked to a student.
Scope: roster.readonly
Path params
| Name | Description |
|---|---|
sourcedId | Student UUID |
Response
200 OK — { "agents": [...] } — array of user objects.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/users/22222222-2222-2222-2222-222222222222/agents" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/users/:sourcedId/linked-users
Returns all agents and students linked to this user.
Scope: roster.readonly
Path params
| Name | Description |
|---|---|
sourcedId | User UUID |
Response
200 OK — { "agents": [...], "students": [...] } — arrays of user objects.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/users/22222222-2222-2222-2222-222222222222/linked-users" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
PUT /rostering/1.0/students/:sourcedId/agents/:agentId
Link a parent/guardian user to a student.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | Student UUID |
agentId | Agent (parent/guardian) UUID |
Response
200 OK — { "status": "ok" }
Example
curl -X PUT "https://api.alpha-1edtech.ai/rostering/1.0/students/22222222-2222-2222-2222-222222222222/agents/33333333-3333-3333-3333-333333333333" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
DELETE /rostering/1.0/students/:sourcedId/agents/:agentId
Unlink a parent/guardian user from a student.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | Student UUID |
agentId | Agent (parent/guardian) UUID |
Response
200 OK — { "status": "ok" }
Example
curl -X DELETE "https://api.alpha-1edtech.ai/rostering/1.0/students/22222222-2222-2222-2222-222222222222/agents/33333333-3333-3333-3333-333333333333" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/courses
Returns a paginated list of courses.
Filter examples:
filter=status='active'— only active coursesfilter=subjects~'Math'— courses covering Math
Scope: roster.readonly
Query params
Standard pagination query params (limit, offset, filter, sort, orderBy, search, fields).
Response
200 OK — { "courses": [...], "offset": 0, "limit": 100, "total": N }
Each course includes: sourcedId, title, courseCode, subjects, grades, org.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/courses?filter=subjects~'Math'" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/courses/:sourcedId
Returns a single course by its sourcedId.
Scope: roster.readonly
Path params
| Name | Description |
|---|---|
sourcedId | Course UUID |
Response
200 OK — Course object. 404 if not found.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/courses/44444444-4444-4444-4444-444444444444" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
PUT /rostering/1.0/courses/:sourcedId
Create or update a course using a standard OneRoster v1.2 Course payload.
Required fields: sourcedId, status, dateLastModified, title, courseCode, org.
The course is automatically linked to your application for event processing. The subjects array determines which Caliper events (by extensions.subject) are attributed to this course.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | Course UUID (must match body) |
Request body
Wrapped as { "course": { ... } }.
| Field | Type | Required | Description |
|---|---|---|---|
sourcedId | string (UUID) | yes | Must match the URL path parameter |
dateLastModified | string (ISO 8601) | yes | Timestamp of this update |
title | string | yes | Display name (e.g., "Math Grade 5") |
courseCode | string | no | Short code (e.g., "MATH-G5") |
org | { sourcedId } | yes | Organization owning this course |
subjects | string[] | no | Subjects (e.g., ["Math"]) — used for event attribution |
grades | string[] | no | Grade levels (e.g., ["5"]) |
metadata | object | no | Additional metadata |
Response
201 Created or 200 OK — { "status": "...", "sourcedId": "..." }
Example
curl -X PUT "https://api.alpha-1edtech.ai/rostering/1.0/courses/44444444-4444-4444-4444-444444444444" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"course": {
"sourcedId": "44444444-4444-4444-4444-444444444444",
"dateLastModified": "2026-01-15T00:00:00.000Z",
"title": "Math Grade 5",
"courseCode": "MATH-G5",
"org": { "sourcedId": "ORG_SOURCED_ID" },
"subjects": ["Math"],
"grades": ["5"]
}
}'
DELETE /rostering/1.0/courses/:sourcedId
Soft-deletes a Course. Returns HTTP 204 with an empty body on success.
Cascade protection: if any Enrollment under this Course is currently active, the DELETE is rejected with HTTP 409 Conflict and { "error": "Cannot delete course with active enrollments" }. Withdraw active enrollments first, then retry.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | Course UUID |
Response
204 No Content on success. 403 — ownership violation. 404 — not found. 409 — active enrollments exist.
Example
curl -X DELETE "https://api.alpha-1edtech.ai/rostering/1.0/courses/44444444-4444-4444-4444-444444444444" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/classes
Returns a paginated list of classes (sections of courses).
Filter examples:
filter=course.sourcedId='COURSE_UUID'— classes for a specific coursefilter=status='active'— only active classes
Scope: roster.readonly
Query params
Standard pagination query params (limit, offset, filter, sort, orderBy, search, fields).
Response
200 OK — { "classes": [...], "offset": 0, "limit": 100, "total": N }
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/classes?filter=course.sourcedId%3D'44444444-4444-4444-4444-444444444444'" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
GET /rostering/1.0/classes/:sourcedId
Returns a single class by its sourcedId.
Scope: roster.readonly
Path params
| Name | Description |
|---|---|
sourcedId | Class UUID |
Response
200 OK — { "class": { ... } }. 404 if not found.
Example
curl "https://api.alpha-1edtech.ai/rostering/1.0/classes/55555555-5555-5555-5555-555555555555" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
PUT /rostering/1.0/classes/:sourcedId
Create or update a class (section) using a standard OneRoster v1.2 Class payload. In OneRoster, students enroll in classes, which are instances of courses.
Required fields: sourcedId, status, dateLastModified, title, course (reference), org, classType, terms (can be empty []).
Typical flow: Create a course first, then create a class for that course, then enroll students in the class.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | Class UUID (must match body) |
Request body
Wrapped as { "class": { ... } }.
| Field | Type | Required | Description |
|---|---|---|---|
sourcedId | string (UUID) | yes | Must match the URL path parameter |
dateLastModified | string (ISO 8601) | yes | Timestamp |
title | string | yes | Display title (e.g., "Math Grade 5 - Section 1") |
course | { sourcedId } | yes | Parent course reference |
org | { sourcedId } | yes | School/org reference |
classType | "scheduled" or "homeroom" | yes | Class type |
terms | array of { sourcedId } | no | Academic session references (can be []) |
classCode | string | no | Short human-readable code |
metadata | object | no | Additional metadata |
Response
201 Created or 200 OK — { "status": "...", "sourcedId": "..." }
Example
curl -X PUT "https://api.alpha-1edtech.ai/rostering/1.0/classes/55555555-5555-5555-5555-555555555555" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"class": {
"sourcedId": "55555555-5555-5555-5555-555555555555",
"dateLastModified": "2026-01-15T00:00:00.000Z",
"title": "Math Grade 5 - Section 1",
"course": { "sourcedId": "44444444-4444-4444-4444-444444444444" },
"org": { "sourcedId": "ORG_SOURCED_ID" },
"classType": "scheduled",
"terms": []
}
}'
DELETE /rostering/1.0/classes/:sourcedId
Soft-deletes a Class. Returns HTTP 204.
Ownership: enforced via the Class's parent Course. If the parent Course is not owned by your client, the DELETE is rejected with HTTP 403.
Scope: roster.createput
Path params
| Name | Description |
|---|---|
sourcedId | Class UUID |