# Refresh access token

Canonical page: https://docs.ovok.com/api/authentication/refresh-access-token

`POST /auth/refresh-token`

Exchanges a refresh token for a new access token and a new refresh token. Call it before the access token expires to keep a session alive.

**Auth:** none. The refresh token in the body is the credential.

## Behaviour

- Ovok forwards the token to Medplum's `oauth2/token` endpoint (`grant_type=refresh_token`, scope `openid offline_access`).
- The request body takes the token as `refresh_token`.
- The response holds `accessToken`, `refreshToken` and `expiresIn` (seconds), the same names the login routes use. Store the new `refreshToken`: use it for the next refresh.
- The response also carries the same three values as `access_token`, `refresh_token` and `expires_in`. Those names are deprecated and will be removed in a later release: read the camelCase ones.
- A refresh token Medplum refuses (spent, expired, revoked, or not a refresh token at all) gives a 401 with Medplum's error description. A refresh token is single-use, so retrying it after a successful refresh also gives a 401: sign in again.
- A body without `refresh_token` gives a 400.
- A session of a Patient whose project turned `PATIENT_LOGIN_ENABLED` off, or of a Practitioner whose project turned `PRACTITIONER_LOGIN_ENABLED` off, gives a 403 `Login is not enabled for this project.` That ends the session: the refresh token is used up, and signing in again is refused while login is off. A Practitioner who is a project admin is not refused, so an admin who is signed in can still turn login back on (they cannot sign in again while it is off). The access token already issued lasts until it expires (60 minutes).
- `POST /oauth2/token` applies the same check to every token it grants (refresh and code exchange), answering `403 { "error": "access_denied", "error_description": "Login is not enabled for this project." }`.

## Example

```bash
curl -X POST 'https://api.sandbox.ovok.com/auth/refresh-token' \
  -H 'Content-Type: application/json' \
  -d '{
    "refresh_token": "example.jwt.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk"
  }'
```
