Creating Courses
Structure and create courses with OneRoster
Overview
Courses define what content your app offers and control which students can access it.
Structure is flexible
OneRoster lets you organize content however fits your app.
Some apps use deep hierarchies (Course, Units, Lessons, Activities), others keep it simpler.
The examples below show one common pattern, but you can adapt the depth and granularity to match your content model.
Choose Environment
Decide on Staging for development or Production for live apps.
Authenticate
Get an access token using your Timeback credentials (see Authentication).
Create the Course
POST to /courses with metadata like title, grades, and subjects.
Add Components
POST to /courses/components to organize content into units, modules, or lessons.
Link Resources
POST to /courses/component-resources to attach learning materials to your structure.
Using Playcademy?
Playcademy handles course setup for you.
Run playcademy timeback setup to create and sync courses from your config.
Environments
Find the OneRoster API base URL for your target environment:
| Environment | Base URL |
|---|---|
| Staging | https://api.staging.alpha-1edtech.ai |
| Production | https://api.alpha-1edtech.ai |
Create a Course
Create the top-level course container:
curl -X POST $TIMEBACK_API_URL/ims/oneroster/rostering/v1p2/courses \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "course": { "sourcedId": "math-grade-5", "status": "active", "title": "Math Grade 5", "courseCode": "MATH-G5", "grades": ["05"], "subjects": ["Math"], "org": { "sourcedId": "your-org-id" } } }'const response = await fetch(`${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/courses`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ course: { sourcedId: 'math-grade-5', status: 'active', title: 'Math Grade 5', courseCode: 'MATH-G5', grades: ['05'], subjects: ['Math'], org: { sourcedId: 'your-org-id' }, }, }),})| Field | Description |
|---|---|
sourcedId | Unique identifier for the course |
grades | Array of grade levels (e.g., ["03", "04", "05"]) |
subjects | Array of subjects (e.g., ["Math", "Science"]) |
Unique IDs are required
OneRoster requires you to supply your own unique sourcedId for each resource.
This applies to courses, components, and all other entities. The API will not auto-generate IDs for you.
Add Components
Components let you organize content within a course: units, modules, lessons, or any hierarchy that fits your app.
Components can nest arbitrarily deep via the parent field.
curl -X POST $TIMEBACK_API_URL/ims/oneroster/rostering/v1p2/courses/components \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "courseComponent": { "sourcedId": "unit-1-fractions", "status": "active", "title": "Unit 1: Fractions", "sortOrder": 1, "course": { "sourcedId": "math-grade-5" }, "parent": null } }'const response = await fetch( `${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/courses/components`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ courseComponent: { sourcedId: 'unit-1-fractions', status: 'active', title: 'Unit 1: Fractions', sortOrder: 1, course: { sourcedId: 'math-grade-5' }, parent: null, }, }), },)| Field | Description |
|---|---|
parent | Set to null for top-level components, or reference another component to nest |
sortOrder | Controls display order (1, 2, 3...) |
Attach Resources
Resources are the actual learning materials: e.g. videos, articles, quizzes.
Create a Resource
Define the learning material with vendor info and metadata.
curl -X POST $TIMEBACK_API_URL/ims/oneroster/resources/v1p2/resources \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "resource": { "sourcedId": "math-app-resource", "status": "active", "title": "Math App", "vendorResourceId": "math-app-v1", "vendorId": "your-vendor-id", "applicationId": "your-app-id", "importance": "primary", "metadata": { "type": "interactive", "subject": "Math", "grades": ["05"], "xp": 100 } } }'await fetch(`${TIMEBACK_API_URL}/ims/oneroster/resources/v1p2/resources`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ resource: { sourcedId: 'math-app-resource', status: 'active', title: 'Math App', vendorResourceId: 'math-app-v1', vendorId: 'your-vendor-id', applicationId: 'your-app-id', importance: 'primary', metadata: { type: 'interactive', subject: 'Math', grades: ['05'], xp: 100, }, }, }),})| Field | Description |
|---|---|
vendorResourceId | Your internal identifier for this resource |
vendorId | Your vendor/organization identifier |
applicationId | Your application identifier |
importance | primary or secondary |
metadata.type | Resource type: interactive, video, text, qti, audio, visual |
metadata.xp | XP awarded for completing this resource |
Link Resource to Component
Connect the resource to a component so it appears in the course structure.
curl -X POST $TIMEBACK_API_URL/ims/oneroster/rostering/v1p2/courses/component-resources \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "componentResource": { "sourcedId": "unit-1-math-app", "status": "active", "title": "Math App - Unit 1", "courseComponent": { "sourcedId": "unit-1-fractions" }, "resource": { "sourcedId": "math-app-resource" }, "sortOrder": 1, "lessonType": "quiz" } }'await fetch(`${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/courses/component-resources`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ componentResource: { sourcedId: 'unit-1-math-app', status: 'active', title: 'Math App - Unit 1', courseComponent: { sourcedId: 'unit-1-fractions' }, resource: { sourcedId: 'math-app-resource' }, sortOrder: 1, lessonType: 'quiz', }, }),})| Field | Description |
|---|---|
title | Display name for this link |
courseComponent | Reference to the component this resource belongs to |
resource | Reference to the resource being linked |
sortOrder | Controls display order within the component (1, 2, 3...) |
lessonType | Content type: quiz, placement, test-out, unit-test, or null |
