# Deprecated routes

Canonical page: https://docs.ovok.com/deprecated-routes

Every route below stops answering on **1 December 2026** (`2026-12-01T00:00:00Z`). Until then each one works exactly as it does today. Move to the replacement before that date.

## How a deprecated route tells you [#how-a-deprecated-route-tells-you]

Each answer from a deprecated route carries three headers:

| Header | Example | Meaning |
|---|---|---|
| `Deprecation` ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745)) | `@1729209600` | When the route was deprecated, in Unix seconds (`@1729209600` is 18 October 2024). |
| `Sunset` ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)) | `Tue, 01 Dec 2026 00:00:00 GMT` | When the route stops answering, as an HTTP-date. |
| `Link` | see the example below | This page as `rel="deprecation"` and `rel="sunset"`, and the replacement as `rel="successor-version"` when there is one. |

For example, a login through the legacy route on the sandbox:

```bash
curl -i -X POST https://api.sandbox.ovok.com/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email": "jane@example.com", "password": "…"}'
```

```http
HTTP/1.1 200 OK
Content-Type: application/json
Deprecation: @1729209600
Sunset: Tue, 01 Dec 2026 00:00:00 GMT
Link: <https://docs.ovok.com/production/deprecated-routes>; rel="deprecation"; type="text/html", <https://docs.ovok.com/production/deprecated-routes>; rel="sunset"; type="text/html", </v2/auth/login>; rel="successor-version"
```

A browser client can read all three headers: they are CORS-exposed. In the OpenAPI documents each deprecated operation has `deprecated: true`, a description that names the sunset day and the replacement, and an `x-ovok-deprecation` extension: `{ "deprecated": "2024-10-18", "sunset": "2026-12-01", "successors": ["/v2/auth/login"] }`.

A replacement path that names a parameter of the deprecated route (`:id`, `:resourceType`) carries the value the caller sent, so `GET /resource/Patient` links to `</fhir/R4/Patient>`.

### What your client should do [#what-your-client-should-do]

1. When an answer carries `Deprecation`, log a warning with the method, the path, the `Sunset` date and the `rel="successor-version"` link. Don't fail the request: the route still works.
2. Move each call to its replacement from the tables below before the `Sunset` date. After that date the route no longer answers.

<Callout type="info" title="Known gap">

A route marked deprecated currently omits these headers on a `401` or `403` that is refused before the route runs, for example a missing or expired token. A fix is in progress. Until then, rely on the tables below rather than on a refusal's headers.

</Callout>

## Legacy FHIR CRUD (deprecated 18 October 2024) [#legacy-fhir-crud-deprecated-18-october-2024]

The replacement is the FHIR R4 API: standard FHIR request and response bodies, not the legacy DTOs.

| Deprecated route | Replacement |
|---|---|
| `POST`, `GET /account`; `GET`, `PUT`, `DELETE /account/:id` | `/fhir/R4/Account`, same methods |
| `POST`, `GET /appointment`; `GET`, `PUT`, `DELETE /appointment/:id` | `/fhir/R4/Appointment`, same methods |
| `POST`, `GET /device`; `GET`, `PUT`, `DELETE /device/:id` | `/fhir/R4/Device`, same methods |
| `POST`, `GET /document-reference`; `GET`, `PATCH /document-reference/:id` | `/fhir/R4/DocumentReference` for the resource; `POST /document`, `GET /document`, `GET`, `PATCH /document/:id` for files |
| `POST`, `GET /location`; `GET`, `PUT`, `DELETE /location/:id` | `/fhir/R4/Location`, same methods |
| `GET /location/schedule`, `GET /location/:id/schedule` | No combined route: read `/fhir/R4/Location` and `/fhir/R4/Schedule` |
| `POST`, `GET /observation`; `GET`, `PUT`, `DELETE /observation/:id` | `/fhir/R4/Observation`, same methods |
| `POST`, `GET /patient`; `GET`, `PUT`, `PATCH`, `DELETE /patient/:id` | `/fhir/R4/Patient`, same methods |
| `GET /patient/:id/observation` | `GET /fhir/R4/Observation/$lastn?patient=Patient/:id` |
| `POST`, `GET /questionnaire`; `GET`, `PUT`, `DELETE /questionnaire/:id` | `/fhir/R4/Questionnaire`, same methods |
| `POST`, `GET /resource/:resourceType`; `GET`, `PUT`, `PATCH`, `DELETE /resource/:resourceType/:id` | `/fhir/R4/:resourceType`, same methods |
| `POST`, `GET /schedule`; `GET`, `PUT`, `DELETE /schedule/:id` | `/fhir/R4/Schedule`, same methods |
| `GET`, `POST /bot/execute` | `GET`, `POST /bots?identifier=<system>\|<code>` |
| `GET`, `POST /bot/:id/execute` | None: run a bot by identifier through `/bots` |

## Files (deprecated 18 October 2024) [#files-deprecated-18-october-2024]

| Deprecated route | Replacement |
|---|---|
| `POST /binary/single` | `POST /document`: it answers a signed upload form, and the file goes straight to storage |
| `POST /binary/multiple` | None as a batch: call `POST /document` once per file |
| `GET /binary/:documentReferenceId` | `GET /document/:id` (a `307` to a signed URL) |

## Authentication (deprecated 18 October 2024) [#authentication-deprecated-18-october-2024]

| Deprecated route | Replacement |
|---|---|
| `POST /auth/login` | `POST /v2/auth/login` |
| `POST /auth/change-password` | `PATCH /v2/auth/change-password` |
| `POST /auth/reset-password` | `POST /v2/auth/reset-password` |
| `POST /auth/set-password` | `POST /v2/auth/reset-password/process` |
| `PATCH /auth/update-email` | None |
| `DELETE /auth/deregister-user` | `DELETE /auth/delete` |
| `POST /auth/signup` | `POST /auth/tenant/Patient/register` or `POST /auth/tenant/Practitioner/register` |
| `POST /auth/external/google` | None |
| `POST /auth/external/apple` | None |
| `POST /auth/tan-login/:tan` | `POST /auth/login/tan`, with the TAN in the body |

## Video calls (deprecated 18 October 2024) [#video-calls-deprecated-18-october-2024]

| Deprecated route | Replacement |
|---|---|
| `POST /v3/video-call/appointment` | `POST /video-call/livekit/appointment` |
| `POST /v3/video-call/user-access` | `POST /video-call/livekit/user-access/:appointmentId` |
| `POST /v3/video-call/guest-access` | `POST /video-call/livekit/guest-access/:appointmentId` |

## Slim (dashboard) routes [#slim-dashboard-routes]

| Deprecated route | Deprecated on | Replacement |
|---|---|---|
| `GET /v1/slim/query_new` | 13 April 2026 | `GET /v1/slim/device/live` |
| `GET /v1/slim/query_new/telemetry` | 13 April 2026 | `GET /v1/slim/device/live/telemetry` |
| `GET`, `POST /v1/slim/user/medical-settings-notifications-consent` | 2 October 2026 | `GET`, `POST /v1/me/consent/medical` |
| `GET /v1/slim/notifications` | 3 October 2026 | `GET /v1/slim/notifications/oob` (out of bed), `/alarms` (device alarms and attention presses), `/medical` (HR/BR) |
| Any `/v{n}/carehub/...` path | 30 September 2026 | The same path under `/v{n}/slim/...` |

`/v{n}/carehub/...` is a hidden alias: it is in no OpenAPI document, and every answer, refusals included, links its own `/v{n}/slim/...` path as `rel="successor-version"`. When the slim route is itself deprecated, `Deprecation` carries that route's date.

## Invitations (deprecated 22 October 2026) [#invitations-deprecated-22-october-2026]

The share invitations are now named by purpose. Each old route still works exactly as before, with the same gates and status codes, and carries `Deprecation: @1792627200` and a `rel="successor-version"` link to its replacement.

| Deprecated route | Replacement | What to change |
|---|---|---|
| `POST /v1/invites/practitioner` | `POST /v1/invites/record-share` | Add `"recipient": "practitioner"` to the body. See [Share a record with a practitioner](/invitations/share-with-practitioner). |
| `POST /v1/invites/practitioner/accept` | `POST /v1/invites/record-share/accept` | Nothing else. The new route also accepts [carer invites](/invitations/share-with-a-carer#step-2-accept). |
| `POST /v1/invites/patient` | `POST /v1/invites/care` | Nothing else. See [Invite a patient into care](/invitations/invite-a-patient). |
| `POST /v1/invites/patient/accept` | `POST /v1/invites/care/accept` | Nothing else. |

Until the sunset, a practitioner offer or a care invitation sent through either route can be accepted on either. Carer invitations exist only on the new routes.

## Deprecated fields [#deprecated-fields]

`POST /auth/refresh-token` still answers `access_token`, `refresh_token` and `expires_in` beside `accessToken`, `refreshToken` and `expiresIn`. The snake-case fields are deprecated in the OpenAPI schema; read the camel-case ones. They have no sunset date yet.
