Skip to Content
Portal API (v1)

OneRoster CSV packages

Send a OneRoster 1.2 CSV package so the portal takes in seasons, students and enrollments.

Many student information systems export OneRoster CSV packages (one .zip file). The portal takes them in two ways:

  • School staff upload the package under Kết nối hệ thống (always previewed before it is applied).
  • The school's system sends it over the API: POST /integration/v1/imports/oneroster, scope imports:write.

Sending over the API

The body is the zip file itself, Content-Type: application/zip, up to 20 MB.

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/zip" \
  -H "Idempotency-Key: 2026-11-13-oneroster" \
  --data-binary @oneroster.zip \
  "https://<trường>.<tên-miền-nền-tảng>/integration/v1/imports/oneroster?dryRun=true"

The answer is 202 with a job; follow it at /jobs/{id} as in Sending data. With ?dryRun=true, counts shows what would change and nothing is saved; drop dryRun to apply. warnings.package holds the package version, each file's mode, how many non-student users were skipped, and notes.

An unreadable package returns 422 with type urn:ttdn:problem:invalid-package and the reason in detail.

What the package needs

FileRequiredUsed for
manifest.csvyesoneroster.version (1.2; 1.1 is also read) and file.<name> = bulk, delta or absent for each file
users.csvyesUsers; only those with the student role are taken
roles.csvfor 1.2Users' roles (1.1 uses the role column of users.csv)
academicSessions.csvnoTerms (term, semester) become seasons
classes.csvnoClasses, to know each enrollment's term
enrollments.csvnoStudents' class enrollments

Other files (orgs.csv, courses.csv, demographics.csv...) are ignored. Each file has a header row and up to 50,000 rows.

How the portal reads it

  • Seasons: each term (term or semester) used by the package's classes becomes a season, placed by its dates as when sending seasons. Without classes, every term is used.
  • Students: everyone with the student role. The student code is taken from identifier, then userIds as {studentCode:SV2026001}, then username. The full name is built in Vietnamese order: familyName middleName givenName. sourcedId becomes externalId.
  • Sign-in: a row with password signs in with a login name (username, or the student code) and that password; without one, with Google using email.
  • Enrollments: a student enrolled in a class is admitted to the season of that class's term. Without enrollments.csv, students are admitted to the open season.
  • Blocking: status = tobedeleted or enabledUser = false blocks the account.
  • No deletion: students missing from a bulk file are left as they are. Deleted terms and enrollments are noted, never applied.
  • Users with other roles (teachers, guardians...) are skipped and counted in ignoredUsers.

When a term is in progress while the school has another season open, the portal creates the new season as upcoming and reports switchSeason in warnings. School staff confirm the switch under Kết nối hệ thống.

On this page