[{"data":1,"prerenderedAt":2979},["ShallowReactive",2],{"api-nav":3,"api-guide:\u002Fapi\u002Fguides\u002Fapi-account":351,"api-spec:guide:\u002Fapi\u002Fguides\u002Fapi-account":2971},[4,28,57,95,115,301,317,331],{"id":5,"title":6,"links":7,"groups":27},"start","Start here",[8,11,15,18,21,24],{"title":9,"to":10},"Overview","\u002Fapi",{"title":12,"to":13,"status":14},"Quickstart","\u002Fapi\u002Fquickstart","available",{"title":16,"to":17,"status":14},"Environments","\u002Fapi\u002Fenvironments",{"title":19,"to":20,"status":14},"Authentication","\u002Fapi\u002Fauthentication",{"title":22,"to":23,"status":14},"Organizations","\u002Fapi\u002Forganizations",{"title":25,"to":26,"status":14},"Permissions","\u002Fapi\u002Fpermissions",[],{"id":29,"title":30,"links":31,"groups":56},"concepts","Concepts",[32,35,38,41,44,47,50,53],{"title":33,"to":34,"status":14},"Requests and responses","\u002Fapi\u002Frequests-and-responses",{"title":36,"to":37,"status":14},"Identifiers","\u002Fapi\u002Fidentifiers",{"title":39,"to":40,"status":14},"Pagination","\u002Fapi\u002Fpagination",{"title":42,"to":43},"Errors","\u002Fapi\u002Ferrors",{"title":45,"to":46,"status":14},"Rate limits","\u002Fapi\u002Frate-limits",{"title":48,"to":49,"status":14},"Retries","\u002Fapi\u002Fretries-and-idempotency",{"title":51,"to":52,"status":14},"Security","\u002Fapi\u002Fsecurity",{"title":54,"to":55,"status":14},"Versioning","\u002Fapi\u002Fversioning",[],{"id":58,"title":59,"links":60,"groups":94},"resources","Guides",[61,64,67,70,73,76,79,82,85,88,91],{"title":62,"to":63,"status":14},"Students","\u002Fapi\u002Fguides\u002Fstudents",{"title":65,"to":66,"status":14},"Bulk registration","\u002Fapi\u002Fguides\u002Fbulk-registration",{"title":68,"to":69,"status":14},"Passwords","\u002Fapi\u002Fguides\u002Fpasswords",{"title":71,"to":72,"status":14},"Supervisors","\u002Fapi\u002Fguides\u002Fsupervisors",{"title":74,"to":75,"status":14},"Reference data","\u002Fapi\u002Fguides\u002Freference-data",{"title":77,"to":78,"status":14},"API account","\u002Fapi\u002Fguides\u002Fapi-account",{"title":80,"to":81,"status":14},"Sign-in links","\u002Fapi\u002Fguides\u002Fsign-in-links",{"title":83,"to":84,"status":14},"Exams","\u002Fapi\u002Fguides\u002Fexams",{"title":86,"to":87,"status":14},"Applications","\u002Fapi\u002Fguides\u002Fapplications",{"title":89,"to":90,"status":14},"Group challenges","\u002Fapi\u002Fguides\u002Fgroup-challenges",{"title":92,"to":93,"status":14},"Certificates and reports","\u002Fapi\u002Fguides\u002Fcertificates-and-reports",[],{"id":96,"title":97,"links":98,"groups":114},"tutorials","Tutorials",[99,102,105,108,111],{"title":100,"to":101,"status":14},"Register and apply","\u002Fapi\u002Ftutorials\u002Fregister-and-apply",{"title":103,"to":104,"status":14},"Send a student to the panel","\u002Fapi\u002Ftutorials\u002Fsend-student-to-panel",{"title":106,"to":107,"status":14},"Change an application","\u002Fapi\u002Ftutorials\u002Fchange-an-application",{"title":109,"to":110,"status":14},"Collect results","\u002Fapi\u002Ftutorials\u002Fcollect-results",{"title":112,"to":113,"status":14},"Token handling","\u002Fapi\u002Ftutorials\u002Ftoken-handling",[],{"id":116,"title":117,"links":118,"groups":125},"reference","Reference",[119,122],{"title":120,"to":121},"All endpoints","\u002Fapi\u002Freference",{"title":123,"to":124},"Sandbox console","\u002Fapi\u002Fconsole",[126,135,145,166,206,212,230,255,271],{"tag":127,"slug":128,"links":129},"Health","health",[130],{"title":131,"to":132,"method":133,"deprecated":134},"Check that the API is up","\u002Fapi\u002Freference\u002Fget-health","GET",false,{"tag":77,"slug":136,"links":137},"api-account",[138,142],{"title":139,"to":140,"method":141,"deprecated":134},"Revoke the token you send, before it expires","\u002Fapi\u002Freference\u002Frevoke-token","POST",{"title":143,"to":144,"method":133,"deprecated":134},"Fetch the API account your token belongs to","\u002Fapi\u002Freference\u002Fget-current-api-account",{"tag":74,"slug":146,"links":147},"reference-data",[148,151,154,157,160,163],{"title":149,"to":150,"method":133,"deprecated":134},"List the countries a student can be registered in","\u002Fapi\u002Freference\u002Flist-countries",{"title":152,"to":153,"method":133,"deprecated":134},"Fetch one country by its id","\u002Fapi\u002Freference\u002Fget-country",{"title":155,"to":156,"method":133,"deprecated":134},"List the grades a student can be registered with","\u002Fapi\u002Freference\u002Flist-grades",{"title":158,"to":159,"method":133,"deprecated":134},"Fetch one grade by its id","\u002Fapi\u002Freference\u002Fget-grade",{"title":161,"to":162,"method":133,"deprecated":134},"List the organizations and their ids","\u002Fapi\u002Freference\u002Flist-organizations",{"title":164,"to":165,"method":133,"deprecated":134},"Fetch one organization by its id","\u002Fapi\u002Freference\u002Fget-organization",{"tag":62,"slug":167,"links":168},"students",[169,172,175,178,181,184,187,191,194,197,200,203],{"title":170,"to":171,"method":133,"deprecated":134},"List your students","\u002Fapi\u002Freference\u002Flist-students",{"title":173,"to":174,"method":141,"deprecated":134},"Register a student","\u002Fapi\u002Freference\u002Fregister-student",{"title":176,"to":177,"method":141,"deprecated":134},"Check a registration without registering the student","\u002Fapi\u002Freference\u002Fcheck-student-registration",{"title":179,"to":180,"method":141,"deprecated":134},"Register many students at once","\u002Fapi\u002Freference\u002Fcreate-student-import",{"title":182,"to":183,"method":133,"deprecated":134},"Follow a batch of students you sent","\u002Fapi\u002Freference\u002Fget-student-import",{"title":185,"to":186,"method":133,"deprecated":134},"Fetch one of your students","\u002Fapi\u002Freference\u002Fget-student",{"title":188,"to":189,"method":190,"deprecated":134},"Update one of your students","\u002Fapi\u002Freference\u002Fupdate-student","PUT",{"title":192,"to":193,"method":190,"deprecated":134},"Set the sign-in password of one of your students","\u002Fapi\u002Freference\u002Fset-student-password",{"title":195,"to":196,"method":133,"deprecated":134},"List your students who can use this organization","\u002Fapi\u002Freference\u002Flist-org-students",{"title":198,"to":199,"method":133,"deprecated":134},"Fetch one of your students, if they can use this organization","\u002Fapi\u002Freference\u002Fget-org-student",{"title":201,"to":202,"method":190,"deprecated":134},"Update one of your students and give them access to this organization","\u002Fapi\u002Freference\u002Fupdate-org-student",{"title":204,"to":205,"method":190,"deprecated":134},"Link one of your students to a supervisor on this organization","\u002Fapi\u002Freference\u002Flink-student-supervisor",{"tag":80,"slug":207,"links":208},"sign-in-links",[209],{"title":210,"to":211,"method":141,"deprecated":134},"Create a single-use sign-in link for one of your students","\u002Fapi\u002Freference\u002Fcreate-signin-link",{"tag":83,"slug":213,"links":214},"exams",[215,218,221,224,227],{"title":216,"to":217,"method":133,"deprecated":134},"List the exams open for applications","\u002Fapi\u002Freference\u002Flist-exams",{"title":219,"to":220,"method":133,"deprecated":134},"List an organization’s exam categories","\u002Fapi\u002Freference\u002Flist-exam-categories",{"title":222,"to":223,"method":133,"deprecated":134},"Fetch one exam category","\u002Fapi\u002Freference\u002Fget-exam-category",{"title":225,"to":226,"method":133,"deprecated":134},"List the exams one of your students can apply to","\u002Fapi\u002Freference\u002Flist-available-exams",{"title":228,"to":229,"method":133,"deprecated":134},"Fetch one exam that is open for applications","\u002Fapi\u002Freference\u002Fget-exam",{"tag":86,"slug":231,"links":232},"applications",[233,236,239,242,245,248,251],{"title":234,"to":235,"method":133,"deprecated":134},"List your students’ applications in this organization","\u002Fapi\u002Freference\u002Flist-applications",{"title":237,"to":238,"method":141,"deprecated":134},"Enter one of your students for an exam","\u002Fapi\u002Freference\u002Fcreate-application",{"title":240,"to":241,"method":133,"deprecated":134},"List your students’ applications for one exam","\u002Fapi\u002Freference\u002Flist-exam-applications",{"title":243,"to":244,"method":133,"deprecated":134},"List one of your students’ applications in this organization","\u002Fapi\u002Freference\u002Flist-student-applications",{"title":246,"to":247,"method":133,"deprecated":134},"Fetch one of your students’ applications","\u002Fapi\u002Freference\u002Fget-application",{"title":249,"to":250,"method":190,"deprecated":134},"Move one of your students’ applications to another exam","\u002Fapi\u002Freference\u002Fmove-application",{"title":252,"to":253,"method":254,"deprecated":134},"Withdraw one of your students from an exam","\u002Fapi\u002Freference\u002Fdelete-application","DELETE",{"tag":256,"slug":257,"links":258},"Documents","documents",[259,262,265,268],{"title":260,"to":261,"method":133,"deprecated":134},"Download a certificate file","\u002Fapi\u002Freference\u002Fdownload-certificate",{"title":263,"to":264,"method":133,"deprecated":134},"List one of your students’ released certificates","\u002Fapi\u002Freference\u002Flist-student-certificates",{"title":266,"to":267,"method":133,"deprecated":134},"Download a result report file","\u002Fapi\u002Freference\u002Fdownload-report",{"title":269,"to":270,"method":133,"deprecated":134},"List one of your students’ released result reports","\u002Fapi\u002Freference\u002Flist-student-reports",{"tag":89,"slug":272,"links":273},"group-challenges",[274,277,280,283,286,289,292,295,298],{"title":275,"to":276,"method":133,"deprecated":134},"List the group challenges an organization runs","\u002Fapi\u002Freference\u002Flist-group-challenges",{"title":278,"to":279,"method":133,"deprecated":134},"Fetch one group challenge","\u002Fapi\u002Freference\u002Fget-group-challenge",{"title":281,"to":282,"method":133,"deprecated":134},"List the groups your students are in for a group challenge","\u002Fapi\u002Freference\u002Flist-group-challenge-groups",{"title":284,"to":285,"method":133,"deprecated":134},"Fetch one group, with its steps and files","\u002Fapi\u002Freference\u002Fget-group-challenge-group",{"title":287,"to":288,"method":133,"deprecated":134},"List what has happened in one group","\u002Fapi\u002Freference\u002Flist-group-challenge-activity",{"title":290,"to":291,"method":141,"deprecated":134},"Send a group’s finished work for one of your students","\u002Fapi\u002Freference\u002Fsubmit-group-challenge-work",{"title":293,"to":294,"method":141,"deprecated":134},"Submit one step of a group for one of your students","\u002Fapi\u002Freference\u002Fsubmit-group-challenge-step",{"title":296,"to":297,"method":133,"deprecated":134},"List your students’ eligibility and groups for a group challenge","\u002Fapi\u002Freference\u002Flist-group-challenge-students",{"title":299,"to":300,"method":133,"deprecated":134},"Fetch one of your students’ eligibility and group for a group challenge","\u002Fapi\u002Freference\u002Fget-group-challenge-student",{"id":302,"title":303,"links":304,"groups":316},"clients","Clients",[305,307,310,313],{"title":9,"to":306,"status":14},"\u002Fapi\u002Fclients",{"title":308,"to":309,"status":14},"Node.js","\u002Fapi\u002Fclients\u002Fnode",{"title":311,"to":312,"status":14},"PHP","\u002Fapi\u002Fclients\u002Fphp",{"title":314,"to":315,"status":14},"Build your own","\u002Fapi\u002Fclients\u002Fbuild-your-own",[],{"id":318,"title":319,"links":320,"groups":330},"agents","AI agents",[321,324,327],{"title":322,"to":323},"AI connections","\u002Fapi\u002Fmcp",{"title":325,"to":326},"What it can do","\u002Fapi\u002Fmcp\u002Ftools",{"title":328,"to":329},"Agent skills","\u002Fapi\u002Fskills",[],{"id":332,"title":333,"links":334,"groups":350},"help","Help",[335,338,341,344,347],{"title":336,"to":337,"status":14},"Glossary","\u002Fapi\u002Fglossary",{"title":339,"to":340,"status":14},"FAQ","\u002Fapi\u002Ffaq",{"title":342,"to":343,"status":14},"Troubleshooting","\u002Fapi\u002Ftroubleshooting",{"title":345,"to":346,"status":14},"Support","\u002Fapi\u002Fsupport",{"title":348,"to":349},"Changelog","\u002Fapi\u002Fchangelog",[],{"id":352,"title":353,"body":354,"description":2961,"extension":2962,"meta":2963,"navTitle":77,"navigation":1250,"operations":2964,"order":2967,"path":78,"section":58,"seo":2968,"status":14,"stem":2969,"__hash__":2970},"apiGuides\u002Fapi\u002Fguides\u002Fapi-account.md","Your API account",{"type":355,"value":356,"toc":2947},"minimark",[357,361,416,427,432,460,532,545,549,554,597,911,939,944,1084,1091,1107,1111,1117,1216,1222,1753,2201,2217,2220,2231,2261,2315,2322,2335,2339,2381,2393,2397,2412,2416,2507,2513,2686,2909,2912,2917,2921,2943],[358,359,360],"p",{},"Two routes act on the API account your token belongs to:",[362,363,364,380],"table",{},[365,366,367],"thead",{},[368,369,370,374,377],"tr",{},[371,372,373],"th",{},"Route",[371,375,376],{},"What it does",[371,378,379],{},"Operation",[381,382,383,401],"tbody",{},[368,384,385,392,395],{},[386,387,388],"td",{},[389,390,391],"code",{},"GET \u002Fv1\u002Fapi-account\u002Fvalidate-me",[386,393,394],{},"Returns the account the token belongs to, with its roles.",[386,396,397],{},[398,399,400],"a",{"href":144},"Get the current API account",[368,402,403,408,411],{},[386,404,405],{},[389,406,407],{},"POST \u002Fv1\u002Fapi-account\u002Frevoke-token",[386,409,410],{},"Revokes the token you send it with, and only that token.",[386,412,413],{},[398,414,415],{"href":140},"Revoke a token",[358,417,418,419,423,424,426],{},"Neither route changes your account itself. There is no route to create an account, change its roles,\nrotate its secret or deactivate it. An operator does all of that, and you can ask for it at\n",[398,420,422],{"href":421},"mailto:info@main-team.org","info@main-team.org",". How to get credentials and sign a token is on\n",[398,425,19],{"href":20},".",[428,429,431],"h2",{"id":430},"permission","Permission",[358,433,434,435,438,439,441,442,445,446,449,450,445,453,455,456,459],{},"Both routes need the action ",[389,436,437],{},"api\u002F*"," on the core record. The action is written with a wildcard, so\nonly a role whose action is ",[389,440,437],{},", ",[389,443,444],{},"*\u002F*"," or ",[389,447,448],{},"*"," grants it, with target ",[389,451,452],{},"mto",[389,454,448],{},". A role such as\n",[389,457,458],{},"student\u002F*"," does not.",[362,461,462,479],{},[365,463,464],{},[368,465,466,469],{},[371,467,468],{},"You have",[371,470,471,474,475,478],{},[389,472,473],{},"validate-me"," and ",[389,476,477],{},"revoke-token"," answer",[381,480,481,494,516],{},[368,482,483,489],{},[386,484,485,486,488],{},"A valid token and the ",[389,487,437],{}," permission",[386,490,491],{},[389,492,493],{},"200",[368,495,496,501],{},[386,497,498,499],{},"A valid token, but no role that grants ",[389,500,437],{},[386,502,503,506,507,441,513],{},[389,504,505],{},"403",", code ",[398,508,510],{"href":509},"\u002Fapi\u002Ferrors#forbidden",[389,511,512],{},"forbidden",[389,514,515],{},"Insufficient role permissions",[368,517,518,521],{},[386,519,520],{},"No token, or a token that fails any check",[386,522,523,506,526],{},[389,524,525],{},"401",[398,527,529],{"href":528},"\u002Fapi\u002Ferrors#unauthorized",[389,530,531],{},"unauthorized",[533,534,536],"callout",{"type":535},"note",[358,537,538,539,541,542,544],{},"A ",[389,540,505],{}," here still tells you something useful: permissions are checked only after a token has been\naccepted, so a ",[389,543,505],{}," means your token is valid and your account only lacks this one permission.",[428,546,548],{"id":547},"check-your-token-and-account","Check your token and account",[358,550,551,553],{},[389,552,391],{}," is the simplest authenticated call there is. It reads nothing but\nyour token, so it is the right first call for a new integration and the right health check for a\nrunning one.",[555,556,561],"pre",{"className":557,"code":558,"language":559,"meta":560,"style":560},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast","curl \"https:\u002F\u002Fapi.main-team.org\u002Fv1\u002Fapi-account\u002Fvalidate-me\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n","bash","",[389,562,563,580],{"__ignoreMap":560},[564,565,568,572,576],"span",{"class":566,"line":567},"line",1,[564,569,571],{"class":570},"soyes","curl",[564,573,575],{"class":574},"sT6z2"," \"https:\u002F\u002Fapi.main-team.org\u002Fv1\u002Fapi-account\u002Fvalidate-me\"",[564,577,579],{"class":578},"sHUrx"," \\\n",[564,581,583,587,590,594],{"class":566,"line":582},2,[564,584,586],{"class":585},"s-5SL","  -H",[564,588,589],{"class":574}," \"Authorization: Bearer ",[564,591,593],{"class":592},"suds8","$TOKEN",[564,595,596],{"class":574},"\"\n",[555,598,602],{"className":599,"code":600,"language":601,"meta":560,"style":560},"language-json shiki shiki-themes github-light-high-contrast github-dark-high-contrast","{\n  \"_id\": \"66f1c2a9e4b0a1d2c3f4a5b6\",\n  \"apiKey\": \"key_Q2x5cGhvbnktZXhhbXBsZS1r\",\n  \"companyName\": \"Northwind Learning\",\n  \"scopes\": [],\n  \"roles\": [\n    { \"effect\": \"allow\", \"action\": \"api\u002F*\", \"target\": \"mto\" },\n    { \"effect\": \"allow\", \"action\": \"*\u002Fread\", \"target\": \"*\" },\n    { \"effect\": \"allow\", \"action\": \"student\u002F*\", \"target\": \"mto\" },\n    { \"effect\": \"allow\", \"action\": \"student\u002Fupdate\", \"target\": \"*\" },\n    { \"effect\": \"allow\", \"action\": \"auth\u002Fsignin\", \"target\": \"*\" },\n    { \"effect\": \"allow\", \"action\": \"application\u002F*\", \"target\": \"*\" },\n    { \"effect\": \"disallow\", \"action\": \"application\u002Fdelete\", \"target\": \"*\" }\n  ],\n  \"isActive\": true\n}\n","json",[389,603,604,609,624,637,650,659,668,705,736,766,796,826,856,888,894,905],{"__ignoreMap":560},[564,605,606],{"class":566,"line":567},[564,607,608],{"class":592},"{\n",[564,610,611,615,618,621],{"class":566,"line":582},[564,612,614],{"class":613},"sne4z","  \"_id\"",[564,616,617],{"class":592},": ",[564,619,620],{"class":574},"\"66f1c2a9e4b0a1d2c3f4a5b6\"",[564,622,623],{"class":592},",\n",[564,625,627,630,632,635],{"class":566,"line":626},3,[564,628,629],{"class":613},"  \"apiKey\"",[564,631,617],{"class":592},[564,633,634],{"class":574},"\"key_Q2x5cGhvbnktZXhhbXBsZS1r\"",[564,636,623],{"class":592},[564,638,640,643,645,648],{"class":566,"line":639},4,[564,641,642],{"class":613},"  \"companyName\"",[564,644,617],{"class":592},[564,646,647],{"class":574},"\"Northwind Learning\"",[564,649,623],{"class":592},[564,651,653,656],{"class":566,"line":652},5,[564,654,655],{"class":613},"  \"scopes\"",[564,657,658],{"class":592},": [],\n",[564,660,662,665],{"class":566,"line":661},6,[564,663,664],{"class":613},"  \"roles\"",[564,666,667],{"class":592},": [\n",[564,669,671,674,677,679,682,684,687,689,692,694,697,699,702],{"class":566,"line":670},7,[564,672,673],{"class":592},"    { ",[564,675,676],{"class":613},"\"effect\"",[564,678,617],{"class":592},[564,680,681],{"class":574},"\"allow\"",[564,683,441],{"class":592},[564,685,686],{"class":613},"\"action\"",[564,688,617],{"class":592},[564,690,691],{"class":574},"\"api\u002F*\"",[564,693,441],{"class":592},[564,695,696],{"class":613},"\"target\"",[564,698,617],{"class":592},[564,700,701],{"class":574},"\"mto\"",[564,703,704],{"class":592}," },\n",[564,706,708,710,712,714,716,718,720,722,725,727,729,731,734],{"class":566,"line":707},8,[564,709,673],{"class":592},[564,711,676],{"class":613},[564,713,617],{"class":592},[564,715,681],{"class":574},[564,717,441],{"class":592},[564,719,686],{"class":613},[564,721,617],{"class":592},[564,723,724],{"class":574},"\"*\u002Fread\"",[564,726,441],{"class":592},[564,728,696],{"class":613},[564,730,617],{"class":592},[564,732,733],{"class":574},"\"*\"",[564,735,704],{"class":592},[564,737,739,741,743,745,747,749,751,753,756,758,760,762,764],{"class":566,"line":738},9,[564,740,673],{"class":592},[564,742,676],{"class":613},[564,744,617],{"class":592},[564,746,681],{"class":574},[564,748,441],{"class":592},[564,750,686],{"class":613},[564,752,617],{"class":592},[564,754,755],{"class":574},"\"student\u002F*\"",[564,757,441],{"class":592},[564,759,696],{"class":613},[564,761,617],{"class":592},[564,763,701],{"class":574},[564,765,704],{"class":592},[564,767,769,771,773,775,777,779,781,783,786,788,790,792,794],{"class":566,"line":768},10,[564,770,673],{"class":592},[564,772,676],{"class":613},[564,774,617],{"class":592},[564,776,681],{"class":574},[564,778,441],{"class":592},[564,780,686],{"class":613},[564,782,617],{"class":592},[564,784,785],{"class":574},"\"student\u002Fupdate\"",[564,787,441],{"class":592},[564,789,696],{"class":613},[564,791,617],{"class":592},[564,793,733],{"class":574},[564,795,704],{"class":592},[564,797,799,801,803,805,807,809,811,813,816,818,820,822,824],{"class":566,"line":798},11,[564,800,673],{"class":592},[564,802,676],{"class":613},[564,804,617],{"class":592},[564,806,681],{"class":574},[564,808,441],{"class":592},[564,810,686],{"class":613},[564,812,617],{"class":592},[564,814,815],{"class":574},"\"auth\u002Fsignin\"",[564,817,441],{"class":592},[564,819,696],{"class":613},[564,821,617],{"class":592},[564,823,733],{"class":574},[564,825,704],{"class":592},[564,827,829,831,833,835,837,839,841,843,846,848,850,852,854],{"class":566,"line":828},12,[564,830,673],{"class":592},[564,832,676],{"class":613},[564,834,617],{"class":592},[564,836,681],{"class":574},[564,838,441],{"class":592},[564,840,686],{"class":613},[564,842,617],{"class":592},[564,844,845],{"class":574},"\"application\u002F*\"",[564,847,441],{"class":592},[564,849,696],{"class":613},[564,851,617],{"class":592},[564,853,733],{"class":574},[564,855,704],{"class":592},[564,857,859,861,863,865,868,870,872,874,877,879,881,883,885],{"class":566,"line":858},13,[564,860,673],{"class":592},[564,862,676],{"class":613},[564,864,617],{"class":592},[564,866,867],{"class":574},"\"disallow\"",[564,869,441],{"class":592},[564,871,686],{"class":613},[564,873,617],{"class":592},[564,875,876],{"class":574},"\"application\u002Fdelete\"",[564,878,441],{"class":592},[564,880,696],{"class":613},[564,882,617],{"class":592},[564,884,733],{"class":574},[564,886,887],{"class":592}," }\n",[564,889,891],{"class":566,"line":890},14,[564,892,893],{"class":592},"  ],\n",[564,895,897,900,902],{"class":566,"line":896},15,[564,898,899],{"class":613},"  \"isActive\"",[564,901,617],{"class":592},[564,903,904],{"class":585},"true\n",[564,906,908],{"class":566,"line":907},16,[564,909,910],{"class":592},"}\n",[533,912,914],{"type":913},"warn",[358,915,916,920,921,924,925,927,928,931,932,935,936,938],{},[917,918,919],"strong",{},"This is the one response without the envelope."," Every other success response is\n",[389,922,923],{},"{ \"success\", \"message\", \"data\", \"pagination\"? }",". ",[389,926,473],{}," returns the account object itself, so\nread ",[389,929,930],{},"apiKey"," from the top level of the body, not from ",[389,933,934],{},"data",". Client code that unwraps ",[389,937,934],{}," for\nevery call needs an exception for this route.",[940,941,943],"h3",{"id":942},"fields","Fields",[362,945,946,959],{},[365,947,948],{},[368,949,950,953,956],{},[371,951,952],{},"Field",[371,954,955],{},"Type",[371,957,958],{},"Meaning",[381,960,961,974,997,1009,1028,1067],{},[368,962,963,968,971],{},[386,964,965],{},[389,966,967],{},"_id",[386,969,970],{},"string",[386,972,973],{},"Your account's id. Students you register belong to this id.",[368,975,976,980,982],{},[386,977,978],{},[389,979,930],{},[386,981,970],{},[386,983,984,985,988,989,992,993,996],{},"Your public key, the value you put in the token's ",[389,986,987],{},"kid"," header and ",[389,990,991],{},"sub"," claim: ",[389,994,995],{},"key_"," followed by 24 characters.",[368,998,999,1004,1006],{},[386,1000,1001],{},[389,1002,1003],{},"companyName",[386,1005,970],{},[386,1007,1008],{},"The name the operator gave your account.",[368,1010,1011,1016,1019],{},[386,1012,1013],{},[389,1014,1015],{},"scopes",[386,1017,1018],{},"array of strings",[386,1020,1021,1022,1025,1026,426],{},"Informational. What you may do is decided by ",[389,1023,1024],{},"roles",", not by ",[389,1027,1015],{},[368,1029,1030,1034,1037],{},[386,1031,1032],{},[389,1033,1024],{},[386,1035,1036],{},"array of objects",[386,1038,1039,1040,1043,1044,445,1047,1050,1051,1054,1055,1050,1058,1043,1061,1063,1064,426],{},"Your permissions. Each role has ",[389,1041,1042],{},"effect"," (",[389,1045,1046],{},"allow",[389,1048,1049],{},"disallow","), ",[389,1052,1053],{},"action"," (for example ",[389,1056,1057],{},"student\u002Fread",[389,1059,1060],{},"target",[389,1062,448],{}," or an organization slug) and, when set, ",[389,1065,1066],{},"authorized",[368,1068,1069,1074,1077],{},[386,1070,1071],{},[389,1072,1073],{},"isActive",[386,1075,1076],{},"boolean",[386,1078,1079,1080,1083],{},"Always ",[389,1081,1082],{},"true"," in a successful response: a deactivated account cannot authenticate at all.",[358,1085,1086,1087,1090],{},"Your ",[389,1088,1089],{},"apiSecret"," is never returned, by this or by any other route. The platform cannot show it to you\nagain, so if you lose it, ask for a new account.",[358,1092,1093,1095,1096,1098,1099,445,1101,1103,1104,1106],{},[398,1094,25],{"href":26}," explains how to read ",[389,1097,1024],{},": how an action with wildcards matches,\nwhat a target of ",[389,1100,448],{},[389,1102,452],{}," covers, and why a matching ",[389,1105,1049],{}," always wins.",[940,1108,1110],{"id":1109},"use-it-as-a-health-check","Use it as a health check",[358,1112,1113,1114,1116],{},"Call ",[389,1115,473],{}," when your integration starts, and whenever you want to know whether \"the API is\ndown\" or \"our credentials are wrong\":",[362,1118,1119,1132],{},[365,1120,1121],{},[368,1122,1123,1126,1129],{},[371,1124,1125],{},"Result",[371,1127,1128],{},"What it means",[371,1130,1131],{},"What to do",[381,1133,1134,1147,1162,1181,1198],{},[368,1135,1136,1141,1144],{},[386,1137,1138,1140],{},[389,1139,493],{}," and the roles you expect",[386,1142,1143],{},"Token, clock and account are all fine.",[386,1145,1146],{},"Carry on.",[368,1148,1149,1154,1159],{},[386,1150,1151,1153],{},[389,1152,493],{},", but a role you need is missing",[386,1155,1156,1157,426],{},"Authentication works; a later call will get ",[389,1158,505],{},[386,1160,1161],{},"Ask the operator for the permission.",[368,1163,1164,1168,1171],{},[386,1165,1166],{},[389,1167,525],{},[386,1169,1170],{},"The token was refused: wrong key or secret, a bad claim, a clock too far off, an expired or revoked token, or a deactivated account. The reason is never given.",[386,1172,1173,1174,1176,1177,1180],{},"Work through the checklist on ",[398,1175,19],{"href":20},". Quote the ",[389,1178,1179],{},"request_id"," if you contact support.",[368,1182,1183,1187,1192],{},[386,1184,1185],{},[389,1186,505],{},[386,1188,1189,1190,426],{},"The token is fine; the account lacks ",[389,1191,437],{},[386,1193,1194,1195,1197],{},"Ask for ",[389,1196,437],{},", or check your token with a route you do have.",[368,1199,1200,1206,1209],{},[386,1201,1202,1205],{},[389,1203,1204],{},"5xx"," or a timeout",[386,1207,1208],{},"A problem on the platform's side.",[386,1210,1211,1212,1215],{},"Retry with backoff (",[398,1213,1214],{"href":49},"Retries and idempotency",").",[358,1217,1218,1219,1221],{},"Changes an operator makes to your account take up to 60 seconds to reach the API. That covers new or\nremoved roles, and deactivation. Right after an operator changes your roles, ",[389,1220,473],{}," can still\nshow the old ones for up to a minute.",[555,1223,1227],{"className":1224,"code":1225,"filename":308,"language":1226,"meta":560,"style":560},"language-js shiki shiki-themes github-light-high-contrast github-dark-high-contrast","import jwt from 'jsonwebtoken';\n\nconst BASE = 'https:\u002F\u002Fapi.main-team.org\u002Fv1';\nconst API_KEY = process.env.MTO_API_KEY;\nconst API_SECRET = process.env.MTO_API_SECRET;\n\nfunction mintToken(lifetimeSeconds = 900) {\n  const now = Math.floor(Date.now() \u002F 1000);\n  return jwt.sign({ sub: API_KEY, iat: now, exp: now + lifetimeSeconds }, API_SECRET, {\n    algorithm: 'HS256',\n    keyid: API_KEY,\n  });\n}\n\nexport async function checkCredentials(requiredActions = []) {\n  const res = await fetch(`${BASE}\u002Fapi-account\u002Fvalidate-me`, {\n    headers: { Authorization: `Bearer ${mintToken(60)}` },\n  });\n  if (res.status === 401) throw new Error('Token refused: check key, secret, clock and account status');\n  if (res.status === 403) throw new Error('Token valid, but the account lacks api\u002F*');\n  if (!res.ok) throw new Error(`validate-me: HTTP ${res.status}`);\n\n  const account = await res.json(); \u002F\u002F no envelope on this route\n  const allowed = new Set(\n    account.roles.filter((r) => r.effect === 'allow').map((r) => r.action),\n  );\n  const missing = requiredActions.filter((a) => !allowed.has(a));\n  return { account, missing }; \u002F\u002F a plain string match; see \u002Fapi\u002Fpermissions for wildcards\n}\n","js",[389,1228,1229,1246,1252,1268,1285,1301,1305,1328,1362,1394,1404,1413,1418,1422,1426,1450,1478,1503,1508,1542,1569,1605,1610,1634,1652,1696,1702,1737,1748],{"__ignoreMap":560},[564,1230,1231,1234,1237,1240,1243],{"class":566,"line":567},[564,1232,1233],{"class":578},"import",[564,1235,1236],{"class":592}," jwt ",[564,1238,1239],{"class":578},"from",[564,1241,1242],{"class":574}," 'jsonwebtoken'",[564,1244,1245],{"class":592},";\n",[564,1247,1248],{"class":566,"line":582},[564,1249,1251],{"emptyLinePlaceholder":1250},true,"\n",[564,1253,1254,1257,1260,1263,1266],{"class":566,"line":626},[564,1255,1256],{"class":578},"const",[564,1258,1259],{"class":585}," BASE",[564,1261,1262],{"class":578}," =",[564,1264,1265],{"class":574}," 'https:\u002F\u002Fapi.main-team.org\u002Fv1'",[564,1267,1245],{"class":592},[564,1269,1270,1272,1275,1277,1280,1283],{"class":566,"line":639},[564,1271,1256],{"class":578},[564,1273,1274],{"class":585}," API_KEY",[564,1276,1262],{"class":578},[564,1278,1279],{"class":592}," process.env.",[564,1281,1282],{"class":585},"MTO_API_KEY",[564,1284,1245],{"class":592},[564,1286,1287,1289,1292,1294,1296,1299],{"class":566,"line":652},[564,1288,1256],{"class":578},[564,1290,1291],{"class":585}," API_SECRET",[564,1293,1262],{"class":578},[564,1295,1279],{"class":592},[564,1297,1298],{"class":585},"MTO_API_SECRET",[564,1300,1245],{"class":592},[564,1302,1303],{"class":566,"line":661},[564,1304,1251],{"emptyLinePlaceholder":1250},[564,1306,1307,1310,1314,1317,1320,1322,1325],{"class":566,"line":670},[564,1308,1309],{"class":578},"function",[564,1311,1313],{"class":1312},"sKwhi"," mintToken",[564,1315,1316],{"class":592},"(",[564,1318,1319],{"class":570},"lifetimeSeconds",[564,1321,1262],{"class":578},[564,1323,1324],{"class":585}," 900",[564,1326,1327],{"class":592},") {\n",[564,1329,1330,1333,1336,1338,1341,1344,1347,1350,1353,1356,1359],{"class":566,"line":707},[564,1331,1332],{"class":578},"  const",[564,1334,1335],{"class":585}," now",[564,1337,1262],{"class":578},[564,1339,1340],{"class":592}," Math.",[564,1342,1343],{"class":1312},"floor",[564,1345,1346],{"class":592},"(Date.",[564,1348,1349],{"class":1312},"now",[564,1351,1352],{"class":592},"() ",[564,1354,1355],{"class":578},"\u002F",[564,1357,1358],{"class":585}," 1000",[564,1360,1361],{"class":592},");\n",[564,1363,1364,1367,1370,1373,1376,1379,1382,1385,1388,1391],{"class":566,"line":738},[564,1365,1366],{"class":578},"  return",[564,1368,1369],{"class":592}," jwt.",[564,1371,1372],{"class":1312},"sign",[564,1374,1375],{"class":592},"({ sub: ",[564,1377,1378],{"class":585},"API_KEY",[564,1380,1381],{"class":592},", iat: now, exp: now ",[564,1383,1384],{"class":578},"+",[564,1386,1387],{"class":592}," lifetimeSeconds }, ",[564,1389,1390],{"class":585},"API_SECRET",[564,1392,1393],{"class":592},", {\n",[564,1395,1396,1399,1402],{"class":566,"line":768},[564,1397,1398],{"class":592},"    algorithm: ",[564,1400,1401],{"class":574},"'HS256'",[564,1403,623],{"class":592},[564,1405,1406,1409,1411],{"class":566,"line":798},[564,1407,1408],{"class":592},"    keyid: ",[564,1410,1378],{"class":585},[564,1412,623],{"class":592},[564,1414,1415],{"class":566,"line":828},[564,1416,1417],{"class":592},"  });\n",[564,1419,1420],{"class":566,"line":858},[564,1421,910],{"class":592},[564,1423,1424],{"class":566,"line":890},[564,1425,1251],{"emptyLinePlaceholder":1250},[564,1427,1428,1431,1434,1437,1440,1442,1445,1447],{"class":566,"line":896},[564,1429,1430],{"class":578},"export",[564,1432,1433],{"class":578}," async",[564,1435,1436],{"class":578}," function",[564,1438,1439],{"class":1312}," checkCredentials",[564,1441,1316],{"class":592},[564,1443,1444],{"class":570},"requiredActions",[564,1446,1262],{"class":578},[564,1448,1449],{"class":592}," []) {\n",[564,1451,1452,1454,1457,1459,1462,1465,1467,1470,1473,1476],{"class":566,"line":907},[564,1453,1332],{"class":578},[564,1455,1456],{"class":585}," res",[564,1458,1262],{"class":578},[564,1460,1461],{"class":578}," await",[564,1463,1464],{"class":1312}," fetch",[564,1466,1316],{"class":592},[564,1468,1469],{"class":574},"`${",[564,1471,1472],{"class":585},"BASE",[564,1474,1475],{"class":574},"}\u002Fapi-account\u002Fvalidate-me`",[564,1477,1393],{"class":592},[564,1479,1481,1484,1487,1490,1492,1495,1498,1501],{"class":566,"line":1480},17,[564,1482,1483],{"class":592},"    headers: { Authorization: ",[564,1485,1486],{"class":574},"`Bearer ${",[564,1488,1489],{"class":1312},"mintToken",[564,1491,1316],{"class":574},[564,1493,1494],{"class":585},"60",[564,1496,1497],{"class":574},")",[564,1499,1500],{"class":574},"}`",[564,1502,704],{"class":592},[564,1504,1506],{"class":566,"line":1505},18,[564,1507,1417],{"class":592},[564,1509,1511,1514,1517,1520,1523,1526,1529,1532,1535,1537,1540],{"class":566,"line":1510},19,[564,1512,1513],{"class":578},"  if",[564,1515,1516],{"class":592}," (res.status ",[564,1518,1519],{"class":578},"===",[564,1521,1522],{"class":585}," 401",[564,1524,1525],{"class":592},") ",[564,1527,1528],{"class":578},"throw",[564,1530,1531],{"class":578}," new",[564,1533,1534],{"class":1312}," Error",[564,1536,1316],{"class":592},[564,1538,1539],{"class":574},"'Token refused: check key, secret, clock and account status'",[564,1541,1361],{"class":592},[564,1543,1545,1547,1549,1551,1554,1556,1558,1560,1562,1564,1567],{"class":566,"line":1544},20,[564,1546,1513],{"class":578},[564,1548,1516],{"class":592},[564,1550,1519],{"class":578},[564,1552,1553],{"class":585}," 403",[564,1555,1525],{"class":592},[564,1557,1528],{"class":578},[564,1559,1531],{"class":578},[564,1561,1534],{"class":1312},[564,1563,1316],{"class":592},[564,1565,1566],{"class":574},"'Token valid, but the account lacks api\u002F*'",[564,1568,1361],{"class":592},[564,1570,1572,1574,1576,1579,1582,1584,1586,1588,1590,1593,1596,1598,1601,1603],{"class":566,"line":1571},21,[564,1573,1513],{"class":578},[564,1575,1043],{"class":592},[564,1577,1578],{"class":578},"!",[564,1580,1581],{"class":592},"res.ok) ",[564,1583,1528],{"class":578},[564,1585,1531],{"class":578},[564,1587,1534],{"class":1312},[564,1589,1316],{"class":592},[564,1591,1592],{"class":574},"`validate-me: HTTP ${",[564,1594,1595],{"class":592},"res",[564,1597,426],{"class":574},[564,1599,1600],{"class":592},"status",[564,1602,1500],{"class":574},[564,1604,1361],{"class":592},[564,1606,1608],{"class":566,"line":1607},22,[564,1609,1251],{"emptyLinePlaceholder":1250},[564,1611,1613,1615,1618,1620,1622,1625,1627,1630],{"class":566,"line":1612},23,[564,1614,1332],{"class":578},[564,1616,1617],{"class":585}," account",[564,1619,1262],{"class":578},[564,1621,1461],{"class":578},[564,1623,1624],{"class":592}," res.",[564,1626,601],{"class":1312},[564,1628,1629],{"class":592},"(); ",[564,1631,1633],{"class":1632},"sLBg1","\u002F\u002F no envelope on this route\n",[564,1635,1637,1639,1642,1644,1646,1649],{"class":566,"line":1636},24,[564,1638,1332],{"class":578},[564,1640,1641],{"class":585}," allowed",[564,1643,1262],{"class":578},[564,1645,1531],{"class":578},[564,1647,1648],{"class":1312}," Set",[564,1650,1651],{"class":592},"(\n",[564,1653,1655,1658,1661,1664,1667,1669,1672,1675,1677,1680,1682,1685,1687,1689,1691,1693],{"class":566,"line":1654},25,[564,1656,1657],{"class":592},"    account.roles.",[564,1659,1660],{"class":1312},"filter",[564,1662,1663],{"class":592},"((",[564,1665,1666],{"class":570},"r",[564,1668,1525],{"class":592},[564,1670,1671],{"class":578},"=>",[564,1673,1674],{"class":592}," r.effect ",[564,1676,1519],{"class":578},[564,1678,1679],{"class":574}," 'allow'",[564,1681,1215],{"class":592},[564,1683,1684],{"class":1312},"map",[564,1686,1663],{"class":592},[564,1688,1666],{"class":570},[564,1690,1525],{"class":592},[564,1692,1671],{"class":578},[564,1694,1695],{"class":592}," r.action),\n",[564,1697,1699],{"class":566,"line":1698},26,[564,1700,1701],{"class":592},"  );\n",[564,1703,1705,1707,1710,1712,1715,1717,1719,1721,1723,1725,1728,1731,1734],{"class":566,"line":1704},27,[564,1706,1332],{"class":578},[564,1708,1709],{"class":585}," missing",[564,1711,1262],{"class":578},[564,1713,1714],{"class":592}," requiredActions.",[564,1716,1660],{"class":1312},[564,1718,1663],{"class":592},[564,1720,398],{"class":570},[564,1722,1525],{"class":592},[564,1724,1671],{"class":578},[564,1726,1727],{"class":578}," !",[564,1729,1730],{"class":592},"allowed.",[564,1732,1733],{"class":1312},"has",[564,1735,1736],{"class":592},"(a));\n",[564,1738,1740,1742,1745],{"class":566,"line":1739},28,[564,1741,1366],{"class":578},[564,1743,1744],{"class":592}," { account, missing }; ",[564,1746,1747],{"class":1632},"\u002F\u002F a plain string match; see \u002Fapi\u002Fpermissions for wildcards\n",[564,1749,1751],{"class":566,"line":1750},29,[564,1752,910],{"class":592},[555,1754,1758],{"className":1755,"code":1756,"filename":311,"language":1757,"meta":560,"style":560},"language-php shiki shiki-themes github-light-high-contrast github-dark-high-contrast","\u003C?php\nuse Firebase\\JWT\\JWT; \u002F\u002F composer require firebase\u002Fphp-jwt\n\nconst MT_BASE = 'https:\u002F\u002Fapi.main-team.org\u002Fv1';\n\nfunction mt_mint_token(int $lifetimeSeconds = 900): string\n{\n    $apiKey = getenv('MTO_API_KEY');\n    $now = time();\n    $payload = ['sub' => $apiKey, 'iat' => $now, 'exp' => $now + $lifetimeSeconds];\n    return JWT::encode($payload, getenv('MTO_API_SECRET'), 'HS256', $apiKey);\n}\n\nfunction mt_check_credentials(): array\n{\n    $ch = curl_init(MT_BASE . '\u002Fapi-account\u002Fvalidate-me');\n    curl_setopt_array($ch, [\n        CURLOPT_RETURNTRANSFER => true,\n        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . mt_mint_token(60)],\n        CURLOPT_TIMEOUT => 30,\n    ]);\n    $raw = curl_exec($ch);\n    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);\n    curl_close($ch);\n\n    if ($status === 401) throw new RuntimeException('Token refused: check key, secret, clock and account status');\n    if ($status === 403) throw new RuntimeException('Token valid, but the account lacks api\u002F*');\n    if ($status !== 200) throw new RuntimeException(\"validate-me: HTTP $status\");\n\n    return json_decode($raw, true); \u002F\u002F the account itself, not an envelope\n}\n","php",[389,1759,1760,1768,1782,1786,1799,1803,1831,1835,1852,1865,1905,1937,1941,1945,1960,1964,1987,1995,2007,2030,2042,2047,2060,2078,2085,2089,2116,2140,2173,2177,2196],{"__ignoreMap":560},[564,1761,1762,1765],{"class":566,"line":567},[564,1763,1764],{"class":578},"\u003C?",[564,1766,1767],{"class":585},"php\n",[564,1769,1770,1773,1776,1779],{"class":566,"line":582},[564,1771,1772],{"class":578},"use",[564,1774,1775],{"class":585}," Firebase\\JWT\\JWT",[564,1777,1778],{"class":592},"; ",[564,1780,1781],{"class":1632},"\u002F\u002F composer require firebase\u002Fphp-jwt\n",[564,1783,1784],{"class":566,"line":626},[564,1785,1251],{"emptyLinePlaceholder":1250},[564,1787,1788,1790,1793,1795,1797],{"class":566,"line":639},[564,1789,1256],{"class":578},[564,1791,1792],{"class":585}," MT_BASE",[564,1794,1262],{"class":578},[564,1796,1265],{"class":574},[564,1798,1245],{"class":592},[564,1800,1801],{"class":566,"line":652},[564,1802,1251],{"emptyLinePlaceholder":1250},[564,1804,1805,1807,1810,1812,1815,1818,1821,1823,1825,1828],{"class":566,"line":661},[564,1806,1309],{"class":578},[564,1808,1809],{"class":1312}," mt_mint_token",[564,1811,1316],{"class":592},[564,1813,1814],{"class":578},"int",[564,1816,1817],{"class":592}," $lifetimeSeconds ",[564,1819,1820],{"class":578},"=",[564,1822,1324],{"class":585},[564,1824,1497],{"class":592},[564,1826,1827],{"class":578},":",[564,1829,1830],{"class":578}," string\n",[564,1832,1833],{"class":566,"line":670},[564,1834,608],{"class":592},[564,1836,1837,1840,1842,1845,1847,1850],{"class":566,"line":707},[564,1838,1839],{"class":592},"    $apiKey ",[564,1841,1820],{"class":578},[564,1843,1844],{"class":585}," getenv",[564,1846,1316],{"class":592},[564,1848,1849],{"class":574},"'MTO_API_KEY'",[564,1851,1361],{"class":592},[564,1853,1854,1857,1859,1862],{"class":566,"line":738},[564,1855,1856],{"class":592},"    $now ",[564,1858,1820],{"class":578},[564,1860,1861],{"class":585}," time",[564,1863,1864],{"class":592},"();\n",[564,1866,1867,1870,1872,1875,1878,1881,1884,1887,1889,1892,1895,1897,1900,1902],{"class":566,"line":768},[564,1868,1869],{"class":592},"    $payload ",[564,1871,1820],{"class":578},[564,1873,1874],{"class":592}," [",[564,1876,1877],{"class":574},"'sub'",[564,1879,1880],{"class":578}," =>",[564,1882,1883],{"class":592}," $apiKey, ",[564,1885,1886],{"class":574},"'iat'",[564,1888,1880],{"class":578},[564,1890,1891],{"class":592}," $now, ",[564,1893,1894],{"class":574},"'exp'",[564,1896,1880],{"class":578},[564,1898,1899],{"class":592}," $now ",[564,1901,1384],{"class":578},[564,1903,1904],{"class":592}," $lifetimeSeconds];\n",[564,1906,1907,1910,1913,1916,1919,1922,1925,1927,1930,1932,1934],{"class":566,"line":798},[564,1908,1909],{"class":578},"    return",[564,1911,1912],{"class":585}," JWT",[564,1914,1915],{"class":578},"::",[564,1917,1918],{"class":1312},"encode",[564,1920,1921],{"class":592},"($payload, ",[564,1923,1924],{"class":585},"getenv",[564,1926,1316],{"class":592},[564,1928,1929],{"class":574},"'MTO_API_SECRET'",[564,1931,1050],{"class":592},[564,1933,1401],{"class":574},[564,1935,1936],{"class":592},", $apiKey);\n",[564,1938,1939],{"class":566,"line":828},[564,1940,910],{"class":592},[564,1942,1943],{"class":566,"line":858},[564,1944,1251],{"emptyLinePlaceholder":1250},[564,1946,1947,1949,1952,1955,1957],{"class":566,"line":890},[564,1948,1309],{"class":578},[564,1950,1951],{"class":1312}," mt_check_credentials",[564,1953,1954],{"class":592},"()",[564,1956,1827],{"class":578},[564,1958,1959],{"class":578}," array\n",[564,1961,1962],{"class":566,"line":896},[564,1963,608],{"class":592},[564,1965,1966,1969,1971,1974,1976,1979,1982,1985],{"class":566,"line":907},[564,1967,1968],{"class":592},"    $ch ",[564,1970,1820],{"class":578},[564,1972,1973],{"class":585}," curl_init",[564,1975,1316],{"class":592},[564,1977,1978],{"class":585},"MT_BASE",[564,1980,1981],{"class":578}," .",[564,1983,1984],{"class":574}," '\u002Fapi-account\u002Fvalidate-me'",[564,1986,1361],{"class":592},[564,1988,1989,1992],{"class":566,"line":1480},[564,1990,1991],{"class":585},"    curl_setopt_array",[564,1993,1994],{"class":592},"($ch, [\n",[564,1996,1997,2000,2002,2005],{"class":566,"line":1505},[564,1998,1999],{"class":585},"        CURLOPT_RETURNTRANSFER",[564,2001,1880],{"class":578},[564,2003,2004],{"class":585}," true",[564,2006,623],{"class":592},[564,2008,2009,2012,2014,2016,2019,2021,2023,2025,2027],{"class":566,"line":1510},[564,2010,2011],{"class":585},"        CURLOPT_HTTPHEADER",[564,2013,1880],{"class":578},[564,2015,1874],{"class":592},[564,2017,2018],{"class":574},"'Authorization: Bearer '",[564,2020,1981],{"class":578},[564,2022,1809],{"class":1312},[564,2024,1316],{"class":592},[564,2026,1494],{"class":585},[564,2028,2029],{"class":592},")],\n",[564,2031,2032,2035,2037,2040],{"class":566,"line":1544},[564,2033,2034],{"class":585},"        CURLOPT_TIMEOUT",[564,2036,1880],{"class":578},[564,2038,2039],{"class":585}," 30",[564,2041,623],{"class":592},[564,2043,2044],{"class":566,"line":1571},[564,2045,2046],{"class":592},"    ]);\n",[564,2048,2049,2052,2054,2057],{"class":566,"line":1607},[564,2050,2051],{"class":592},"    $raw ",[564,2053,1820],{"class":578},[564,2055,2056],{"class":585}," curl_exec",[564,2058,2059],{"class":592},"($ch);\n",[564,2061,2062,2065,2067,2070,2073,2076],{"class":566,"line":1612},[564,2063,2064],{"class":592},"    $status ",[564,2066,1820],{"class":578},[564,2068,2069],{"class":585}," curl_getinfo",[564,2071,2072],{"class":592},"($ch, ",[564,2074,2075],{"class":585},"CURLINFO_RESPONSE_CODE",[564,2077,1361],{"class":592},[564,2079,2080,2083],{"class":566,"line":1636},[564,2081,2082],{"class":585},"    curl_close",[564,2084,2059],{"class":592},[564,2086,2087],{"class":566,"line":1654},[564,2088,1251],{"emptyLinePlaceholder":1250},[564,2090,2091,2094,2097,2099,2101,2103,2105,2107,2110,2112,2114],{"class":566,"line":1698},[564,2092,2093],{"class":578},"    if",[564,2095,2096],{"class":592}," ($status ",[564,2098,1519],{"class":578},[564,2100,1522],{"class":585},[564,2102,1525],{"class":592},[564,2104,1528],{"class":578},[564,2106,1531],{"class":578},[564,2108,2109],{"class":585}," RuntimeException",[564,2111,1316],{"class":592},[564,2113,1539],{"class":574},[564,2115,1361],{"class":592},[564,2117,2118,2120,2122,2124,2126,2128,2130,2132,2134,2136,2138],{"class":566,"line":1704},[564,2119,2093],{"class":578},[564,2121,2096],{"class":592},[564,2123,1519],{"class":578},[564,2125,1553],{"class":585},[564,2127,1525],{"class":592},[564,2129,1528],{"class":578},[564,2131,1531],{"class":578},[564,2133,2109],{"class":585},[564,2135,1316],{"class":592},[564,2137,1566],{"class":574},[564,2139,1361],{"class":592},[564,2141,2142,2144,2146,2149,2152,2154,2156,2158,2160,2162,2165,2168,2171],{"class":566,"line":1739},[564,2143,2093],{"class":578},[564,2145,2096],{"class":592},[564,2147,2148],{"class":578},"!==",[564,2150,2151],{"class":585}," 200",[564,2153,1525],{"class":592},[564,2155,1528],{"class":578},[564,2157,1531],{"class":578},[564,2159,2109],{"class":585},[564,2161,1316],{"class":592},[564,2163,2164],{"class":574},"\"validate-me: HTTP ",[564,2166,2167],{"class":592},"$status",[564,2169,2170],{"class":574},"\"",[564,2172,1361],{"class":592},[564,2174,2175],{"class":566,"line":1750},[564,2176,1251],{"emptyLinePlaceholder":1250},[564,2178,2180,2182,2185,2188,2190,2193],{"class":566,"line":2179},30,[564,2181,1909],{"class":578},[564,2183,2184],{"class":585}," json_decode",[564,2186,2187],{"class":592},"($raw, ",[564,2189,1082],{"class":585},[564,2191,2192],{"class":592},"); ",[564,2194,2195],{"class":1632},"\u002F\u002F the account itself, not an envelope\n",[564,2197,2199],{"class":566,"line":2198},31,[564,2200,910],{"class":592},[358,2202,2203,2204,2207,2208,2210,2211,2213,2214,2216],{},"The check in the Node.js example compares action names as plain strings, which is enough to spot a\nmissing role such as ",[389,2205,2206],{},"auth\u002Fsignin",". It does not expand wildcards: a role of ",[389,2209,444],{}," grants\n",[389,2212,2206],{}," but would be reported as missing. Use the matching rules on ",[398,2215,25],{"href":26},"\nif you want an exact answer.",[428,2218,415],{"id":2219},"revoke-a-token",[358,2221,2222,2224,2225,2227,2228,2230],{},[389,2223,407],{}," revokes the token you call it with. From then on every request\ncarrying that token gets ",[389,2226,525],{},", on every server the API runs on. Nothing else changes: your\n",[389,2229,1089],{}," stays the same, other tokens you have signed keep working, and you can sign a new one\nstraight away.",[555,2232,2234],{"className":557,"code":2233,"language":559,"meta":560,"style":560},"curl -X POST \"https:\u002F\u002Fapi.main-team.org\u002Fv1\u002Fapi-account\u002Frevoke-token\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n",[389,2235,2236,2251],{"__ignoreMap":560},[564,2237,2238,2240,2243,2246,2249],{"class":566,"line":567},[564,2239,571],{"class":570},[564,2241,2242],{"class":585}," -X",[564,2244,2245],{"class":574}," POST",[564,2247,2248],{"class":574}," \"https:\u002F\u002Fapi.main-team.org\u002Fv1\u002Fapi-account\u002Frevoke-token\"",[564,2250,579],{"class":578},[564,2252,2253,2255,2257,2259],{"class":566,"line":582},[564,2254,586],{"class":585},[564,2256,589],{"class":574},[564,2258,593],{"class":592},[564,2260,596],{"class":574},[555,2262,2264],{"className":599,"code":2263,"language":601,"meta":560,"style":560},"{\n  \"success\": true,\n  \"message\": \"Token revoked successfully\",\n  \"data\": { \"expiresIn\": 1830 }\n}\n",[389,2265,2266,2270,2281,2293,2311],{"__ignoreMap":560},[564,2267,2268],{"class":566,"line":567},[564,2269,608],{"class":592},[564,2271,2272,2275,2277,2279],{"class":566,"line":582},[564,2273,2274],{"class":613},"  \"success\"",[564,2276,617],{"class":592},[564,2278,1082],{"class":585},[564,2280,623],{"class":592},[564,2282,2283,2286,2288,2291],{"class":566,"line":626},[564,2284,2285],{"class":613},"  \"message\"",[564,2287,617],{"class":592},[564,2289,2290],{"class":574},"\"Token revoked successfully\"",[564,2292,623],{"class":592},[564,2294,2295,2298,2301,2304,2306,2309],{"class":566,"line":639},[564,2296,2297],{"class":613},"  \"data\"",[564,2299,2300],{"class":592},": { ",[564,2302,2303],{"class":613},"\"expiresIn\"",[564,2305,617],{"class":592},[564,2307,2308],{"class":585},"1830",[564,2310,887],{"class":592},[564,2312,2313],{"class":566,"line":652},[564,2314,910],{"class":592},[358,2316,2317,2318,2321],{},"No body is needed, and you should send none. The token to revoke is the one in the ",[389,2319,2320],{},"Authorization","\nheader.",[358,2323,2324,2327,2328,2331,2332,2334],{},[389,2325,2326],{},"expiresIn"," is the number of seconds the revocation is held: the token's remaining lifetime plus 30\nseconds. The extra 30 seconds match the clock tolerance the API allows after ",[389,2329,2330],{},"exp",", so a revoked token\ncannot become valid again in that window. After ",[389,2333,2326],{}," seconds the token would be refused as\nexpired anyway. The value is at least 1 and at most 3660 (the one-hour maximum lifetime plus 60\nseconds).",[940,2336,2338],{"id":2337},"when-to-revoke","When to revoke",[362,2340,2341,2350],{},[365,2342,2343],{},[368,2344,2345,2348],{},[371,2346,2347],{},"Situation",[371,2349,1131],{},[381,2351,2352,2360,2368],{},[368,2353,2354,2357],{},[386,2355,2356],{},"A process that holds a long-lived token shuts down",[386,2358,2359],{},"Revoke the token as part of shutdown, so a copy left in memory dumps or logs is useless.",[368,2361,2362,2365],{},[386,2363,2364],{},"One token was exposed: it was logged, pasted into a ticket, or sent to the wrong system",[386,2366,2367],{},"Revoke that token, then sign a new one.",[368,2369,2370,2375],{},[386,2371,1086,2372,2374],{},[917,2373,1089],{}," was exposed",[386,2376,2377,2378,2380],{},"Revoking tokens is not enough, because whoever holds the secret can sign new ones. Ask the operator to deactivate the account at ",[398,2379,422],{"href":421},". Deactivation stops every token signed with that secret within 60 seconds.",[533,2382,2384],{"type":2383},"security",[358,2385,2386,2389,2390,2392],{},[917,2387,2388],{},"A replacement account starts empty."," Students belong to the account that registered them, so a new\naccount does not see the students the old one registered. Agree the move with the operator before a\ncompromised account is replaced. ",[398,2391,51],{"href":52}," covers secret storage and incident\nhandling in more depth.",[940,2394,2396],{"id":2395},"a-replacement-token-must-differ-from-the-revoked-one","A replacement token must differ from the revoked one",[358,2398,2399,2400,2403,2404,2406,2407,445,2409,2411],{},"A token is revoked by its exact text. Signing is deterministic, so a token signed with the same key,\nthe same ",[389,2401,2402],{},"iat"," and the same ",[389,2405,2330],{}," is the same text, and it is refused as revoked too. This bites a\nclient that revokes a token and immediately signs a replacement within the same second, with the same\nlifetime. Make sure the new token's ",[389,2408,2402],{},[389,2410,2330],{}," differs: wait a second, or change the lifetime by a\nsecond.",[940,2413,2415],{"id":2414},"refusals","Refusals",[362,2417,2418,2434],{},[365,2419,2420],{},[368,2421,2422,2425,2428,2431],{},[371,2423,2424],{},"Status",[371,2426,2427],{},"Code",[371,2429,2430],{},"Message",[371,2432,2433],{},"When",[381,2435,2436,2456,2478],{},[368,2437,2438,2442,2448,2453],{},[386,2439,2440],{},[389,2441,525],{},[386,2443,2444],{},[398,2445,2446],{"href":528},[389,2447,531],{},[386,2449,2450],{},[389,2451,2452],{},"Authentication is required or the provided credentials are invalid.",[386,2454,2455],{},"The token was not accepted, including a token that is already revoked. There is nothing to revoke.",[368,2457,2458,2462,2468,2472],{},[386,2459,2460],{},[389,2461,505],{},[386,2463,2464],{},[398,2465,2466],{"href":509},[389,2467,512],{},[386,2469,2470],{},[389,2471,515],{},[386,2473,2474,2475,2477],{},"Your account lacks ",[389,2476,437],{},". Without it you cannot revoke your own tokens; keep token lifetimes short, and ask the operator for the permission.",[368,2479,2480,2485,2493,2501],{},[386,2481,2482],{},[389,2483,2484],{},"400",[386,2486,2487],{},[398,2488,2490],{"href":2489},"\u002Fapi\u002Ferrors#bad_request",[389,2491,2492],{},"bad_request",[386,2494,2495,445,2498],{},[389,2496,2497],{},"Invalid token format.",[389,2499,2500],{},"No token provided.",[386,2502,2503,2504,2506],{},"The token could not be read or has no ",[389,2505,2330],{},". A token the API has accepted always has one, so you should never see this. Nothing was revoked.",[358,2508,2509,2510,2512],{},"Revoking twice is harmless in effect, but the second call gets ",[389,2511,525],{},": the token is already revoked,\nso it no longer authenticates the call that would revoke it.",[555,2514,2516],{"className":1224,"code":2515,"filename":308,"language":1226,"meta":560,"style":560},"export async function revoke(token) {\n  const res = await fetch(`${BASE}\u002Fapi-account\u002Frevoke-token`, {\n    method: 'POST',\n    headers: { Authorization: `Bearer ${token}` },\n  });\n  if (res.status === 401) return { alreadyUnusable: true };\n  if (!res.ok) throw new Error(`revoke-token: HTTP ${res.status}`);\n  const { data } = await res.json();\n  return { expiresIn: data.expiresIn };\n}\n\n\u002F\u002F On shutdown:\n\u002F\u002F process.on('SIGTERM', async () => { await revoke(currentToken); process.exit(0); });\n",[389,2517,2518,2536,2559,2569,2581,2585,2608,2639,2661,2668,2672,2676,2681],{"__ignoreMap":560},[564,2519,2520,2522,2524,2526,2529,2531,2534],{"class":566,"line":567},[564,2521,1430],{"class":578},[564,2523,1433],{"class":578},[564,2525,1436],{"class":578},[564,2527,2528],{"class":1312}," revoke",[564,2530,1316],{"class":592},[564,2532,2533],{"class":570},"token",[564,2535,1327],{"class":592},[564,2537,2538,2540,2542,2544,2546,2548,2550,2552,2554,2557],{"class":566,"line":582},[564,2539,1332],{"class":578},[564,2541,1456],{"class":585},[564,2543,1262],{"class":578},[564,2545,1461],{"class":578},[564,2547,1464],{"class":1312},[564,2549,1316],{"class":592},[564,2551,1469],{"class":574},[564,2553,1472],{"class":585},[564,2555,2556],{"class":574},"}\u002Fapi-account\u002Frevoke-token`",[564,2558,1393],{"class":592},[564,2560,2561,2564,2567],{"class":566,"line":626},[564,2562,2563],{"class":592},"    method: ",[564,2565,2566],{"class":574},"'POST'",[564,2568,623],{"class":592},[564,2570,2571,2573,2575,2577,2579],{"class":566,"line":639},[564,2572,1483],{"class":592},[564,2574,1486],{"class":574},[564,2576,2533],{"class":592},[564,2578,1500],{"class":574},[564,2580,704],{"class":592},[564,2582,2583],{"class":566,"line":652},[564,2584,1417],{"class":592},[564,2586,2587,2589,2591,2593,2595,2597,2600,2603,2605],{"class":566,"line":661},[564,2588,1513],{"class":578},[564,2590,1516],{"class":592},[564,2592,1519],{"class":578},[564,2594,1522],{"class":585},[564,2596,1525],{"class":592},[564,2598,2599],{"class":578},"return",[564,2601,2602],{"class":592}," { alreadyUnusable: ",[564,2604,1082],{"class":585},[564,2606,2607],{"class":592}," };\n",[564,2609,2610,2612,2614,2616,2618,2620,2622,2624,2626,2629,2631,2633,2635,2637],{"class":566,"line":670},[564,2611,1513],{"class":578},[564,2613,1043],{"class":592},[564,2615,1578],{"class":578},[564,2617,1581],{"class":592},[564,2619,1528],{"class":578},[564,2621,1531],{"class":578},[564,2623,1534],{"class":1312},[564,2625,1316],{"class":592},[564,2627,2628],{"class":574},"`revoke-token: HTTP ${",[564,2630,1595],{"class":592},[564,2632,426],{"class":574},[564,2634,1600],{"class":592},[564,2636,1500],{"class":574},[564,2638,1361],{"class":592},[564,2640,2641,2643,2646,2648,2651,2653,2655,2657,2659],{"class":566,"line":707},[564,2642,1332],{"class":578},[564,2644,2645],{"class":592}," { ",[564,2647,934],{"class":585},[564,2649,2650],{"class":592}," } ",[564,2652,1820],{"class":578},[564,2654,1461],{"class":578},[564,2656,1624],{"class":592},[564,2658,601],{"class":1312},[564,2660,1864],{"class":592},[564,2662,2663,2665],{"class":566,"line":738},[564,2664,1366],{"class":578},[564,2666,2667],{"class":592}," { expiresIn: data.expiresIn };\n",[564,2669,2670],{"class":566,"line":768},[564,2671,910],{"class":592},[564,2673,2674],{"class":566,"line":798},[564,2675,1251],{"emptyLinePlaceholder":1250},[564,2677,2678],{"class":566,"line":828},[564,2679,2680],{"class":1632},"\u002F\u002F On shutdown:\n",[564,2682,2683],{"class":566,"line":858},[564,2684,2685],{"class":1632},"\u002F\u002F process.on('SIGTERM', async () => { await revoke(currentToken); process.exit(0); });\n",[555,2687,2689],{"className":1755,"code":2688,"filename":311,"language":1757,"meta":560,"style":560},"\u003C?php\nfunction mt_revoke(string $token): ?int\n{\n    $ch = curl_init(MT_BASE . '\u002Fapi-account\u002Frevoke-token');\n    curl_setopt_array($ch, [\n        CURLOPT_POST => true,\n        CURLOPT_RETURNTRANSFER => true,\n        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $token],\n        CURLOPT_TIMEOUT => 30,\n    ]);\n    $raw = curl_exec($ch);\n    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);\n    curl_close($ch);\n\n    if ($status === 401) return null; \u002F\u002F already unusable\n    if ($status !== 200) throw new RuntimeException(\"revoke-token: HTTP $status\");\n    return json_decode($raw, true)['data']['expiresIn'];\n}\n",[389,2690,2691,2697,2716,2720,2739,2745,2756,2766,2781,2791,2795,2805,2819,2825,2829,2851,2880,2905],{"__ignoreMap":560},[564,2692,2693,2695],{"class":566,"line":567},[564,2694,1764],{"class":578},[564,2696,1767],{"class":585},[564,2698,2699,2701,2704,2706,2708,2711,2713],{"class":566,"line":582},[564,2700,1309],{"class":578},[564,2702,2703],{"class":1312}," mt_revoke",[564,2705,1316],{"class":592},[564,2707,970],{"class":578},[564,2709,2710],{"class":592}," $token)",[564,2712,1827],{"class":578},[564,2714,2715],{"class":578}," ?int\n",[564,2717,2718],{"class":566,"line":626},[564,2719,608],{"class":592},[564,2721,2722,2724,2726,2728,2730,2732,2734,2737],{"class":566,"line":639},[564,2723,1968],{"class":592},[564,2725,1820],{"class":578},[564,2727,1973],{"class":585},[564,2729,1316],{"class":592},[564,2731,1978],{"class":585},[564,2733,1981],{"class":578},[564,2735,2736],{"class":574}," '\u002Fapi-account\u002Frevoke-token'",[564,2738,1361],{"class":592},[564,2740,2741,2743],{"class":566,"line":652},[564,2742,1991],{"class":585},[564,2744,1994],{"class":592},[564,2746,2747,2750,2752,2754],{"class":566,"line":661},[564,2748,2749],{"class":585},"        CURLOPT_POST",[564,2751,1880],{"class":578},[564,2753,2004],{"class":585},[564,2755,623],{"class":592},[564,2757,2758,2760,2762,2764],{"class":566,"line":670},[564,2759,1999],{"class":585},[564,2761,1880],{"class":578},[564,2763,2004],{"class":585},[564,2765,623],{"class":592},[564,2767,2768,2770,2772,2774,2776,2778],{"class":566,"line":707},[564,2769,2011],{"class":585},[564,2771,1880],{"class":578},[564,2773,1874],{"class":592},[564,2775,2018],{"class":574},[564,2777,1981],{"class":578},[564,2779,2780],{"class":592}," $token],\n",[564,2782,2783,2785,2787,2789],{"class":566,"line":738},[564,2784,2034],{"class":585},[564,2786,1880],{"class":578},[564,2788,2039],{"class":585},[564,2790,623],{"class":592},[564,2792,2793],{"class":566,"line":768},[564,2794,2046],{"class":592},[564,2796,2797,2799,2801,2803],{"class":566,"line":798},[564,2798,2051],{"class":592},[564,2800,1820],{"class":578},[564,2802,2056],{"class":585},[564,2804,2059],{"class":592},[564,2806,2807,2809,2811,2813,2815,2817],{"class":566,"line":828},[564,2808,2064],{"class":592},[564,2810,1820],{"class":578},[564,2812,2069],{"class":585},[564,2814,2072],{"class":592},[564,2816,2075],{"class":585},[564,2818,1361],{"class":592},[564,2820,2821,2823],{"class":566,"line":858},[564,2822,2082],{"class":585},[564,2824,2059],{"class":592},[564,2826,2827],{"class":566,"line":890},[564,2828,1251],{"emptyLinePlaceholder":1250},[564,2830,2831,2833,2835,2837,2839,2841,2843,2846,2848],{"class":566,"line":896},[564,2832,2093],{"class":578},[564,2834,2096],{"class":592},[564,2836,1519],{"class":578},[564,2838,1522],{"class":585},[564,2840,1525],{"class":592},[564,2842,2599],{"class":578},[564,2844,2845],{"class":585}," null",[564,2847,1778],{"class":592},[564,2849,2850],{"class":1632},"\u002F\u002F already unusable\n",[564,2852,2853,2855,2857,2859,2861,2863,2865,2867,2869,2871,2874,2876,2878],{"class":566,"line":907},[564,2854,2093],{"class":578},[564,2856,2096],{"class":592},[564,2858,2148],{"class":578},[564,2860,2151],{"class":585},[564,2862,1525],{"class":592},[564,2864,1528],{"class":578},[564,2866,1531],{"class":578},[564,2868,2109],{"class":585},[564,2870,1316],{"class":592},[564,2872,2873],{"class":574},"\"revoke-token: HTTP ",[564,2875,2167],{"class":592},[564,2877,2170],{"class":574},[564,2879,1361],{"class":592},[564,2881,2882,2884,2886,2888,2890,2893,2896,2899,2902],{"class":566,"line":1480},[564,2883,1909],{"class":578},[564,2885,2184],{"class":585},[564,2887,2187],{"class":592},[564,2889,1082],{"class":585},[564,2891,2892],{"class":592},")[",[564,2894,2895],{"class":574},"'data'",[564,2897,2898],{"class":592},"][",[564,2900,2901],{"class":574},"'expiresIn'",[564,2903,2904],{"class":592},"];\n",[564,2906,2907],{"class":566,"line":1505},[564,2908,910],{"class":592},[428,2910,45],{"id":2911},"rate-limits",[358,2913,2914,2915,426],{},"Both routes count against your rate limit like any other: 100 requests per 60 seconds, per account and\nper operation. A health check every few seconds from several servers adds up, and they all share one\nbudget because the count belongs to the account. Once a minute is plenty. See\n",[398,2916,45],{"href":46},[428,2918,2920],{"id":2919},"related","Related",[2922,2923,2924,2933,2938],"ul",{},[2925,2926,2927,2929,2930,2932],"li",{},[398,2928,19],{"href":20},": signing tokens, the lifetime and clock rules, and the ",[389,2931,525],{},"\nchecklist.",[2925,2934,2935,2937],{},[398,2936,112],{"href":113},": caching a token, several servers, and revoking on\nshutdown.",[2925,2939,2940,2942],{},[398,2941,25],{"href":26},": what each role grants.",[2944,2945,2946],"style",{},"html pre.shiki code .soyes, html code.shiki .soyes{--shiki-default:#702C00;--shiki-dark:#FFB757}html pre.shiki code .sT6z2, html code.shiki .sT6z2{--shiki-default:#032563;--shiki-dark:#ADDCFF}html pre.shiki code .sHUrx, html code.shiki .sHUrx{--shiki-default:#A0111F;--shiki-dark:#FF9492}html pre.shiki code .s-5SL, html code.shiki .s-5SL{--shiki-default:#023B95;--shiki-dark:#91CBFF}html pre.shiki code .suds8, html code.shiki .suds8{--shiki-default:#0E1116;--shiki-dark:#F0F3F6}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sne4z, html code.shiki .sne4z{--shiki-default:#024C1A;--shiki-dark:#72F088}html pre.shiki code .sKwhi, html code.shiki .sKwhi{--shiki-default:#622CBC;--shiki-dark:#DBB7FF}html pre.shiki code .sLBg1, html code.shiki .sLBg1{--shiki-default:#66707B;--shiki-dark:#BDC4CC}",{"title":560,"searchDepth":582,"depth":626,"links":2948},[2949,2950,2954,2959,2960],{"id":430,"depth":582,"text":431},{"id":547,"depth":582,"text":548,"children":2951},[2952,2953],{"id":942,"depth":626,"text":943},{"id":1109,"depth":626,"text":1110},{"id":2219,"depth":582,"text":415,"children":2955},[2956,2957,2958],{"id":2337,"depth":626,"text":2338},{"id":2395,"depth":626,"text":2396},{"id":2414,"depth":626,"text":2415},{"id":2911,"depth":582,"text":45},{"id":2919,"depth":582,"text":2920},"Check which account a token belongs to and what it may do, and revoke a single token before it expires.","md",{},[2965,2966],"getCurrentApiAccount","revokeToken","50",{"title":353,"description":2961},"api\u002Fguides\u002Fapi-account","gZ1l42lwNYl1azmp7WsKYXzwUbFLzpgQp16bzca3wK8",[2972,2977],{"operationId":2965,"slug":2973,"method":133,"path":2974,"tag":77,"summary":143,"deprecated":134,"public":134,"permission":2975,"scope":2976,"order":626},"get-current-api-account","\u002Fv1\u002Fapi-account\u002Fvalidate-me","api\u002F*:$org:$ID","flat",{"operationId":2966,"slug":477,"method":141,"path":2978,"tag":77,"summary":139,"deprecated":134,"public":134,"permission":2975,"scope":2976,"order":582},"\u002Fv1\u002Fapi-account\u002Frevoke-token",1791554615147]