---
title: "Update Preference Categories"
method: POST
path: "/v1/{workspace}/preference_category/"
---

# Update Preference Categories

`POST /v1/{workspace}/preference_category/`

Use this API to set preference categories to be used in workflow or to show on user preference page.

## Path parameters

- `workspace` string, required

## Query parameters

- `commit` boolean
- `commit_message` string

## Request body

- object
  - `root_categories` object[] — Array of root preference categories. Include all three root categories (system, transactional, promotional) even if empty.
    - `root_category` 'system' | 'transactional' | 'promotional' — Root category classification. system=critical notifications, transactional=user actions, promotional=marketing.
    - `sections` object[] — Sections group related categories. Users cannot set preferences at section level.
      - `name` string — Name of the section displayed in the preference interface.
      - `description` string — Description of what notifications this section covers.
      - `tags` string[] — Tags to organize and filter sections. Use lowercase, hyphenated values (e.g., "security", "billing").
      - `categories` object[] — Categories that users can set preferences for.
        - `category` string — Unique identifier for the category. Use lowercase letters, numbers, and hyphens only.
        - `name` string — Display name for the category shown in the preference interface.
        - `description` string — Description of what notifications this category covers.
        - `default_preference` 'opt_in' | 'opt_out' | 'cant_unsubscribe' — Default preference setting for this category.
        - `default_mandatory_channels` string[] — Channels that users cannot unsubscribe from when default preference is cant_unsubscribe.
        - `default_opt_in_channels` string[], nullable — Add channels that should be opted-in by default when preference is either `On` or `Can't Unsubscribe`. Set to null or do not pass this parameter to set all channels as opted-in. In case of `Can't Unsubscribe`, mandatory channels are opted-in by default.
        - `tags` string[] — Tags to organize and filter categories. Use lowercase, hyphenated values (e.g., "user-management", "payment-alerts").
        - `digest_schedule` DigestSchedule, nullable — Digest schedule configuration for batching notifications. Set enabled to `false` to disable digest or don't pass this key. Digest schedule will only apply if you add digest node in the workflow linked to this category and set the `schedule_type` in node config to `category_digest_schedule`.
          - `enabled` boolean — Whether you want to give digest options against this category.
          - `options` object[] — Array of digest schedule options (up to 10). Exactly one option must have `is_default` set to true.
            - `id` string — Unique identifier for the option. Max 64 characters, allowed characters: [a-z0-9_-]. id is generated from label if not set.
            - `label` string — Display label to be shown to user for the option.
            - `frequency` 'instantly' | 'minutely' | 'hourly' | 'daily' | 'weekly' | 'weekly_mo2fr' | 'monthly' — Frequency of the digest schedule. Instant means the notification will be sent immediately without batching. You can also use this in workflow branch to take users through different flow basis on the frequency.
            - `interval` integer — Interval multiplier for the frequency (e.g., interval=2 with frequency=weekly means every 2 weeks). Default value = 1.
            - `time` object — For `daily`, `weekly`, and `monthly` frequencies, this is the exact time the notification is sent. For `hourly` and `minutely` (interval > 1) frequencies, it's the anchor time from which subsequent intervals are calculated. Applies to all frequencies except `instantly` and `minutely` with interval=1.
              - …
            - `weekdays` object — Weekday configuration. Applicable for `weekly` and `weekly_mo2fr` frequencies. For `weekly_mo2fr`, edit_policy is always `locked` with weekdays Monday through Friday.
              - …
            - `monthdays` object — Monthday configuration. Applicable for `monthly` frequency.
              - …
            - `dtstart` object — Start date-time configuration. Only applicable for `daily` frequency with interval > 1.
              - …
            - `is_default` boolean — Whether this option is the default selection. Exactly one option in the array must be set to true.
        - `properties` CategoryConditionProperty[], nullable — Condition properties for the category (up to 25). Set to null to disable conditions.
          - `key` string — Unique identifier for the property. Must match the pattern [_a-z][a-z0-9_]+ and be at most 64 characters. Reference it in a workflow condition block as `$category.properties.key`. For example, to match a recipient's `role` subscription property against the category's `role` property: `$recipient.subscription.role == $category.properties.role`.
          - `label` string — Optional Display label for the property to be shown to user inside the preference centre.
          - `value_type` 'integer' | 'string' | 'string_choice' | 'list_choice' | 'string_dynamic' | 'list_dynamic' — Data type of the property value
          - `is_optional` boolean — Whether this property is optional. For optional property, default value is not required.
          - `choices` object[] — Available choices when value_type is `string_choice` or `list_choice`. Up to 25 choices. `string_choice` means single-select list and `list_choice` means multi-select list.
            - `value` string — The underlying value of this choice. This is the value passed to the workflow when the choice is selected.
            - `label` string — Display label for the choice
          - `default_value` unknown
          - `dynamic_choices_key` string — Key path your UI will use to populate dynamic choices. Applicable for `string_dynamic` and `list_dynamic` value types.
          - `edit_policy` 'locked' | 'editable' — Whether the recipient can edit this property value. `Locked` means can't edit. Tenant can always edit irrespective of edit_policy.

## Response `200`

Successfully created/updated preference category

- object
  - `$schema` string — JSON schema reference for preference category structure
  - `root_categories` object[] — Array of root preference categories
    - `root_category` string — The root category classification for the preference category
    - `sections` object[] — Array of sections within the preference category. Can be empty if not yet configured.
      - `name` string — Name of the section
      - `description` string — Description of what notifications this section covers
      - `tags` string[] — Tags to organize and filter sections. Use lowercase, hyphenated values.
      - `categories` object[] — Array of categories within this section. Can be empty if not yet configured.
        - `category` string — Unique identifier for the category
        - `name` string — Display name for the category
        - `description` string — Description of what notifications this category covers
        - `default_preference` 'opt_in' | 'opt_out' | 'cant_unsubscribe' — Default preference setting for this category
        - `default_mandatory_channels` string[] — Channels that are mandatory for this category
        - `default_opt_in_channels` string[], nullable — These channels will only be opt_in when the default preference is `opt_in` or `cant_unsubscribe`. Other channels will be opt_out by default. If not set, all channels will be opt_in by default.
        - `tags` string[] — Tags to organize and filter categories. Use lowercase, hyphenated values (e.g., "user-management", "payment-alerts").
        - `digest_schedule` DigestSchedule, nullable — Digest schedule configuration for batching notifications. Set enabled to `false` to disable digest or don't pass this key. Digest schedule will only apply if you add digest node in the workflow linked to this category and set the `schedule_type` in node config to `category_digest_schedule`.
          - `enabled` boolean — Whether you want to give digest options against this category.
          - `options` object[] — Array of digest schedule options (up to 10). Exactly one option must have `is_default` set to true.
            - `id` string — Unique identifier for the option. Max 64 characters, allowed characters: [a-z0-9_-]. id is generated from label if not set.
            - `label` string — Display label to be shown to user for the option.
            - `frequency` 'instantly' | 'minutely' | 'hourly' | 'daily' | 'weekly' | 'weekly_mo2fr' | 'monthly' — Frequency of the digest schedule. Instant means the notification will be sent immediately without batching. You can also use this in workflow branch to take users through different flow basis on the frequency.
            - `interval` integer — Interval multiplier for the frequency (e.g., interval=2 with frequency=weekly means every 2 weeks). Default value = 1.
            - `time` object — For `daily`, `weekly`, and `monthly` frequencies, this is the exact time the notification is sent. For `hourly` and `minutely` (interval > 1) frequencies, it's the anchor time from which subsequent intervals are calculated. Applies to all frequencies except `instantly` and `minutely` with interval=1.
              - …
            - `weekdays` object — Weekday configuration. Applicable for `weekly` and `weekly_mo2fr` frequencies. For `weekly_mo2fr`, edit_policy is always `locked` with weekdays Monday through Friday.
              - …
            - `monthdays` object — Monthday configuration. Applicable for `monthly` frequency.
              - …
            - `dtstart` object — Start date-time configuration. Only applicable for `daily` frequency with interval > 1.
              - …
            - `is_default` boolean — Whether this option is the default selection. Exactly one option in the array must be set to true.
        - `properties` CategoryConditionProperty[], nullable — Condition properties for the category (up to 25). Set to null to disable conditions.
          - `key` string — Unique identifier for the property. Must match the pattern [_a-z][a-z0-9_]+ and be at most 64 characters. Reference it in a workflow condition block as `$category.properties.key`. For example, to match a recipient's `role` subscription property against the category's `role` property: `$recipient.subscription.role == $category.properties.role`.
          - `label` string — Optional Display label for the property to be shown to user inside the preference centre.
          - `value_type` 'integer' | 'string' | 'string_choice' | 'list_choice' | 'string_dynamic' | 'list_dynamic' — Data type of the property value
          - `is_optional` boolean — Whether this property is optional. For optional property, default value is not required.
          - `choices` object[] — Available choices when value_type is `string_choice` or `list_choice`. Up to 25 choices. `string_choice` means single-select list and `list_choice` means multi-select list.
            - `value` string — The underlying value of this choice. This is the value passed to the workflow when the choice is selected.
            - `label` string — Display label for the choice
          - `default_value` unknown
          - `dynamic_choices_key` string — Key path your UI will use to populate dynamic choices. Applicable for `string_dynamic` and `list_dynamic` value types.
          - `edit_policy` 'locked' | 'editable' — Whether the recipient can edit this property value. `Locked` means can't edit. Tenant can always edit irrespective of edit_policy.
  - `status` 'draft' | 'active' — Current status of the preference category
  - `version_no` integer — Version number field as an identifier to track the version
  - `commit_message` string — Commit message describing the changes that were made
  - `committed_at` string, date-time — Timestamp when the changes were committed
  - `validation_result` object — Result of validating the preference category
    - `is_valid` boolean — true if the preference category is valid, false if there are errors
    - `errors` string[] — Array of error messages when validation fails

## Other responses

- `401` — ServiceToken not found
- `404` — Workspace not found

---

[API](https://skmtc.dev/suprsend/apis/suprsend-api.md) · [All operations](https://skmtc.dev/suprsend/apis/suprsend-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/suprsend/suprsend-api/revisions/ea7b2f7c41a9/schema)
