---
title: "Replace user preferences in bulk"
method: PUT
path: "/users/{user_id}/preferences"
tags: ["User Preferences"]
---

# Replace user preferences in bulk

`PUT /users/{user_id}/preferences`

Replaces a user's entire set of preference overrides. Any topic you leave out is reset to its default, so send the full set rather than a subset.

## Path parameters

- `user_id` string, required

## Query parameters

- `tenant_id` string, nullable

## Request body

- UsersBulkReplacePreferencesParams
  - `topics` UsersBulkTopicPreferenceUpdate[], required — The complete set of topic overrides for the user. Up to 50 topics may be provided. Any existing override not listed here is reset to its topic default; an empty array resets every existing override.
    - `topic_id` string, required — A unique identifier associated with a subscription topic.
    - `status` 'OPTED_IN' | 'OPTED_OUT', required — The subscription status to apply for this topic.
    - `has_custom_routing` boolean — Whether the recipient has chosen specific delivery channels for this topic.
    - `custom_routing` ChannelClassification[] — The channels a user has chosen to receive notifications through for this topic.

## Response `200`

The replacement was applied. `items` contains the complete resulting set of topic overrides for the user, and `deleted` lists the ids of the overrides that were reset to their topic default.

- UsersBulkReplacePreferencesResponse
  - `items` UsersBulkPreferenceTopic[], required — The complete resulting set of topic overrides for the user.
    - `topic_id` string, required
    - `status` 'OPTED_IN' | 'OPTED_OUT', required — The applied subscription status. Echoes the requested value, so it is always OPTED_IN or OPTED_OUT.
    - `has_custom_routing` boolean, required
    - `custom_routing` ChannelClassification[], required
  - `deleted` string[], required — The ids of the overrides that were reset to their topic default.

## Other responses

- `400` — The request was rejected and nothing was applied. Semantic validation failures (unknown topic, a REQUIRED topic that cannot be opted out, or plan-gated custom routing) are aggregated into UsersBulkPreferenceValidationError (with a per-topic errors list). Structural failures (missing/oversized topics, unknown properties, malformed JSON) return the standard BadRequest shape.
- `429` — Too many requests; the client has been rate limited.

---

[API](https://skmtc.net/trycourier/apis/courier.md) · [All operations](https://skmtc.net/trycourier/apis/courier/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/trycourier/courier/versions/04f69fbf96a5/schema)
