Update one of your students and give them access to this organization
- Bearer token
- Permission
student/update - Per organization
Changes the fields you send and leaves the rest as they are: no field is required, and one you leave out is not cleared. It writes the student’s one record, the one getStudent returns and every organization shares, so a change made here shows everywhere.
Access to this organization. Leave activatedPlatformsThisSeason out and this organization’s slug is added to it, unless it already holds common. The student then shows in listOrgStudents and can be sent a link with createSigninLink. This is how you give a student access, so unlike the reads it does not need them to have it already, and an empty body, {}, does only that. If you do send activatedPlatformsThisSeason, the values you send are added to the stored list, and this organization is added only if you name it. The list only ever grows: nothing is removed, a value it already holds is not added twice, and [] adds nothing.
Fields follow registration’s rules: birth is a date that exists, as DD/MM/YYYY (31/02/2008 is refused), sex is m, f or n, country is an id from listCountries, and grade, city and school take an id or a name. A city name is looked up in the student’s country, and a school name in their country and city: the ones in this body, or else the stored ones. A name or id that matches nothing is refused; nothing is ever created. firstName, lastName, birth and sex can be changed but not cleared: an empty value or null is refused. phone is cleared with "". password is refused here: use setStudentPassword.
Email. A new address sets emailConfirmed back to false, since nobody has confirmed it yet. Sending the address the student already has, in any letter case, changes nothing. An address another student already has is refused.
Sending the same body again leaves the student as the first call did. Answers with the stored record, references as ids; read the student to have them resolved. Only students your account registered can be updated; another account’s student answers 404, like an unknown id.
Parameters
Path parameters
| Name | Type | Description |
|---|---|---|
organizationIdrequired | stringpattern ^[0-9a-f]{24}$ | The organization’s Example |
studentIdrequired | string | The student’s id ( |
Request body
firstNamestringThe student’s first name. Printed on certificates and reports, followed by
lastName.example
JanelastNamestringThe student’s surname. Printed on certificates and reports after
firstName. It cannot be empty.example
DoebirthstringDate of birth as
DD/MM/YYYY, and a date that exists:31/02/2008is refused. An ISO date such as2008-05-14is refused.pattern
^(0[1-9]|[12]\d|3[01])\/(0[1-9]|1[0-2])\/\d{4}$example14/05/2008sexstringOne of
m,forn.one of
mfnexample
femailstringThe student’s email address, stored in lower case. An address belongs to one student on the whole platform, so one already registered, by your account or another, is refused with 409.
format
emailexamplejane.doe@example.comemail2stringLeave this out. Any value but an empty one is refused with 400.
phonestringA phone number, stored as you send it. No format is checked. On an update,
""clears it.example
+1 555 0100countrystringThe
_idof a country, fromlistCountries(GET /v1/country). An id only: a name or an ISO code is refused. Its two-letter code starts the student’susername.pattern
^[0-9a-fA-F]{24}$example6650a1b2c3d4e5f6a7b8c9d1gradestringThe
_idof a grade, fromlistGrades(GET /v1/grade), or its name,1to12. Either way the grade’s_idis what is stored. One that matches no grade is refused with 400. The grade decides which exams the student is offered.example
10schoolstringThe
_idof a school, or its name withincountryandcity, matched without regard to case. There is no list of schools to look one up in: send the name your records hold. One that matches no school is refused with 400; no school is ever created.example
Springfield High SchoolcitystringThe
_idof a city, or its name withincountry, matched without regard to case. There is no list of cities to look one up in: send the name your records hold. One that matches no city is refused with 400; no city is ever created.example
SpringfieldactivatedPlatformsThisSeasonarray of stringOrganization slugs, or 'common' for every organization, to add to the student's list. Nothing is ever removed: a value the list already holds is not added twice, and
[]adds nothing. Leave it out to add this organization, which adds nothing if the list holds 'common'. Send it and only what you name is added, so this organization is added only if you name it.each one of
commonstemhilinguaneogmathcodingmax items
6example["stem"]
Responses
200 OK
Success: message is "Student updated successfully.".
Body
successbooleanrequiredAlways
trueon a success.one of
truemessagestringrequiredexample
Student updated successfully.dataobject · StudentRecordResponserequiredOne of your students as stored, with
country,city,school,grade,supervisorandpartneras ids. What registration, the updates andsetStudentPasswordanswer with; read the student to have them resolved.20 fields of data
_idstringrequiredThe student’s id: what every
studentIdpath parameter and body field takes.example
6650a1b2c3d4e5f6a7b8c9d0mainIdstringOnly on an organization’s own copy of a student, which
linkStudentSupervisoranswers with: there it is the student’s id, and_idis the organization’s own. Absent on every other operation.example
6650a1b2c3d4e5f6a7b8c9d0usernamestringrequiredIssued at registration, never chosen by you: the country’s two-letter code, a letter, then a number. It is how the student signs in and how support refers to the account.
example
XXB1045firstNamestringrequiredThe student’s first name.
example
JanelastNamestringrequiredThe student’s surname.
example
DoefullNamestringrequiredfirstNameandlastNamejoined by a space, kept in step when either changes.example
Jane DoeemailstringrequiredThe student’s email address, in lower case.
example
jane.doe@example.comemailConfirmedbooleanrequiredWhether the student has confirmed
email. It startsfalse, only the student can make ittrue, and changingemailsets it back tofalse. Once it istrue,setStudentPasswordis refused: the account is the student’s.example
falsephonestringA phone number, as you sent it.
example
+1 555 0100birthstringDate of birth,
DD/MM/YYYY.example
14/05/2008sexstringm,forn.one of
mfnexample
fcountrystringThe id of the student’s country.
example
6650a1b2c3d4e5f6a7b8c9d1citystringThe id of the student’s city. A city you sent by name is stored as the id it resolved to.
example
6650a1b2c3d4e5f6a7b8c9d2schoolstringThe id of the student’s school. A school you sent by name is stored as the id it resolved to.
example
6650a1b2c3d4e5f6a7b8c9d3gradestringThe id of the student’s grade. A grade you sent by name is stored as the id it resolved to.
example
6650a1b2c3d4e5f6a7b8c9d4supervisorstringThe id of the student’s supervisor, when one is attached.
example
6650a1b2c3d4e5f6a7b8c9d5partnerstringThe id of the student’s partner, when one is attached.
example
6650a1b2c3d4e5f6a7b8c9d6activatedPlatformsThisSeasonarray of stringrequiredThe organizations the student is active on this season, by
slug;commonmeans every organization. Registration setscommonunless you send a list. The organization-scoped student operations see a student only when this lists that organization orcommon, and updating a student through one adds that organization.example
["common"]createdAtstringrequiredWhen the student was registered.
format
date-timeexample2026-09-01T09:30:00.000ZupdatedAtstringrequiredWhen the record last changed.
format
date-timeexample2026-09-02T14:05:00.000Z
Headers
X-RateLimit-LimitintegerRequests your account may make to this operation per window (100).
X-RateLimit-RemainingintegerRequests left in the current window.
X-RateLimit-ResetintegerSeconds until the current window ends.
Example
{
"success": true,
"message": "Student updated successfully.",
"data": {
"_id": "6650a1b2c3d4e5f6a7b8c9d0",
"mainId": "6650a1b2c3d4e5f6a7b8c9d0",
"username": "XXB1045",
"firstName": "Jane",
"lastName": "Doe",
"fullName": "Jane Doe",
"email": "jane.doe@example.com",
"emailConfirmed": false,
"phone": "+1 555 0100",
"birth": "14/05/2008",
"sex": "f",
"country": "6650a1b2c3d4e5f6a7b8c9d1",
"city": "6650a1b2c3d4e5f6a7b8c9d2",
"school": "6650a1b2c3d4e5f6a7b8c9d3",
"grade": "6650a1b2c3d4e5f6a7b8c9d4",
"supervisor": "6650a1b2c3d4e5f6a7b8c9d5",
"partner": "6650a1b2c3d4e5f6a7b8c9d6",
"activatedPlatformsThisSeason": [
"common"
],
"createdAt": "2026-09-01T09:30:00.000Z",
"updatedAt": "2026-09-02T14:05:00.000Z"
}
}400 Bad request
bad_request: The body is not valid JSON, breaks a field’s rules, or has a field this operation does not accept ("property <name> should not exist").bad_request:studentIdis not a well-formed id.bad_request:country,grade,cityorschoolmatches no record, by id or by name, or acityorschoolname was sent for a student with no country (or, for a school, no city) to look it up in.bad_request:emailisnull: an address can be changed, not removed. Any other value that is not an address is refused by the body’s rules ("email must be an email").bad_request:firstName,lastName,birth,sex,phoneoractivatedPlatformsThisSeasonisnull, orfirstNameorlastNameis empty. These can be changed, not removed; clearphonewith"".
When
bad_requestThe body is not valid JSON, breaks a field’s rules, or has a field this operation does not accept ("property <name> should not exist").
bad_requeststudentIdis not a well-formed id.bad_requestcountry,grade,cityorschoolmatches no record, by id or by name, or acityorschoolname was sent for a student with no country (or, for a school, no city) to look it up in.bad_requestemailisnull: an address can be changed, not removed. Any other value that is not an address is refused by the body’s rules ("email must be an email").bad_requestfirstName,lastName,birth,sex,phoneoractivatedPlatformsThisSeasonisnull, orfirstNameorlastNameis empty. These can be changed, not removed; clearphonewith"".
Example
{
"error": {
"code": "bad_request",
"documentation_url": "https://hub.main-team.org/api/errors#bad_request",
"message": "The request was malformed or contained invalid parameters.",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
401 Unauthorized
unauthorized: The token is missing or malformed, is not signed with your account’s apiSecret, breaks the iat and exp rules, has expired or been revoked, or its account is not active. All of these answer the same.
When
unauthorizedThe token is missing or malformed, is not signed with your account’s
apiSecret, breaks theiatandexprules, has expired or been revoked, or its account is not active. All of these answer the same.
Example
{
"error": {
"code": "unauthorized",
"documentation_url": "https://hub.main-team.org/api/errors#unauthorized",
"message": "Authentication is required or the provided credentials are invalid.",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
403 Forbidden
forbidden: The token is valid, but no role on your account allows student/update on the organization in the path, or a role denies it.
When
forbiddenThe token is valid, but no role on your account allows
student/updateon the organization in the path, or a role denies it.
Example
{
"error": {
"code": "forbidden",
"documentation_url": "https://hub.main-team.org/api/errors#forbidden",
"message": "Insufficient role permissions",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
404 Not found
not_found:organizationIdis not the_idof an organization.not_found: No student of yours has thisstudentId. A student registered by another account answers the same.
When
Example
{
"error": {
"code": "not_found",
"documentation_url": "https://hub.main-team.org/api/errors#not_found",
"message": "Organization not found!",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
409 Conflict
conflict: email is already another student’s address. The answer does not say whose.
When
conflictemailis already another student’s address. The answer does not say whose.
Example
{
"error": {
"code": "conflict",
"documentation_url": "https://hub.main-team.org/api/errors#conflict",
"message": "That email address is already registered.",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
413 Payload too large
payload_too_large: The body is larger than 100 kB.
When
payload_too_largeThe body is larger than 100 kB.
Example
{
"error": {
"code": "payload_too_large",
"documentation_url": "https://hub.main-team.org/api/errors#payload_too_large",
"message": "request entity too large",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
415 Unsupported media type
unsupported_media_type: The body declares a charset that is not a UTF one (send UTF-8), or a Content-Encoding other than gzip, deflate or br.
When
unsupported_media_typeThe body declares a charset that is not a UTF one (send UTF-8), or a
Content-Encodingother than gzip, deflate or br.
Example
{
"error": {
"code": "unsupported_media_type",
"documentation_url": "https://hub.main-team.org/api/errors#unsupported_media_type",
"message": "unsupported charset \"ISO-8859-1\"",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
429 Too many requests
too_many_requests: Your account has made more than 100 requests to this operation in the current 60-second window. Wait the seconds in Retry-After before sending again.
When
too_many_requestsYour account has made more than 100 requests to this operation in the current 60-second window. Wait the seconds in
Retry-Afterbefore sending again.
Headers
Retry-AfterintegerSeconds to wait before sending again; a request sent sooner is refused too.
Example
{
"error": {
"code": "too_many_requests",
"documentation_url": "https://hub.main-team.org/api/errors#too_many_requests",
"message": "Too many requests to this operation. Wait the number of seconds in Retry-After, then try again.",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.
500 Internal error
internal_error: Something failed on our side. Retry later, and quote request_id if it goes on.
When
internal_errorSomething failed on our side. Retry later, and quote
request_idif it goes on.
Example
{
"error": {
"code": "internal_error",
"documentation_url": "https://hub.main-team.org/api/errors#internal_error",
"message": "An unexpected error occurred.",
"request_id": "0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8e"
}
}Fields of the error body
errorobject · ErrorDetailrequiredWhat went wrong.
5 fields of error
codestringrequiredA stable machine code: branch on this. Each one is explained at
documentation_url.one of
invalid_emailbad_requestunauthorizedforbiddennot_foundconflictpayload_too_largeunsupported_media_typeunprocessable_entitytoo_many_requestsinternal_errorservice_unavailableexample
not_foundmessagestringrequiredWritten for a person, and may change: never branch on it.
example
Not found!documentation_urlstringrequiredWhere this code is explained.
format
uriexamplehttps://hub.main-team.org/api/errors#not_foundrequest_idstringrequiredThis request’s id, also sent as the
X-Request-Idresponse header: the one you sent, when it was acceptable, or else one the API made. Quote it when you report a problem.example
0b5c6d0e-8f7a-4b1c-9d2e-3f4a5b6c7d8edetailsobjectPresent only where an operation says so, and then with the shape that operation documents — the rows it could not accept, say. Treat it as absent everywhere else, and ignore a
detailsyou do not recognise.