Skip to Content
Portal API (v1)

Limits and errors

Request and record limits, rate-limit headers and error types of the portal API.

Limits

Limits protect each school's portal from floods (OWASP API Security, API4: unrestricted resource consumption). The numbers below are per-connection defaults; ask the school if you need others.

LimitDefault
Read calls600 a minute
Write calls60 a minute
Concurrent calls4
Records sent2,000 a minute, 50,000 a day
Records a school receives (all connections together)5,000 a minute
Students per batch500
JSON body5 MB
OneRoster CSV package20 MB, 50,000 rows per file
Jobs waiting or running per school4

Jobs are paced by the record limits, so a large package can take a few minutes.

Rate-limit headers

Every answer carries headers from the IETF draft RateLimit header fields for HTTP:

RateLimit-Policy: "read";q=600;w=60
RateLimit: "read";r=596;t=42
  • q: calls allowed per w seconds. r: calls left. t: seconds until the window resets.
  • Writes add a "records" policy for records per minute.

Going over returns 429 Too Many Requests with Retry-After (seconds). Wait that long, then retry; send writes with an Idempotency-Key so retries never create duplicates.

Errors

Errors are Problem Details (RFC 9457), application/problem+json:

{
  "type": "urn:ttdn:problem:invalid-request",
  "title": "The request is not valid",
  "status": 422,
  "detail": "Some students are not valid; nothing was queued.",
  "instance": "/integration/v1/students/batch",
  "errors": [{ "index": 3, "ref": "SV2026004", "message": "studentCode and name are required." }]
}

Act on type; title and detail are for people.

HTTPtype (urn:ttdn:problem:...)When
401unauthorizedMissing, wrong, expired or revoked token, or a token of another school
403insufficient-scopeThe token lacks the scope for this endpoint
403ip-not-allowedCalled from an address outside the school's allowlist
404not-foundNo such season, student or job
409conflict, code-taken, login-name-taken, declared-codeThe data points at another account (email, student code or login name already belongs to someone else)
409season-closedAdmitting students to a closed season
413too-largeBody too large, or more than 500 students
422invalid-requestInvalid data; errors lists each row
422invalid-packageThe OneRoster CSV package cannot be read
422idempotency-key-reused, invalid-idempotency-keyThe Idempotency-Key was used for a different body, or is longer than 255 characters
429rate-limitedOver a limit; wait for Retry-After
500internal-errorPortal error; retry later and tell the school if it persists
503busyThe school already has 4 jobs waiting; wait for Retry-After

What the school sees

Under Kết nối hệ thống, each connection's Theo dõi view shows the school calls per day for 30 days (success, request errors, server errors), records sent and recent errors. The portal counts only; it does not store request contents. Daily numbers are kept 13 months, recent errors 30 days.

On this page