Перейти к содержимому

Аутентификация

После входа или подтверждения телефона API выдаёт пару токенов. Access-токен подписывает запросы, refresh-токен обменивается на новую пару, когда access-токен истёк.

Токен Формат Срок жизни Где хранить
access JWT 15 минут в памяти приложения
refresh непрозрачная строка 30 дней мобильный клиент — в защищённом хранилище; веб — httpOnly-кука

Точные сроки приходят в ответе: accessTokenExpiresIn — время жизни access-токена в секундах, refreshTokenExpiresAt — момент истечения refresh-токена. Ориентируйтесь на них, а не на цифры из таблицы.

Такой ответ возвращают /v1/auth/verify-phone, /v1/auth/login, /v1/auth/login/sms и /v1/auth/refresh.

{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"accessTokenExpiresIn": 900,
"refreshToken": "3f1c2d9e-6b7a-4c55-9a51-0d8e7f6a1b2c.kq3Vb8...",
"refreshTokenExpiresAt": "2026-10-24T09:15:00.000Z"
}
Поле Тип Описание
accessToken string JWT для заголовка Authorization: Bearer
accessTokenExpiresIn integer через сколько секунд истечёт access-токен
refreshToken string только мобильным клиентам; веб получает его в куке
refreshTokenExpiresAt string ISO 8601, только мобильным клиентам

Способ доставки refresh-токена выбирает заголовок X-Client.

Заголовок X-Client не передаётся. Refresh-токен приходит в теле ответа; храните его в Keychain (iOS) или EncryptedSharedPreferences / Keystore (Android). Для обновления передайте его в теле:

Окно терминала
curl -X POST https://api.rekassa.uz/v1/auth/refresh \
-H 'Content-Type: application/json' \
-d '{"refreshToken": "3f1c2d9e-6b7a-4c55-9a51-0d8e7f6a1b2c.kq3Vb8..."}'
POST/v1/auth/refresh

POST /v1/auth/refresh выдаёт новую пару и сразу отзывает предъявленный refresh-токен: каждый refresh-токен одноразовый (ротация). Срок жизни сессии при этом продлевается ещё на 30 дней от момента обновления.

  1. Отправьте запрос с access-токеном. Если API ответил 401 с кодом unauthorized, access-токен истёк или недействителен.

  2. Вызовите POST /v1/auth/refresh — ровно один раз, даже если в этот момент 401 получили несколько запросов.

  3. Сохраните новую пару и повторите исходные запросы с новым access-токеном.

  4. Если refresh ответил 401 с кодом session_expired, сессия закончилась: удалите токены и отправьте пользователя на экран входа.

let refreshing = null
/** Все запросы, получившие 401, ждут одно и то же обновление. */
function refreshTokens() {
refreshing ??= fetch('https://api.rekassa.uz/v1/auth/refresh', {
method: 'POST',
credentials: 'include',
headers: { 'X-Client': 'web' },
})
.then((response) => {
if (!response.ok) throw new Error('session_expired')
return response.json()
})
.finally(() => {
refreshing = null
})
return refreshing
}

session_expired возвращается, когда refresh-токен не передан, повреждён, истёк, уже был использован, сессия завершена или пользователь заблокирован. Браузерному клиенту при этом API удаляет куку rk_refresh.

POST/v1/auth/logout

POST /v1/auth/logout завершает текущую сессию и удаляет куку. Access-токен в заголовке не нужен — сессию определяет refresh-токен: мобильный клиент передаёт его в теле, браузер — куку.

Окно терминала
curl -X POST https://api.rekassa.uz/v1/auth/logout \
-H 'Content-Type: application/json' \
-d '{"refreshToken": "3f1c2d9e-6b7a-4c55-9a51-0d8e7f6a1b2c.kq3Vb8..."}'

Ответ — 204 No Content, в том числе если сессия уже была завершена. Завершить сессию на другом устройстве можно через DELETE /v1/me/sessions/{id}.

Событие Что происходит
Сброс пароля по SMS завершаются все сессии пользователя
Смена пароля в профиле завершаются все сессии, кроме текущей
Смена пароля или блокировка сотрудником портала завершаются все сессии пользователя
Повторное использование refresh-токена завершается эта сессия
POST /v1/auth/logout, DELETE /v1/me/sessions/{id} завершается указанная сессия