VISH app — RUT (MIIT) timetable

The timetable of the Russian University of Transport for students and staff of every institute. The timetable of your own group and of any teacher by day and week, free MIIT rooms right now, occupancy of rooms, groups and teachers, notifications about timetable changes and an AI timetable assistant.

Institutes

The RUT (MIIT) app covers five institutes: VISH — Higher Engineering School, AGA — Civil Aviation Academy, ADKH — Road Management Academy, PISH — Advanced Engineering School “HSR Academy” and IMTK — Institute of International Transport Communications. A group’s and a teacher’s timetable are searched the same way in any of them.

What the VISH app can do
Sections
Guide

Authentication: API keys and OAuth

Updated 27.10.2026

In API VISH, there are three ways to access the method: without logging in, with an API key, and with an OAuth token from “Logging in through VISH”. Which one to choose depends on whose data you are reading and who is running the program. Checked with booth d1 on October 23, 2026.

What to choose

Without loginAPI keyOAuth token (“Login via VISH”)
What isOpen data for: schedules, groups, teachers, classroomsYour script, bot, upload, dashboardYour website or application that includes other people
On behalf of whomOn behalf of no oneOn your behalf, within the rights of the keyOn behalf of the logged-in person, with his consent
How istransmitted —Header X-Api-Key: vish_…Header Authorization: Bearer …
What is allowedPublic methods GETEverything that is allowed by the key and your roleRead-only from the short list of methods
Срок—До даты в ключе (выпущенный себе — не дольше 730 дней)15 минут, дальше обновление токеном refresh
Where there isd1 and productiond1 and productionSo far only d1

If you don't need to read anything personal, do without logging in: fewer secrets, fewer risks.

API Key

The key is obtained on the “Developer page in the application. For” more information, see the API and Access Keys page. The key starts with vish_ and is passed in a separate header.:

bash
curl -H "X-Api-Key: $VISH_API_KEY" "$VISH_API/auth/me"
  • A request with a key is a request on your behalf, but only within the rights specified when issuing the key. What is not in the set, the key will be refused, even if you have the right to do so yourself. If your role's rights are later reduced, the key also loses them — immediately, from the next request.
  • The key is in the header, never in the address: addresses end up in logs, browser history, and header Referer.
  • If both the key and Authorization are in the request, the key is counted.
  • Some methods are only for the person in the application: your key, personal notes, consent, account deletion. You can't call them with a key — the answer is 403 SESSION_REQUIRED.
  • Reissue the key that appeared somewhere with the “Reissue” button on the “developer” page: the old line stops working immediately.

Check the key and see what it is allowed to do:

// Who the key acts as, and which permissions it carries.
const API = process.env.VISH_API ?? 'https://d1.vish-app.ru/api/v1'
const KEY = process.env.VISH_API_KEY
if (!KEY) throw new Error('set VISH_API_KEY')

const response = await fetch(`${API}/auth/me`, { headers: { 'X-Api-Key': KEY } })
const me = await response.json()
if (!response.ok || !me.id) throw new Error(`HTTP ${response.status}: ${JSON.stringify(me)}`)

console.log('role:', me.role)
console.log('permissions:', me.permissions.length ? me.permissions.join(', ') : '(none: public reads only)')

The OAuth token

The access token allows you to “log in through VISH”: a person logs into your app with account VISH and allows them access. How to enable it is on the Login through VISH for developers page. Here's how the token differs from the key.:

  • Passed in header Authorization: Bearer <access_token>.
  • It acts on behalf of the logged-in person, but only for reading and only for the methods that the granted permission calls.: schedule:read — GET /schedule, GET /schedule/subscriptions/mine, GET /schedule/{id}/subscription; notes:read — GET /schedule/{id}/notes. Any other method will answer 403 OAUTH_SCOPE_INSUFFICIENT.
  • Employee or administrator rights, if a person has them, are not transferred to the token.
  • It lives for 15 minutes; a new one is received with a refresh token (30 days, changes with each update).
  • The browser will not allow you to read responses to such requests (CORS) from a page on another site: call schedule methods with a token from your server. Only protocol addresses /oauth/… are available from the browser.
  • A person can disable your application in “Settings” → “Access” → “Connected token applications” stop working from the next request.

Log in to the app itself

Application VISH logs in via Telegram or MAX and receives its Bearer token. This input is for people in the application, not for integrations: do not try to repeat it from the script. The script needs a key, and someone else's site needs to “log in through VISH”.

Login Errors

HTTPerror.codeWhat happened
401AUTH_REQUIREDThe method requires login, but there is no key or token
401UNAUTHORIZEDThe key is incorrect, revoked, expired, or its owner is no longer there
401ACCESS_TOKEN_INVALIDBearer-the token is invalid or expired — update it
403SESSION_REQUIREDThe human-only method in Appendix
403OAUTH_SCOPE_INSUFFICIENTThis method is not allowed for the OAuth token
403FORBIDDENMissing rights — see Access Rights (RBAC)

What failures look like — without a real key, with obviously incorrect values:

// A made-up key and a made-up bearer token are both refused with 401.
const API = process.env.VISH_API ?? 'https://d1.vish-app.ru/api/v1'

const attempt = async (headers) => {
	const response = await fetch(`${API}/auth/me`, { headers })
	return { status: response.status, code: (await response.json()).error?.code }
}

const key = await attempt({ 'X-Api-Key': 'vish_not_a_real_key' })
const bearer = await attempt({ Authorization: 'Bearer not-a-real-token' })

if (key.status !== 401 || key.code !== 'UNAUTHORIZED') throw new Error(`key: ${JSON.stringify(key)}`)
if (bearer.status !== 401 || bearer.code !== 'ACCESS_TOKEN_INVALID') throw new Error(`bearer: ${JSON.stringify(bearer)}`)
console.log('made-up key   ->', key.status, key.code)
console.log('made-up token ->', bearer.status, bearer.code)

Try it: the method below will answer 401 without a key, and with your key in the “API Key” field, it will answer with your data. The key remains only in this tab and is not saved anywhere.

Try the request

Only methods with a lock need a key. It lives on this page only: it is never stored, goes out only as a header of this request and is forgotten when you leave. Where to get a key

Verified: 2026-10, PWA aa337c45, platform bff65fce._