Skip to main content

Overview

The @timeback/oneroster package provides a TypeScript client for the OneRoster 1.2 API, supporting:
  • Rostering: Users, orgs, schools, courses, classes, enrollments
  • Gradebook: Categories, line items, results, score scales
  • Assessment: Assessment line items and results
  • Resources: Learning resources linked to courses

Installation

npm install @timeback/oneroster

Quick Start

import { OneRosterClient } from '@timeback/oneroster'

// Environment mode (Timeback APIs)
const client = new OneRosterClient({
	env: 'staging', // or 'production'
	auth: {
		clientId: process.env.ONEROSTER_CLIENT_ID!,
		clientSecret: process.env.ONEROSTER_CLIENT_SECRET!,
	},
})

// Or explicit mode (custom OneRoster API)
const customClient = new OneRosterClient({
	baseUrl: 'https://api.example.com',
	auth: {
		clientId: process.env.ONEROSTER_CLIENT_ID!,
		clientSecret: process.env.ONEROSTER_CLIENT_SECRET!,
		authUrl: 'https://auth.example.com/oauth2/token',
	},
})

const { data: students, hasMore } = await client.users.list({ where: { role: 'student' } })
const user = await client.users.get('user-123')

Rostering

Users

client.users.list()
client.users.list({ where: { role: 'teacher' } })
client.users.first({ where: { role: 'administrator' } })
client.users.listAll()
client.users.get(userId)
client.users.create({ givenName, familyName, email, role })
client.users.update(userId, { givenName })
client.users.delete(userId)
MethodReturnsDescription
list()PageResultList users (supports where filter)
first()User | undefinedGet first matching user
listAll()User[]Fetch all pages
get()UserGet user by ID
create()CreateResponseCreate user (returns sourcedIdPairs)
update()voidUpdate user
delete()voidDelete user

Scoped User Operations

Access user-specific data using the callable pattern:
client.users('user-123').demographics()
client.users('user-123').classes()
client.users('user-123').resources()
client.users('user-123').agents()
client.users('user-123').agentFor()
client.users('user-123').addAgent({ agentSourcedId: 'parent-123' })
client.users('user-123').removeAgent('parent-123')
client.users('user-123').createCredential({ type: 'username', username: 'johndoe' })
client.users('user-123').decryptCredential('cred-id')

Students & Teachers

Dedicated read-only resources for role-specific queries:
client.students.list()
client.students.get(studentId)
client.students(studentId).classes()
client.teachers.list()
client.teachers.get(teacherId)
client.teachers(teacherId).classes()

Schools & Organizations

client.schools.list()
client.schools.get(schoolId)
client.orgs.list()

Courses & Classes

client.courses.list()
client.courses(courseId).classes()
client.classes.get(classId)
client.classes(classId).students()
client.classes(classId).teachers()
client.classes(classId).enrollments()

Enrollments

client.enrollments.list()
client.enrollments.list({ where: { status: 'active' } })
client.enrollments.get(enrollmentId)
client.enrollments.create({ user, class, role })

Gradebook

client.gradebook.categories.list()
client.gradebook.categories.get(categoryId)
client.gradebook.lineItems.list()
client.gradebook.lineItems.get(lineItemId)
client.gradebook.lineItems.create({ title, class, category, assignDate, dueDate })
client.gradebook.lineItems(lineItemId).results()
client.gradebook.results.list()
client.gradebook.results.create({ lineItem, student, score, scoreStatus })
client.gradebook.scoreScales.list()

Pagination

All list() methods return PageResult<T> with { data, hasMore, total, nextOffset }.
client.users.list({ offset?, limit? })
client.users.listAll(options?)
client.users.stream(options?)
MethodReturnsDescription
list()PageResult<T>Single page with pagination info
listAll()T[]Auto-fetches all pages
stream()AsyncIterable<T>Memory-efficient streaming iterator

Filtering

Use the where parameter to filter results:
client.users.list({ where: { role: 'student' } })
client.enrollments.list({ where: { status: 'active' } })
client.users.list({ where: { role: 'student', status: 'active' } })

Error Handling

import { NotFoundError, UnauthorizedError } from '@timeback/oneroster/errors'

try {
	const user = await client.users.get('invalid-id')
} catch (error) {
	if (error instanceof NotFoundError) {
		console.error('User not found')
	} else if (error instanceof UnauthorizedError) {
		console.error('Invalid credentials')
	}
	throw error
}

Next Steps