# Exchange practitioner session code for tokens

Canonical page: https://docs.ovok.com/api/tenant-authentication/exchange-practitioner-session-code-for-tokens

`POST /auth/tenant/Practitioner/login/token`

Finishes a practitioner login into one tenant: binds the session to the practitioner's membership in that tenant, then exchanges the session code and your PKCE `codeVerifier` for an access token and a refresh token.

**Auth:** none. The session code and code verifier prove the earlier steps.
**Scope:** the project that owns `tenantCode`. Pick it from the `profiles` returned by `login/start` or `login/mfa`.

## Behaviour

- `PRACTITIONER_LOGIN_ENABLED` on the chosen project must not be `false` (it defaults to on).
- The practitioner must have a membership in the chosen tenant. Ovok points the pending login at that membership before the code is redeemed, so the tokens are scoped to that project.
- Ovok redeems the code with Medplum's `oauth2/token` endpoint (`grant_type=authorization_code`).
- If the account was scheduled for deletion (`DELETE /auth/delete`), logging in cancels the deletion.
- The response holds `accessToken`, `refreshToken`, `expiresIn` (seconds) and references to the `project` and `profile`.
- Error responses are delayed to take at least one second.

## Example

```bash
curl -X POST 'https://api.sandbox.ovok.com/auth/tenant/Practitioner/login/token' \
  -H 'Content-Type: application/json' \
  -d '{
    "sessionCode": "<sessionCode from login/start>",
    "codeVerifier": "<your codeVerifier>",
    "tenantCode": "my-medical-project"
  }'
```
