> ## Documentation Index
> Fetch the complete documentation index at: https://docs.suprsend.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create or Update Preference Category

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

⚠️ This API call will **override existing categories** with whatever is passed in the request body. Recommended approach is to first fetch the current categories using [GET method](/reference/get-category), modify the response as needed, and then send it back in the request body. <br />
You can read more about preference categories [here](/docs/notification-category).

<Note>
  <p>
    <strong>Note:</strong>
    Changes will only be pushed if `"validation_result":{"is_valid":true}` in the response. General reasons for validation failure are:

    * There are multiple categories with the same slug
    * Some subcategories have been deleted in this version, on which active workflows are configured
    * You've not passed all three categories in the request body - system, transactional, promotional
  </p>
</Note>


## OpenAPI

````yaml POST /v1/{workspace}/preference_category/
openapi: 3.1.1
info:
  title: SuprSend API
  description: APIs supported on suprsend platform
  version: 1.2.2
servers:
  - url: https://hub.suprsend.com
security:
  - sec0: []
  - BearerAuth: []
paths:
  /v1/{workspace}/preference_category/:
    post:
      summary: Update Preference Categories
      description: >-
        Use this API to set preference categories to be used in workflow or to
        show on user preference page.
      operationId: create-update-category
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: commit
          schema:
            type: boolean
          description: >-
            Whether to commit changes immediately. Set to true to make changes
            live, false to save as draft.
        - in: query
          name: commit_message
          schema:
            type: string
          description: >-
            Optional commit message describing the changes made. Required when
            commit=true.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                root_categories:
                  type: array
                  description: >-
                    Array of root preference categories. Include all three root
                    categories (system, transactional, promotional) even if
                    empty.
                  items:
                    type: object
                    properties:
                      root_category:
                        type: string
                        description: >-
                          Root category classification. system=critical
                          notifications, transactional=user actions,
                          promotional=marketing.
                        enum:
                          - system
                          - transactional
                          - promotional
                      sections:
                        type: array
                        description: >-
                          Sections group related categories. Users cannot set
                          preferences at section level.
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                              description: >-
                                Name of the section displayed in the preference
                                interface.
                            description:
                              type: string
                              description: >-
                                Description of what notifications this section
                                covers.
                            tags:
                              type: array
                              description: >-
                                Tags to organize and filter sections. Use
                                lowercase, hyphenated values (e.g., "security",
                                "billing").
                              items:
                                type: string
                            categories:
                              type: array
                              description: Categories that users can set preferences for.
                              items:
                                type: object
                                properties:
                                  category:
                                    type: string
                                    description: >-
                                      Unique identifier for the category. Use
                                      lowercase letters, numbers, and hyphens
                                      only.
                                    pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
                                  name:
                                    type: string
                                    description: >-
                                      Display name for the category shown in the
                                      preference interface.
                                  description:
                                    type: string
                                    description: >-
                                      Description of what notifications this
                                      category covers.
                                  default_preference:
                                    type: string
                                    description: >-
                                      Default preference setting for this
                                      category.
                                    enum:
                                      - opt_in
                                      - opt_out
                                      - cant_unsubscribe
                                  default_mandatory_channels:
                                    type: array
                                    description: >-
                                      Channels that users cannot unsubscribe
                                      from when default preference is
                                      cant_unsubscribe.
                                    items:
                                      type: string
                                      enum:
                                        - email
                                        - sms
                                        - whatsapp
                                        - androidpush
                                        - inbox
                                        - iospush
                                        - slack
                                        - webpush
                                  default_opt_in_channels:
                                    type: array
                                    nullable: true
                                    description: >-
                                      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.
                                    items:
                                      type: string
                                      enum:
                                        - email
                                        - sms
                                        - whatsapp
                                        - androidpush
                                        - inbox
                                        - iospush
                                        - slack
                                        - webpush
                                        - ms_teams
                                  tags:
                                    type: array
                                    description: >-
                                      Tags to organize and filter categories.
                                      Use lowercase, hyphenated values (e.g.,
                                      "user-management", "payment-alerts").
                                    items:
                                      type: string
                                      pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
                                  digest_schedule:
                                    $ref: '#/components/schemas/DigestSchedule'
                                  properties:
                                    type: array
                                    nullable: true
                                    description: >-
                                      Condition properties for the category (up
                                      to 25). Set to null to disable conditions.
                                    maxItems: 25
                                    items:
                                      $ref: >-
                                        #/components/schemas/CategoryConditionProperty
      responses:
        '200':
          description: Successfully created/updated preference category
          content:
            application/json:
              schema:
                type: object
                properties:
                  $schema:
                    type: string
                    description: JSON schema reference for preference category structure
                    example: >-
                      https://schema.suprsend.com/preference_category/v1/schema.json
                  root_categories:
                    type: array
                    description: Array of root preference categories
                    items:
                      type: object
                      properties:
                        root_category:
                          type: string
                          description: >-
                            The root category classification for the preference
                            category
                          example: system
                        sections:
                          type: array
                          description: >-
                            Array of sections within the preference category.
                            Can be empty if not yet configured.
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                                description: Name of the section
                                example: Account Updates
                              description:
                                type: string
                                description: >-
                                  Description of what notifications this section
                                  covers
                                example: Important account-related notifications
                              tags:
                                type: array
                                description: >-
                                  Tags to organize and filter sections. Use
                                  lowercase, hyphenated values.
                                items:
                                  type: string
                              categories:
                                type: array
                                description: >-
                                  Array of categories within this section. Can
                                  be empty if not yet configured.
                                items:
                                  type: object
                                  properties:
                                    category:
                                      type: string
                                      description: Unique identifier for the category
                                      example: password-reset
                                    name:
                                      type: string
                                      description: Display name for the category
                                      example: Password Reset
                                    description:
                                      type: string
                                      description: >-
                                        Description of what notifications this
                                        category covers
                                    default_preference:
                                      type: string
                                      description: >-
                                        Default preference setting for this
                                        category
                                      enum:
                                        - opt_in
                                        - opt_out
                                        - cant_unsubscribe
                                      example: opt_in
                                    default_mandatory_channels:
                                      type: array
                                      description: >-
                                        Channels that are mandatory for this
                                        category
                                      items:
                                        type: string
                                        enum:
                                          - email
                                          - sms
                                          - whatsapp
                                          - androidpush
                                          - iospush
                                          - inbox
                                          - slack
                                          - webpush
                                      example:
                                        - email
                                    default_opt_in_channels:
                                      type: array
                                      nullable: true
                                      description: >-
                                        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.
                                      items:
                                        type: string
                                        enum:
                                          - email
                                          - sms
                                          - whatsapp
                                          - androidpush
                                          - iospush
                                          - inbox
                                          - slack
                                          - webpush
                                      example: null
                                    tags:
                                      type: array
                                      description: >-
                                        Tags to organize and filter categories.
                                        Use lowercase, hyphenated values (e.g.,
                                        "user-management", "payment-alerts").
                                      items:
                                        type: string
                                        pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
                                    digest_schedule:
                                      $ref: '#/components/schemas/DigestSchedule'
                                    properties:
                                      type: array
                                      nullable: true
                                      description: >-
                                        Condition properties for the category
                                        (up to 25). Set to null to disable
                                        conditions.
                                      maxItems: 25
                                      items:
                                        $ref: >-
                                          #/components/schemas/CategoryConditionProperty
                  status:
                    type: string
                    description: Current status of the preference category
                    enum:
                      - draft
                      - active
                    example: draft
                  version_no:
                    type: integer
                    description: Version number field as an identifier to track the version
                    example: 3
                  commit_message:
                    type: string
                    description: Commit message describing the changes that were made
                    example: null
                  committed_at:
                    type: string
                    format: date-time
                    description: Timestamp when the changes were committed
                    example: null
                  validation_result:
                    type: object
                    description: Result of validating the preference category
                    properties:
                      is_valid:
                        type: boolean
                        description: >-
                          true if the preference category is valid, false if
                          there are errors
                        example: true
                      errors:
                        type: array
                        description: Array of error messages when validation fails
                        items:
                          type: string
              example:
                $schema: https://schema.suprsend.com/preference_category/v1/schema.json
                root_categories:
                  - root_category: system
                    sections: []
                  - root_category: transactional
                    sections:
                      - name: Task Updates
                        description: null
                        tags: null
                        categories:
                          - category: tagged-to-me
                            name: Tagged to Me
                            description: >-
                              Status Update or mentions on tasks assigned by me
                              or tagged to me
                            default_preference: opt_in
                            default_mandatory_channels: null
                            default_opt_in_channels: null
                            tags: null
                            digest_schedule:
                              enabled: true
                              options:
                                - id: instant
                                  label: Instant
                                  frequency: instantly
                                  is_default: true
                                - id: daily-digest
                                  label: Daily at 9:00 AM
                                  frequency: daily
                                  interval: 1
                                  time:
                                    edit_policy: editable
                                    default_value: '09:00'
                                  is_default: false
                            properties:
                              - key: priority
                                label: Minimum priority
                                value_type: string_choice
                                is_optional: false
                                choices:
                                  - value: low
                                    label: Low
                                  - value: medium
                                    label: Medium
                                  - value: high
                                    label: High
                                default_value: high
                                edit_policy: editable
                  - root_category: promotional
                    sections:
                      - name: Product Updates
                        description: null
                        tags: null
                        categories:
                          - category: newsletter
                            name: Newsletter
                            description: null
                            default_preference: opt_out
                            default_mandatory_channels: null
                            default_opt_in_channels: null
                            tags: null
                            digest_schedule: null
                            properties: null
                version_no: 3
                status: draft
                commit_message: null
                committed_at: null
                validation_result:
                  is_valid: true
        '401':
          description: ServiceToken not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 401
                  message:
                    type: string
                    example: ServiceToken not found
              example:
                code: 401
                message: ServiceToken not found
        '404':
          description: Workspace not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: 'workspace not found for slug/uid: workspace'
              example:
                code: 404
                message: 'workspace not found for slug/uid: workspace'
      security:
        - ServiceTokenAuth: []
      servers:
        - url: https://management-api.suprsend.com
      x-codeSamples:
        - lang: cURL
          label: Create/Update Category
          source: >
            curl -X POST
            "https://management-api.suprsend.com/v1/{workspace}/preference_category/?commit=false"
            \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json" \
              --data '{
                "root_categories": [
                  {
                    "root_category": "system"
                  },
                  {
                    "root_category": "transactional",
                    "sections": [
                      {
                        "name": "Task Updates",
                        "categories": [
                          {
                            "category": "tagged-to-me",
                            "name": "Tagged to Me",
                            "description": "Status Update or mentions on tasks assigned by me or tagged to me",
                            "default_preference": "opt_in",
                            "digest_schedule": {
                              "enabled": true,
                              "options": [
                                {
                                  "id": "instant",
                                  "label": "Instant",
                                  "frequency": "instantly",
                                  "is_default": true
                                },
                                {
                                  "id": "daily-digest",
                                  "label": "Daily at 9:00 AM",
                                  "frequency": "daily",
                                  "interval": 1,
                                  "time": { "edit_policy": "editable", "default_value": "09:00" },
                                  "is_default": false
                                }
                              ]
                            },
                            "properties": [
                              {
                                "key": "threshold",
                                "label": "Threshold",
                                "value_type": "integer",
                                "is_optional": false,
                                "default_value": 10,
                                "edit_policy": "editable"
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  },
                  {
                    "root_category": "promotional",
                    "sections": [
                      {
                        "name": "Product Updates",
                        "categories": [
                          {
                            "category": "newsletter",
                            "name": "Newsletter",
                            "default_preference": "opt_out",
                            "digest_schedule": null,
                            "properties": null
                          }
                        ]
                      }
                    ]
                  }
                ]
              }'
components:
  schemas:
    DigestSchedule:
      type: object
      nullable: true
      description: >-
        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`.
      properties:
        enabled:
          type: boolean
          description: Whether you want to give digest options against this category.
        options:
          type: array
          description: >-
            Array of digest schedule options (up to 10). Exactly one option must
            have `is_default` set to true.
          maxItems: 10
          items:
            type: object
            properties:
              id:
                type: string
                description: >-
                  Unique identifier for the option. Max 64 characters, allowed
                  characters: [a-z0-9_-]. id is generated from label if not set.
                maxLength: 64
              label:
                type: string
                description: Display label to be shown to user for the option.
                maxLength: 256
              frequency:
                type: string
                description: >-
                  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.
                enum:
                  - instantly
                  - minutely
                  - hourly
                  - daily
                  - weekly
                  - weekly_mo2fr
                  - monthly
              interval:
                type: integer
                description: >-
                  Interval multiplier for the frequency (e.g., interval=2 with
                  frequency=weekly means every 2 weeks). Default value = 1.
                minimum: 1
              time:
                type: object
                description: >-
                  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.
                properties:
                  edit_policy:
                    type: string
                    enum:
                      - locked
                      - editable
                    description: >-
                      Whether the recipient can edit this value. `Locked` means
                      can't edit. Tenant can always edit irrespective of
                      edit_policy.
                  default_value:
                    type: string
                    description: Default time in HH:MM format (24-hour)
                    example: '00:00'
              weekdays:
                type: object
                description: >-
                  Weekday configuration. Applicable for `weekly` and
                  `weekly_mo2fr` frequencies. For `weekly_mo2fr`, edit_policy is
                  always `locked` with weekdays Monday through Friday.
                properties:
                  edit_policy:
                    type: string
                    enum:
                      - locked
                      - editable
                    description: >-
                      Whether the recipient can edit this value. `Locked` means
                      can't edit. Tenant can always edit irrespective of
                      edit_policy.
                  default_value:
                    type: array
                    description: Array of weekday codes
                    items:
                      type: string
                      enum:
                        - su
                        - mo
                        - tu
                        - we
                        - th
                        - fr
                        - sa
              monthdays:
                type: object
                description: Monthday configuration. Applicable for `monthly` frequency.
                properties:
                  edit_policy:
                    type: string
                    enum:
                      - locked
                      - editable
                    description: >-
                      Whether the recipient can edit this value. `Locked` means
                      can't edit. Tenant can always edit irrespective of
                      edit_policy.
                  default_value:
                    type: array
                    description: >-
                      Array of monthday objects specifying which days of the
                      month
                    items:
                      type: object
                      properties:
                        pos:
                          type: integer
                          description: Position of the day in the month (1-based)
                        day:
                          type: string
                          description: >-
                            Optional day of the week. If omitted, refers to the
                            calendar day at that position.
                          enum:
                            - su
                            - mo
                            - tu
                            - we
                            - th
                            - fr
                            - sa
              dtstart:
                type: object
                description: >-
                  Start date-time configuration. Only applicable for `daily`
                  frequency with interval > 1.
                properties:
                  edit_policy:
                    type: string
                    enum:
                      - locked
                      - editable
                    description: >-
                      Whether the recipient can edit this value. `Locked` means
                      can't edit. Tenant can always edit irrespective of
                      edit_policy.
                  default_value:
                    type: string
                    format: date-time
                    description: Start date-time in ISO 8601 format
                    example: '2026-06-20T00:00:00Z'
              is_default:
                type: boolean
                description: >-
                  Whether this option is the default selection. Exactly one
                  option in the array must be set to true.
    CategoryConditionProperty:
      type: object
      description: >-
        A condition property that can be configured per category to allow
        user-level customization.
      properties:
        key:
          type: string
          description: >-
            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`.
          maxLength: 64
        label:
          type: string
          description: >-
            Optional Display label for the property to be shown to user inside
            the preference centre.
          maxLength: 256
        value_type:
          type: string
          description: Data type of the property value
          enum:
            - integer
            - string
            - string_choice
            - list_choice
            - string_dynamic
            - list_dynamic
        is_optional:
          type: boolean
          description: >-
            Whether this property is optional. For optional property, default
            value is not required.
          default: false
        choices:
          type: array
          description: >-
            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.
          maxItems: 25
          items:
            type: object
            properties:
              value:
                type: string
                description: >-
                  The underlying value of this choice. This is the value passed
                  to the workflow when the choice is selected.
              label:
                type: string
                description: Display label for the choice
        default_value:
          description: >-
            Default value for the property. Data type depends on value_type —
            string for string/string_choice/string_dynamic, integer for integer,
            array of strings for list_choice/list_dynamic. Can be null.
          nullable: true
        dynamic_choices_key:
          type: string
          description: >-
            Key path your UI will use to populate dynamic choices. Applicable
            for `string_dynamic` and `list_dynamic` value types.
        edit_policy:
          type: string
          description: >-
            Whether the recipient can edit this property value. `Locked` means
            can't edit. Tenant can always edit irrespective of edit_policy.
          enum:
            - locked
            - editable
  securitySchemes:
    sec0:
      type: apiKey
      in: header
      name: Authorization
      x-bearer-format: bearer
      description: >-
        Bearer authentication header of the form `Bearer <token>`, where <token>
        is your auth token.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API_Key
      description: >-
        Pass as `Bearer <API_KEY>`. Get API Key from SuprSend dashboard
        Developers -> API Keys section.
    ServiceTokenAuth:
      type: apiKey
      in: header
      name: ServiceToken <token>
      description: >-
        You can get Service Token from [SuprSend dashboard -> Account Settings
        -> Service
        Tokens](https://app.suprsend.com/en/account-settings/service-tokens)
        section.

````