Skip to Content
Portal API (v1)

Portal API overview

A JSON API for systems without OneRoster to read and send students, seasons and enrollments.

Not every school system supports OneRoster. The portal API (v1) is a plain JSON REST API that lets the school's software read and send internship data: students, seasons, season enrollments, account blocks; and read internship results and approved companies. It also accepts OneRoster CSV packages from software that can export them but has no OneRoster API.

Systems that support OneRoster 1.2 should read through the OneRoster API. Both APIs share connections, scopes and limits.

At a glance

  • Base URL: https://<trường>.<tên-miền-nền-tảng>/integration/v1. The school is identified by the domain; a token only works at the school that issued it.
  • Format: JSON, UTF-8. Instants in ISO 8601 (UTC); dates (startDate, endDate) as YYYY-MM-DD in Vietnam time.
  • Errors: Problem Details (RFC 9457), application/problem+json. See Limits and errors.
  • Machine-readable description: OpenAPI 3.1 at /integration/v1/openapi.json.

Authentication

Every call sends Authorization: Bearer <token>. The school creates a connection under Kết nối hệ thống and chooses one of two kinds:

Connection kindHow it worksSuits
Access tokenOne ttdn_pat_... token sent with every call. Optional expiry (30, 90, 180, 365 days) or none.Simple systems, sync scripts
Client id and secretGet a one-hour token at /oauth/token with OAuth 2.0 Client Credentials, as for OneRoster.Systems used to OAuth 2.0
curl -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://<trường>.<tên-miền-nền-tảng>/integration/v1/seasons"
  • Rotation: the school presses Thay khoá to issue a new token (or secret); the old one keeps working for 24 hours.
  • Revocation: stops every token of the connection at once; it cannot be undone.
  • Address allowlist: if the school lists network addresses (IPv4/IPv6, CIDR such as 203.0.113.0/24), calls from other addresses get 403.

Tokens and secrets are shown only once. Keep them in environment variables or a secret store, never in source code or unencrypted messages.

Scopes

ScopeAllows
students:readRead students
students:writeCreate, update, block, unblock students
seasons:readRead seasons
seasons:writeCreate and update seasons from the school's terms
enrollments:readRead the students of a season
enrollments:writeAdmit students to a season
results:readRead internship results
companies:readRead the companies approved for a season
imports:writeSend OneRoster CSV packages

Checking jobs (/jobs/...) needs any write scope: students:write, enrollments:write or imports:write. A missing scope returns 403 naming the scope needed.

Conventions

Paging

Long lists (/students, /seasons/{id}/enrollments, /seasons/{id}/results) come in pages:

  • limit: 1 to 500, default 100.
  • The body has next: the cursor of the next page, or null at the end. Send it back as ?cursor=<next> with the same parameters.
  • The Link: <...>; rel="next" header (RFC 8288) holds the next page's URL.

Syncing changes

GET /students?updatedSince=2026-11-01T00:00:00Z returns only students changed since then. Store the time each sync starts and use it next time.

Dry runs

Every write accepts ?dryRun=true: the portal checks and answers as if for real but saves nothing.

Safe retries

Batch writes (POST) accept an Idempotency-Key header (1 to 255 characters; a UUID is best). Resending with the same key within 24 hours returns the first answer (with Idempotent-Replayed: true) and creates no new job. The same key with a different body is refused (422).

Identifiers

  • Students are identified by student code (studentCode, case-insensitive).
  • externalId (optional, up to 128 characters) is the record's id in the school's system. Once sent, the portal matches students by it first, then by student code, then by email.
  • Seasons have a portal id and an externalId: the term's id in the school's system.

Endpoint groups

GroupPage
Read seasons, students, enrollments, results, companiesReading data
Send seasons, students, enrollments, blocks; follow jobsSending data
Send OneRoster CSV packagesOneRoster CSV packages

On this page