# V1 compatibility

V2 supports two different kinds of “keep the old thing working.” This page covers both, in human terms. The exact contract is in v1-compatibility.md.


# The big picture

flowchart LR
  subgraph callers [Callers]
    OldHTTP["Legacy HTTP clients"]
    OldFacade["Old notification.success API"]
    NewClient["New NotificationsClient"]
  end

  subgraph service [This service]
    V1["/api/Notification/*"]
    V2["/v1/*"]
    DB[(Same notifications table)]
  end

  OldHTTP --> V1
  OldFacade --> V2
  NewClient --> V2
  V1 --> DB
  V2 --> DB

A notification created via V1 appears in V2 lists and vice versa. You can migrate producers and consumers on separate schedules.


# 1. Legacy HTTP surface (/api/Notification/*)

Still fully supported (marked deprecated in OpenAPI, no removal date until traffic is gone).

V1 endpoint What it does V2 equivalent
POST /api/Notification/Create/{user} Create for {user} POST /v1/notifications
POST /api/Notification/CreatePayload/{user}?payload-type=&entity= Template create POST /v1/notifications
PUT …/SetViewed/{id} Mark read POST /v1/notifications/{id}/read
PUT …/SetUnread/{id} Mark unread POST /v1/notifications/{id}/unread
PUT …/Remove/{id} Delete DELETE /v1/notifications/{id}
DELETE …/ForceRemove/{id} Delete DELETE /v1/notifications/{id}

# What you change in the old client

Usually just the base URL — point it at this service instead of the old host.

# Auth change (important)

V1 used to trust a shared API key in some deployments. This service does not.
Create / CreatePayload need a real publisher Cognito token (scope or group). Inbox mutations still use the caller’s user token.

# Response shape

V1 routes keep the classic envelope (never problem+json):

{
  "value": { "id": "…" },
  "errors": [],
  "warnings": []
}

# Templates (CreatePayload)

Configure V1_PAYLOAD_TEMPLATES on the Worker (JSON map of payload-type → title/body/actionUrl). {entity} is substituted from the query string. Retries are idempotent per (user, payload-type, entity) — an upgrade over classic V1.


# 2. Legacy app façade (notification.success(...))

The old Video Library quick-start looked like:

await notification.success('Title', 'Message', '/optional-url');

V2 supports that shape without shipping a magic global:

// lib/notificationService.ts
import { NotificationsClient, createNotificationService } from '@inovus-medical/notifications';

const client = new NotificationsClient({
  baseUrl: 'https://notifications.totumcloud.com',
  getAccessToken: () => auth.getValidAccessToken(),
});

export const notification = createNotificationService(client);

Existing imports of ./lib/notificationService can keep working. Toasts stay in your app.


# Intentional small differences (HTTP V1)

None of these usually matter if clients treat ids as opaque and only read the envelope:

  1. Remove is a real delete (V1 called it soft-delete but offered no restore API)
  2. Notification ids are UUIDs from this service
  3. CreatePayload retries no longer duplicate
  4. Failures set accurate HTTP status codes and fill errors[]

Full list: v1-compatibility.md.


# Suggested migration order

  1. Point legacy HTTP callers at the new base URL; verify envelopes
  2. Give producers Cognito M2M clients (retire shared API keys)
  3. Move producers to client.publish + dedupeKey when convenient
  4. Move the bell to NotificationsClient / useNotifications
  5. Swap notification.success to createNotificationService
  6. Decommission the old VL table / edge function / shared secrets when logs show no V1 traffic
flowchart TD
  A["Base URL cutover"] --> B["Cognito publisher tokens"]
  B --> C["New publish + dedupeKey"]
  C --> D["New inbox client / React hook"]
  D --> E["Convenience façade"]
  E --> F["Turn off legacy infra"]

# Why bother migrating at all?

You don’t have to overnight — but V2 gives you pagination, honest polling, safe retries, OpenAPI, and multi-app reuse. The compatibility layers exist so migration can be boring.

Next: Advanced usage, or the deep dive in why-v2.md.