---
title: "Update Preferences"
method: PUT
path: "/v1/notification-preferences"
tags: ["notification-preferences"]
---

# Update Preferences

`PUT /v1/notification-preferences`

## Request

- Base URL: `https://api.usekeel.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.usekeel.io/v1/notification-preferences`
- Auth: none declared

Full replace of the caller's preferences (04-AC-23).

Field-level rules (operational always-on, IANA timezone, exactly the
spec 01 §3 fields) live on the request model — an invalid write 422s
before anything touches the database. Every changed boolean is also
recorded as a ``notification_preference.changed`` event (D17).

## Headers

- `Authorization` string, nullable
- `X-Org-Id` string, nullable

## Request body

- UpdateNotificationPreferencesRequest: `PUT /v1/notification-preferences` body (04-AC-23). A FULL replace of exactly the spec 01 §3 fields — all six required, no others accepted (no per-trigger toggles exist in v1, R-5). Two rules are enforced HERE, as validation errors and never silent ignores: - ``operational`` may not be disabled: operational (A/D) in-app delivery is always-on (spec 01 §3, spec 04 §5's interpretation note), and accepting-then-ignoring the flag is exactly the silent ignore 04-AC-23 bans. (``in_app_enabled``/``email_enabled`` remain lawful writes: the channel booleans govern non-operational classes — spec 01 §3's parenthetical exempts operational from them in the engine.) - ``timezone`` must be a real IANA zone name or null (spec 01 §3 — explicit storage, never geoip).
  - `operational` boolean, required
  - `product_updates` boolean, required
  - `announcements` boolean, required
  - `email_enabled` boolean, required
  - `in_app_enabled` boolean, required
  - `timezone` string, nullable, required

## Response `200`

Successful Response

- NotificationPreferencesResponse: `GET/PUT /v1/notification-preferences` — exactly the spec 01 §3 fields. ``principal_id``/``created_at``/``updated_at`` are scoping/storage internals and stay unexposed (same stance as §1.2's send_id).
  - `operational` boolean, required
  - `product_updates` boolean, required
  - `announcements` boolean, required
  - `email_enabled` boolean, required
  - `in_app_enabled` boolean, required
  - `timezone` string, nullable, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/usekeel/apis/keel-api.md) · [All operations](https://skmtc.dev/usekeel/apis/keel-api/llms.txt) · [OpenAPI document](https://skmtc.dev/usekeel/apis/keel-api/revisions/3191ca10b0ab?raw)
