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

# Update user preferences in bulk

`POST /users/{user_id}/preferences`

Adds or updates a user's preferences for several subscription topics at once. Topics you leave out keep whatever they were set to before.

## Path parameters

- `user_id` string, required

## Query parameters

- `tenant_id` string, nullable

## Headers

- `Idempotency-Key` string
- `x-idempotency-expiration` string

## Request body

- UsersBulkUpdatePreferencesParams
  - `topics` UsersBulkTopicPreferenceUpdate[], required — The topics to create or update. Between 1 and 50 topics may be provided in a single request.
    - `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 bulk update was applied. `items` contains the resulting topic overrides that were created or updated, and `errors` lists any topics that could not be applied, each with a reason.

- UsersBulkUpdatePreferencesResponse
  - `items` UsersBulkPreferenceTopic[], required — The topics that were successfully created or updated.
    - `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
  - `errors` UsersBulkPreferenceError[], required — The topics that could not be applied, each with a reason.
    - `topic_id` string, required
    - `reason` string, required — A human-readable explanation of why the topic could not be applied.

## Other responses

- `400` — The request was malformed and nothing was applied — for example a missing or oversized `topics` array, unknown properties, or malformed JSON.
- `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)
