Skip to content
API documentation
View as MarkdownOpen in Claude

Help

Glossary

Each term is defined once, in the sense this documentation uses it. The link after a definition goes to the page that covers the topic in full. Terms are grouped by topic and sorted alphabetically within each group.

Access and authentication

Action

The first part of a role: what the role lets you do, written <resource>/<operation>, for example student/read or application/create. A * in either segment matches any value there (student/*, */read, */*). A * on its own matches every action. The two sides must have the same number of segments. For example, student/* grants student/read but not a deeper action. See Permissions.

Allow and disallow

The effect of a role. An account needs a matching allow role for a request to go through. A matching disallow role always wins over any number of matching allow roles, so it is how you carve an exception out of a broad grant, for example "everything except deleting applications".

API account

The identity your integration uses to call the API. An operator creates it and gives you its apiKey and apiSecret. Everything you create through the API belongs to this account, including students and applications. Another account, even a replacement account for the same company, cannot see those records. See Authentication.

apiKey

The public identifier of your API account: key_ followed by 24 letters, digits, - or _. You put it in the kid header of every token and again as the token's sub claim. It is not a secret, but it is useless without the matching apiSecret.

apiSecret

Your signing key: secret_ followed by a long random string. You get it once, when the account is created, and it cannot be recovered or shown again. It signs your tokens and must never leave your servers. See Security.

authorized

The third part of a role. If it is empty or holds your own account's _id, the role applies to your account. If it holds any other id, the role does nothing, and this is true for disallow roles too.

Clock skew

How far your server's clock may disagree with the API's clock: 30 seconds. The API still accepts a token for 30 seconds after its exp. It also accepts an iat up to 30 seconds in the future, but no further.

iat and exp

The two required time claims of a token, in whole seconds since the Unix epoch. iat is when you signed the token and exp is when it stops working. exp must be later than iat, and exp - iat may be at most 3600 seconds.

kid

The JWT header field that names the key a token was signed with. For this API it is always your apiKey. The API reads it to decide which account's secret to check the signature against.

Operator

A Main Team staff member who manages API accounts. Operators create accounts, set their roles, and deactivate them. You cannot do any of this yourself through the API. Write to support to ask.

Permission

What a single operation requires: an action on the organization the request acts on. For example, POST /v1/{organizationId}/application requires application/create on that organization. Each operation's reference page names its permission. See Permissions.

Revocation

Ending one token before its exp, with POST /v1/api-account/revoke-token. The API refuses the revoked token from then on. Your other tokens and your apiSecret keep working.

Role

One entry in your account's list of grants: { effect, action, target, authorized }. Operators set roles. You can read yours with GET /v1/api-account/validate-me. See Permissions.

Target

The second part of a role: which organization the role applies to. It is either * (every organization) or one slug: mto, stem, hilingua, neo, gmath or coding. Operations without an organization in their path act on mto, so they need a role whose target is mto or *.

Token

The credential you send with every request, as Authorization: Bearer <token>. It is a JWT that you sign yourself with HS256 and your apiSecret. The API has no endpoint that issues tokens. See Authentication and Token handling.

Organizations and students

Activated organizations

The organizations a student may be used on, stored on the student as activatedPlatformsThisSeason. The value common means every organization, and it is the default at registration. Otherwise the list holds organization slugs. A student must be activated for an organization before you can create a sign-in link there, and before they appear in that organization's student list. See Students.

Bulk registration

Registering 30 to 1000 students in one request with createStudentImport. The batch is checked before it is accepted and then registered in the background, all of it or none of it. See Bulk registration.

Core record

The main copy of a student, which Main Team keeps under the mto organization. Registration creates it. It holds the profile, the username and the password. The operations without an organization in their path act on the core record. Its _id is the student id you use everywhere in this API. See Organizations.

Email confirmation

Whether the student has proven they receive email at their address, returned as emailConfirmed. Students you register start out unconfirmed. Changing a student's email address through the API resets it to false. It does not stop a sign-in link from working, but the panel asks an unconfirmed student to confirm their address with an emailed 6-digit code, on every page until they do, My Exams included, so they must confirm before starting an exam. A student already inside an exam room is not interrupted. Only the confirmation on the core record counts. Once it is true, you can no longer set the student's password.

Import

One batch sent to createStudentImport, and the record of what happened to it. Read it with getStudentImport: status runs from queued through running to succeeded or failed, every row carries its student's _id once it has succeeded, and the import stops being readable 30 days after it finishes.

Flat operation

An operation whose path has no {organizationId}, such as GET /v1/student or GET /v1/country. It acts on the core record, and its permission is checked against the mto target.

mainId

The core-record id of a person, carried on every person that an organization's data returns. Each organization keeps its own copy of a student with a different _id, so the user._id on an application is that organization's id for the student. mainId is the id you registered them with, so match your records on mainId. See Identifiers.

Organization

One of the platforms a student can take part in. mto is the core platform, and the flat operations act on it. stem, hilingua, neo, gmath and coding are the olympiads, and you address each one by its organization id. GET /v1/organization lists the organizations you can put in a path. See Organizations.

Organization copy

An organization's own record of a student, linked to the core record by mainId. It is created the first time the student opens a sign-in link for that organization, and the API cannot create it any other way. You need it before you can create applications, list a student's applications, certificates or reports, or link a supervisor on that organization.

Organization id

The _id of an organization, as returned by GET /v1/organization: 24 hexadecimal characters. It is the {organizationId} in a path. It is never the slug. An id that names no organization, or names one that GET /v1/organization does not list, answers 404 with the message Organization not found!.

Ownership

The rule that your account can only act on students it registered itself, and on records reached through those students, such as applications, certificates and reports. Another account's record answers exactly like a missing one: 404 not_found. This means a response never reveals that someone else's record exists.

Slug

The short, lower-case name of an organization: mto, stem, hilingua, neo, gmath or coding. Slugs appear in role targets, where mto is one of them, in activatedPlatformsThisSeason, which takes the other five and common, and in some messages. Paths never take a slug. They take the organization id.

Supervisor

A teacher or coordinator account on one organization. You link a student to a supervisor by the supervisor's username with PUT /v1/{organizationId}/student/{studentId}/supervisor. The link applies to that organization only. The API never creates supervisor accounts. See Supervisors.

Username

The student's platform login name, issued at registration and never changed through the API. It is the country's two-letter code, one letter (never P, S or T), and a sequence number that starts at 1000, for example XXB1045 with the country's code in place of XX. It is not a secret, so a password may not contain it.

Exams and applications

Application

A student's entry for one exam on one organization. You create one with POST /v1/{organizationId}/application, giving the student and the exam. Every application has a payment. See Applications.

Available exams

The exams one student may apply for on one organization, returned by GET /v1/{organizationId}/exam/available/{studentId} as a tree: category, then session, then language. Each leaf carries the exam as matchedExam. The student's grade and country narrow the list, and so do the sittings the student already holds. It follows the same rules as the exam picker in the student panel, and it works before the student has ever signed in to the organization. See Exams.

Exam

One paper: a category, sat in one language, at one session. Its _id is what you put in examId.

Exam category

A subject or competition line within an organization, for example Science or AI Challenge. Exams belong to one category. An exam in an inactive category is never open.

Grade

The school year a student is in, stored on the student and required at registration. Every exam accepts a fixed set of grades, so a student is offered only exams for their grade. Grade ids are the same on every organization. See Reference data.

matchedExam

The exam at a leaf of the available exams tree. matchedExam._id is the examId you send to create or move an application.

Move

Changing which exam an application is for, with PUT /v1/{organizationId}/application/{applicationId}. Moves are how you change an application's language or date. They are refused once the exam has started, when the student could not apply for the new exam, and in a few other cases, such as a paid application moving to an exam with a different price. See Change an application.

Open exam

An exam that is still accepting applications. Its session date is in the future, its category is active, and applications to it are not switched off. Only open exams are listed by GET /v1/{organizationId}/exam or can be applied for.

Payment

The record of what an application costs and whether it has been paid, returned inside the application. The API creates it with the application, but it never charges or refunds anyone. An exam with no price, or a price of 0, gets a payment with amount 0 and status paid.

Session

One date on which exams are sat, also called a sitting. A student cannot hold two exams in the same category on the same session.

Settled payment

A payment with status paid and an amount above 0, meaning money has actually been paid. A free exam's payment is not settled, even though its status is paid. An application with a settled payment cannot be deleted, and it can be moved only to an exam with the same price.

Sign-in

A URL that signs one of your students into one organization's student panel when their browser opens it. It is valid for 120 seconds and works once. You create it with POST /v1/{organizationId}/auth/signin and redirect the browser to it at once. See Sign-in links.

Redirect

The optional path inside the organization where the student lands after signing in, for example /dashboard. It must start with a single / (so // is refused) and contain no whitespace and no backslashes. The text {userId} in it is replaced with the student's id on that organization. Without it, the student lands on the organization's home page.

Results

Certificate

A PDF certificate that an organization issues to a student, for example for taking part or for an award. You list a student's certificates, then download each one. See Certificates and reports.

Released document

A certificate or report that the organization has published. Only released documents are listed or downloaded. A document that is not released yet, not yours, or has no file answers the same 404.

Report

A PDF results report for one of a student's applications. It is listed and downloaded like a certificate. A report that was withdrawn is treated as not released.

shortId

A short identifier that certificates and reports carry in their shortId field, next to their _id. The download operations accept either one.

Group challenges

Grade group

A set of grades that form groups together in a group challenge. Every member of a group comes from the same grade group, and a student whose grade is in none of a challenge's grade groups cannot take part. See Group challenges.

Group

A handful of students, formed by their teacher in the panel, who work through a group challenge together. It is prepared (awaiting_payment, draft), confirmed by the teacher (finalized), and completed once its work is sent. See Group challenges.

Group challenge

A project an organization runs for groups of students between two dates (windowStart to windowEnd), worked through in steps. You can read where your students stand and submit steps for them. See Group challenges.

Step

One stage of a group challenge, such as a proposal or a video. A group's steps open one after another: a step is locked until the one before it is submitted, open while the group uploads work for it, and submitted once sent. See Group challenges.

Requests and responses

documentation_url

The link, included in every error, to the explanation of its error code on the Errors page.

Envelope

The fixed shape every JSON response takes. On success it is { success, message, data, pagination? }. On failure it is { error: { code, message, documentation_url, request_id } }. One operation, GET /v1/api-account/validate-me, returns its object without the success envelope. See Requests and responses.

Error code

The stable, machine-readable name of an error, such as unauthorized or conflict, in error.code. Your code should branch on the HTTP status and this code, never on the message text. See Errors.

Idempotent

An operation you can safely repeat because doing it twice has the same effect as doing it once. Creating an application for the same student and exam twice returns the existing application. Registering a student twice does not: the second attempt is refused. See Retries and idempotency.

operationId

The stable name of an operation in the reference, such as createApplication. Its page is at /api/reference/ followed by the name in kebab case (/api/reference/create-application). Quote it when you ask for help.

Pagination

How list operations return their results one page at a time. You choose the page with page (default 1) and limit (default 20, at most 100), and the response carries pagination: { page, limit, total, totalPages }. See Pagination.

Rate limit

How many requests your account may make: 100 requests per 60 seconds to each operation, and each operation is counted on its own. Past that, the API answers 429 with a Retry-After header. See Rate limits.

Request id

The id of one request. It comes back in the X-Request-Id header of every response and as error.request_id in every error. You may send your own id in X-Request-Id: up to 256 letters, digits and . _ : ; = + / @ -. Any other value is replaced with an id the API generates. Quote the request id when you contact support. It is how a single request is found in our logs.

Search the API documentation

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