Skip to content
API documentation

Help

Changelog

Every change to the API contract, by version, newest first: operations, request and response fields, error codes, and the rules your integration relies on. A change that can break code written against these pages is marked Breaking.

Versions follow semantic versioning. A minor version adds without breaking, a patch version fixes, and a new major version gets a new path prefix; every 1.x version is served under /v1. Ignore response fields your code does not recognise: new ones can arrive in any minor version.

1.2.0

Nine new operations under one new tag, Group challenges, behind two new permissions, group-challenge/read and group-challenge/submit. Nothing that worked against 1.1.1 changes.

Added

  • Group challenges, a new resource under /v1/{organizationId}/group-challenge with the tag "Group challenges" and the permission group-challenge/read (also granted by */read, */* and *): listGroupChallenges and getGroupChallenge read the challenges an organization runs; listGroupChallengeStudents and getGroupChallengeStudent say where each of your students stands (eligible by grade, in a group, the group's state) and give the panelPath to send them to with createSigninLink; listGroupChallengeGroups and getGroupChallengeGroup read the groups your students are in, with each step and its files; listGroupChallengeActivity lists what happened in a group. Only your own students are named: every other person is their role alone. The operations answer 404 on an organization where group challenges are not switched on.
  • Submitting group challenge work for one of your students, behind the new permission group-challenge/submit (also granted by */* and *, not by */read): submitGroupChallengeStep submits a group's open step and opens the next, and submitGroupChallengeWork sends the group's finished work and e-mails its members and teacher. Both take { "studentId": "<studentId>" }, a student of yours who is an active member of the group, and are recorded in the group's history as your account acting for them. Repeating a submit that already happened answers 200 with changed: false.

Changed

Release notes for 1.2.0

1.1.1

A documentation release. The published agent kit now carries six skills instead of two, including one written against bulk registration, and none of them describes anything but this API. Every call that worked against 1.1.0 works unchanged.

Changed

  • The agent kit published at https://hub.main-team.org/api/skills now has six skills instead of two, all of them about this REST API: integrating-main-team-api (tokens, the envelopes, pagination, rate limits, retries and idempotency, polling, every error code), registering-a-main-team-student, registering-main-team-students-from-spreadsheets, enrolling-students-in-olympiad-exams-via-api, downloading-results-and-certificates-via-api and managing-api-access-and-tokens. The spreadsheet skill is now written against createStudentImport and getStudentImport: it builds one request body of 30 to 1000 rows, reads the 422 row list, and polls the import until it has succeeded or failed. Nothing in the kit describes the MCP server, which is a separate service. No operation, field, permission or error code changed.

Release notes for 1.1.1

1.1.0

Three new operations — bulk registration, its status, and a registration pre-check — with an email filter on listStudents, a signedIn field and filter on listOrgStudents, and an optional details object on error bodies. Nothing that worked against 1.0.1 changes.

Added

  • createStudentImport: POST /v1/student/import registers 30 to 1000 students in one request. Every row follows registerStudent's rules and takes everything it takes except password, plus an optional externalRef of your own that is echoed back. The whole batch is checked before anything is queued; the answer is 202 with the import and a Location header, and the students are registered in the background. They are written in one transaction: a batch registers every row or registers nothing, so there is no partial import to reconcile. Each student gets the same welcome email registerStudent sends. Limits: one unfinished import per account (409 otherwise), 10 requests an hour, and bodies up to 1.5 MB on this operation where every other takes 100 kB. Sending the same rows again inside 24 hours answers with the import you already have rather than a second one. It needs student/create on mto, the permission registration needs.
  • getStudentImport: GET /v1/student/import/{importId} returns one of your imports and one page of its rows, with page and limit. status is queued, running, succeeded, failed or cancelled; on succeeded every row carries the student's _id, and on anything else no student of that batch was registered. An import stops being readable 30 days after it finishes and then answers 404, as does one another account sent. It needs student/create on mto.
  • Error bodies may carry an optional details object, and createStudentImport is the first operation to send one: its 422 puts every row it cannot register in error.details.rows, each with its position, the property at fault and a code to branch on. Ignore a details you do not recognise; no other operation sends one.
  • checkStudentRegistration: POST /v1/student/check runs the checks registerStudent makes before it creates anything, on the same body without password, and answers 200 with what they found: valid; every country, grade, city or school that matches nothing, with the message registration would refuse it with; the _id each reference resolves to; and whether one of your students already has the email address, with that student's _id. Nothing is created and no username is issued. It needs student/create on mto, the permission registration needs. Only your own students are checked for the address, so an address a student on another account holds is still refused by registerStudent alone.
  • listStudents: an optional email query parameter lists only your students who have one of up to 100 addresses, separated by commas, matched exactly and without regard to case. A value that is not such a list is refused with 400 bad_request.
  • listOrgStudents: each student carries signedIn, whether they have signed in to that organization at least once, and an optional signedIn query parameter, true or false, lists only the students who have or only those who have not. Any other value is refused with 400 bad_request. createApplication and linkStudentSupervisor on an organization need the student to have signed in there once.

Release notes for 1.1.0

1.0.1

The sandbox is live and the contract names it as a second server, and the panel now requires students to confirm their email address. No operation, field or error code changes.

Added

  • The contract's server list names the sandbox, https://apisnd.main-team.org, after production, marked x-environment: sandbox. Production stays the first entry, so a tool that takes the first server still calls production. No operation changes.

Changed

  • The sandbox is live at https://apisnd.main-team.org/v1. It runs the same release as production, with separate accounts issued by an operator, seeded reference data with production's organization ids, no emails and test-mode payments. Registration is open there, with the same permissions and rate limits as in production. The official client libraries accept only the production base URL, so call the sandbox over HTTPS directly. The "Try it" console on the reference pages works against the sandbox with a token you paste. Students pay in the sandbox's panels with Stripe's test cards, such as 4242 4242 4242 4242; the Environments page lists them. Test cards never work in production.
  • createSigninLink: a student whose email address is not confirmed must now confirm it before they can use the panel, My Exams included, so they confirm before they can start an exam. The panel asks for a 6-digit code on every page until the address is confirmed, and the student can no longer put it off; signing out is the only way out. A student already inside an exam room is not interrupted. Only the confirmation on the student's core record counts. A code is valid for 15 minutes, and a new one can be requested after 60 seconds. The sandbox sends no emails, so its panels don't ask. Have your students confirm well before an exam day, for example right after their first sign-in. The request, its answers and the link are unchanged.
  • Documentation corrections: the pages that called the sandbox planned now describe it as it runs, and every page that called the panel's email confirmation prompt optional now describes it as required. The pages no longer write a current version number into their text: the API reference shows the version they describe, and the changelog lists every version.

Release notes for 1.0.1

1.0.0

Initial release of the v1 partner API, with 35 operations for students, sign-in links, exams, applications, certificates and reports.

Added

Release notes for 1.0.0

Search the API documentation

Guides, endpoints by name, path or permission, and error codes such as not_found.