openapi: 3.1.1
info:
  title: SuprSend API
  description: APIs supported on suprsend platform
  version: 1.2.2
servers:
  - url: https://hub.suprsend.com
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API_Key  # Just for documentation, doesn't enforce behavior
      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.
    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.
  schemas:
    TemplateVariant:
      type: object
      properties:
        $schema:
          type: string
          description: Schema URL for variant validation.
          example: "https://schema.suprsend.com/template/v2/variant_schema.json"
        channel:
          type: string
          description: Channel this variant belongs to.
          example: "email"
        id:
          type: string
          description: Variant identifier.
          example: "default"
        tenant_id:
          type: string
          nullable: true
          description: Tenant this variant is scoped to, or null for default.
        locale:
          type: string
          description: Locale code.
          example: "en"
        conditions:
          type: array
          description: Conditions for variant selection at send time.
          items:
            type: object
        hash:
          type: string
          description: Content hash for change detection.
        needs_vendor_approval:
          type: boolean
          description: Whether this variant requires vendor approval (SMS DLT, WhatsApp).
        sysgen_template_name:
          type: string
          nullable: true
          description: System-generated template name for vendor approval.
        approval_status:
          type: string
          enum: ["auto_approved", "pending", "sent_for_approval", "approved", "rejected"]
          description: Current approval status of the variant.
        discard_comment:
          type: string
          nullable: true
          description: Reason provided when a variant is discarded.
        approval_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the variant was approved.
        has_error:
          type: boolean
          description: Whether the variant has validation errors.
        seq_no:
          type: integer
          description: Ordering within the channel + tenant + locale combination.
        action:
          type: string
          nullable: true
          description: Action taken in the latest commit (Updated, Added, Unchanged, or null).
        created_at:
          type: string
          format: date-time
          description: Timestamp when the variant was created.
        content:
          type: object
          description: Channel-specific content. Structure varies by channel. Only returned in variant detail endpoint.
        vendor_approvals:
          type: array
          description: Vendor approval entries (WhatsApp/SMS only). Only returned in variant detail endpoint.
          items:
            type: object
    Workflow:
      type: object
      properties:
        $schema:
          type: string
          format: uri
          description: Schema URL for workflow validation
          example: "https://schema.suprsend.com/workflow/v1/schema.json"
        slug:
          type: string
          description: Unique identifier for the workflow
          minLength: 1
          maxLength: 255
          pattern: "^[a-z0-9-_]+$"
          example: "welcome-sequence"
        is_enabled:
          type: boolean
          description: Whether the workflow is enabled
          example: true
        created_at:
          type: string
          format: date-time
          description: When the workflow was created
        last_executed_at:
          type: string
          format: date-time
          description: When the workflow was last executed
          nullable: true
        name:
          type: string
          description: Human-readable name of the workflow
          example: "Welcome Sequence"
        description:
          type: string
          nullable: true
          description: Description explaining the usecase of the workflow
        updated_at:
          type: string
          format: date-time
          description: When the workflow was last updated
        commit_message:
          type: string
          nullable: true
          description: Last commit message
        hash:
          type: string
          nullable: true
          description: Git-like hash for version tracking
        status:
          type: string
          enum: ["active", "inactive", "draft"]
          description: Current status of the workflow
        category:
          type: string
          description: Notification category of the workflow. Used to apply category-specific settings and preferences.
          example: "transactional"
        tags:
          type: array
          items:
            type: string
          description: Tags for organizing and filtering workflows in API.
        ratelimit:
          type: object
          nullable: true
          description: Workflow [throttle](https://docs.suprsend.com/docs/throttle) settings. This is used to limit the number of times a workflow can be executed per user in a given time period.
        conditions:
          type: array
          items:
            type: object
          description: Trigger Conditions for workflow execution. Workflow will only be executed if trigger conditions evaluate to true.
        trigger_type:
          type: string
          enum: ["event", "dynamic", "api"]
          description: How the workflow is triggered. You can refer to all trigger types [here](https://docs.suprsend.com/reference/trigger-workflows#trigger-types).
        trigger_events:
          type: array
          items:
            type: string
          description: Events that trigger this workflow. This will be set for trigger_type = `event`.
        override_recipients_type:
          type: string
          nullable: true
          description: Type of recipient override. Define whether to override and run this workflow for user, list of users or a single object.
          enum: ["user", "single_object_fields"]
        override_recipients_user_expr:
          type: string
          nullable: true
          description: Expression for overriding recipients when override_recipients_type = `user`.
        override_recipients_single_object_fields_expr:
          type: string
          nullable: true
          description: Expression for overriding recipients when override_recipients_type = `single_object_fields`.
        override_actor_user_expr:
          type: string
          nullable: true
          description: Expression for overriding actor
        override_tenant_expr:
          type: string
          nullable: true
          description: Expression for overriding tenant
        active_at:
          type: string
          format: date-time
          description: When the workflow's live version became active. Will be `null` for draft version.
        updated_by:
          type: object
          nullable: true
          properties:
            name:
              type: string
              description: Name of the user who last updated the workflow
            email:
              type: string
              format: email
              description: Email of the user who last updated the workflow
          description: User who last updated the workflow
        tree:
          type: object
          description: Node tree structure of the workflow. Shows the list of all nodes used in the workflow along with their configuration.
        validation_result:
          type: object
          properties:
            is_valid:
              type: boolean
              description: true if the workflow tree is valid to be published.
            errors:
              type: array
              items:
                type: string
              description: List of errors if the workflow tree is not valid.
          description: Validation status of the workflow
    WorkflowTriggerSingleBody:
      type: object
      description: A single workflow trigger payload. Send this object as-is for a single workflow trigger, or wrap multiple instances in a JSON array for a bulk trigger.
      required:
        - workflow
        - recipients
      properties:
        workflow:
          type: string
          description: You can get workflow slug from workflow settings on SuprSend dashboard.
          default: _workflow_slug_
        recipients:
          type: array
          description: List of recipients to be notified. You can either add recipient as array of distinct_ids or array of recipient objects. You can add up to 100 recipients in a single API.
          items:
            oneOf:
              - type: object
                title: "Identify user inline"
                description: "You can pass user properties and channels inline in workflow trigger request. Properties and channels passed here also update in user profile on workflow trigger."
                required: [distinct_id]
                properties:
                  is_transient:
                    type: boolean
                    description: set `is_transient = true` to send notification to anonymous user. You don't need to pass `distinct_id` for anonymous sending.
                  distinct_id:
                    type: string
                    description: unique identifier of the user who needs to be notified
                    default: id1
                  $channels:
                    type: array
                    items:
                      type: string
                      example: "email"
                      description: channel to send notification to
                      enum:
                        - email
                        - sms
                        - inbox
                        - androidpush
                        - iospush
                        - slack
                        - ms_teams
                        - webpush
                        - whatsapp
                  $email:
                    type: array
                    items:
                      type: string
                      format: email
                      example: "john@example.com"
                  $sms:
                      type: array
                      items:
                        type: string
                        example: "+1234567890"
                  $inbox:
                    type: array
                    items:
                      type: string
                      example: "4nlPk4t4kurG5kChxxxx"
                  $androidpush:
                    type: array
                    items:
                      type: string
                      example: "__android_push_token__"
                  $iospush:
                    type: array
                    items:
                      type: string
                      example: "__ios_push_token__"
                  $slack:
                    type: array
                    description: Slack channel configuration
                    items:
                      oneOf:
                        - type: object
                          title: "Slack using email"
                          required: [email, access_token]
                          properties:
                            email:
                              type: string
                              format: email
                              description: User email address
                              example: "user@example.com"
                            access_token:
                              type: string
                              description: Slack bot access token
                              example: "xoxb-XXXXXXXX"
                        - type: object
                          title: "Slack using member ID"
                          required: [user_id, access_token]
                          properties:
                            user_id:
                              type: string
                              description: Slack user ID (U/WXXXXXXXX format)
                              example: "U/WXXXXXXXX"
                            access_token:
                              type: string
                              description: Slack bot access token
                              example: "xoxb-XXXXXX"
                        - type: object
                          title: "Slack using channel"
                          required: [channel, access_token]
                          properties:
                            channel:
                              type: string
                              description: Slack channel ID (CXXXXXXXX format)
                              example: "CXXXXXXXX"
                            access_token:
                              type: string
                              description: Slack bot access token
                              example: "xoxb-XXXXXX"
                        - type: object
                          title: "Slack using incoming webhook"
                          required: [incoming_webhook]
                          properties:
                            incoming_webhook:
                              type: object
                              required: [url]
                              properties:
                                url:
                                  type: string
                                  format: uri
                                  description: Slack incoming webhook URL
                                  example: "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"
                  $ms_teams:
                    type: array
                    description: Microsoft Teams channel configuration
                    items:
                      oneOf:
                        - type: object
                          title: "MS Teams using conversation ID"
                          required: [tenant_id, service_url, conversation_id]
                          properties:
                            tenant_id:
                              type: string
                              description: Microsoft Teams tenant ID
                              example: "c1981ab2-9aaf-xxxx-xxxx"
                            service_url:
                              type: string
                              format: uri
                              description: Microsoft Teams service URL
                              example: "https://smba.trafficmanager.net/amer"
                            conversation_id:
                              type: string
                              description: Microsoft Teams conversation ID
                              example: "19:c1524d7c-a06f-456f-8abe-xxxx"
                        - type: object
                          title: "MS Teams using user ID"
                          required: [tenant_id, service_url, user_id]
                          properties:
                            tenant_id:
                              type: string
                              description: Microsoft Teams tenant ID
                              example: "c1981ab2-9aaf-xxxx-xxxx"
                            service_url:
                              type: string
                              format: uri
                              description: Microsoft Teams service URL
                              example: "https://smba.trafficmanager.net/amer"
                            user_id:
                              type: string
                              description: Microsoft Teams user ID
                              example: "29:1nsLcmJ2RKtYH6Cxxxx-xxxx"
                        - type: object
                          title: "MS Teams using incoming webhook"
                          required: [incoming_webhook]
                          properties:
                            incoming_webhook:
                              type: object
                              required: [url]
                              properties:
                                url:
                                  type: string
                                  format: uri
                                  description: Microsoft Teams incoming webhook URL
                                  example: "https://wnk1z.webhook.office.com/webhookb2/XXXXXXXXX"
                  $timezone:
                    type: string
                    example: "America/New_York"
                  $locale:
                    type: string
                    example: "en_GB"
                  $context:
                    type: object
                    description: "Scoping context for the inline profile fields on this recipient. Use `$context.tenant_id` when you want the properties and channels passed in this recipient object to be written against a specific tenant's per-tenant profile instead of the user's global profile. See [User-Tenant Mapping](/docs/user-tenant-mapping)."
                    properties:
                      tenant_id:
                        type: string
                        description: "Tenant to scope inline profile updates to. When set, must equal the top-level `tenant_id` on the trigger — mismatched values reject the request and the workflow does not run."
                        example: "acme-corp"
              - type: object
                title: "Notify object"
                required: [id,object_type]
                properties:
                  id:
                    type: string
                    description: Unique identifier of the object
                    example: frontend
                  object_type:
                    type: string
                    description: Filename to be shown in email
                additionalProperties:
                  type: string
                  description: You can pass other user properties similar to recipient payload. It will be used when notification is sent to object channels as $recipient.<property>.
        actor:
          type: object
          description: Includes distinct_id and properties of the user who performed the action. You can use it for [cross-user notifications]("https://docs.suprsend.com/docs/trigger-workflow#sending-cross-user-notifications"). Actor properties can be added as `$actor.<prop>`.
          properties:
            is_transient:
              type: boolean
              description: set `is_transient = true` to pass anonymous actor. You don't need to pass `distinct_id` for anonymous user.
            distinct_id:
              type: string
              description: unique identifier of the actor who performed the action
              default: id1
            $context:
              type: object
              description: "Scoping context for the inline profile fields on the actor. Use `$context.tenant_id` to write actor properties and channels against a specific tenant's per-tenant profile. See [User-Tenant Mapping](/docs/user-tenant-mapping)."
              properties:
                tenant_id:
                  type: string
                  description: "Tenant to scope inline actor updates to. When set, must equal the top-level `tenant_id` on the trigger — mismatched values reject the request and the workflow does not run."
                  example: "acme-corp"
          additionalProperties:
            type: string
            description: You can pass additional actor properties as `"user_prop1":"value1"` . Extra properties will be update in user profile which can then be used in the template as `$actor.<property>`.

        data:
          type: object
          description: variable data required to render dynamic template content or workflow properties like dynamic delay or channel override in send node.
          properties:
            $attachments:
              type: array
              description: Use this key to pass email attachment in the trigger. You can either pass attachment as a public URL or as a base64-encoded file (limit < 50KB).
              items:
                oneOf:
                  - type: object
                    title: "Pass Public URL"
                    description: Pass file as **publicly accessible URL** (No limit on file size)
                    required: [url]
                    properties:
                      url:
                        type: string
                        format: uri
                        description: Publicly accessible URL of the file
                        example: "https://bitcoincore.org/bitcoin.pdf"
                      filename:
                        type: string
                        description: Filename to be shown in email
                        example: "billing.pdf"
                      ignore_if_error:
                        type: boolean
                        description: Ignore the attachment if it fails to load

                  - type: object
                    title: "Pass Base64 File Locally"
                    description: Pass file as a **base-64 file** (supported limit < 50KB)
                    required: [data]
                    properties:
                      data:
                        type: string
                        description: Base64-encoded content of the file
                      filename:
                        type: string
                        description: Filename to be shown in email
                      contentType:
                        type: string
                        example: application/pdf
          additionalProperties:
            type: string
        tenant_id:
          type: string
          description: "Tenant context for this trigger. Applies the tenant's branding, admin preferences, and vendor routing, and — for users with a [per-tenant profile](/docs/user-tenant-mapping) — resolves recipients against the merged (global + per-tenant) profile."
        $idempotency_key:
          type: string
          description: Idempotency_key (valid for 24hrs)
    DigestNode:
      title: Digest
      type: object
      description: "[**Digest**](https://docs.suprsend.com/docs/digest): Batches and sends summary notifications at a recurring digest schedule."
      required:
        - node_type
        - name
        - schedule_type
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Daily digest"
        node_type:
          type: string
          const: digest
        description:
          type: string
          nullable: true
          description: Description of what this node does
        schedule_type:
          type: string
          enum: ["static", "dynamic", "category_digest_schedule"]
          description: "Type of schedule. Determines how the digest schedule is resolved. \n\n**static**: Schedule is fixed and will be used for all recipients. \n\n**dynamic**: Schedule is dynamic and will be computed at runtime using the `dynamic_schedule_expr`. \n\n**category_digest_schedule**: Uses the digest schedule configured on the notification category linked to this workflow. The recipient's selected digest option (or the category default) determines the schedule."
        dynamic_schedule_expr:
          type: string
          description: "jq-expression for deriving dynamic digest schedule at runtime. Eg. `.digest_schedule`"
          example: ".digest_schedule"
        schedule:
          $ref: '#/components/schemas/Schedule'
        retain_count:
          type: integer
          minimum: 1
          maximum: 100
          description: "Maximum number of items to retain after digest closes (1-100). By default, 10 items are retained."
        retain_order:
          type: string
          enum: ["first", "last"]
          description: "Retain items in this order when retain_count is specified."
        trigger_min_count:
          type: integer
          minimum: 1
          description: "Digest will be sent if number of triggers in the batch are greater than or equal to this count, else skipped."
    Schedule:
      type: object
      description: "Static schedule configuration for digest notifications."
      properties:
        frequency:
          type: string
          enum: ["minutely", "hourly", "daily", "weekly_mo2fr", "weekly", "monthly"]
          description: "Frequency of the digest schedule."
        interval:
          type: integer
          minimum: 1
          description: "Multiplier for recurrence schedule. Eg. 2 for every 2 hours, 3 for every 3 days, etc."
        weekdays:
          type: array
          items:
            type: string
            enum: ["su", "mo", "tu", "we", "th", "fr", "sa"]
          description: "Which days to include when frequency is 'weekly'."
        monthdays:
          type: array
          items:
            type: object
            properties:
              pos:
                type: integer
                minimum: -31
                maximum: 31
              day:
                type: string
                enum: [null, "su", "mo", "tu", "we", "th", "fr", "sa"]
          description: "Which days to include when frequency is 'monthly'."
        time:
          type: string
          description: "Time of day to send digest in HH:MM format (24-hour)."
          examples: ["09:00", "18:30"]
        dtstart:
          type: string
          description: "When to start schedule calculation from in ISO datetime format."
        tz_selection:
          type: string
          enum: ["fixed", "recipient"]
          description: "timezone of the recurring schedule. \n\n**fixed**: Fixed timezone. \n\n**recipient**: Recipient's timezone picked from user properties."
        tz_fixed:
          type: string
          description: "Fixed IANA timezone."
          pattern: "^[A-Za-z_/]+$"
          examples:
            new_york:
              summary: "New York timezone"
              value: "America/New_York"
            london:
              summary: "London timezone"
              value: "Europe/London"

    DelayNode:
      title: Delay
      type: object
      description: "[**Delay**](https://docs.suprsend.com/docs/delay): Pauses workflow execution for a specified duration."
      required:
        - node_type
        - name
        - delay_type
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Wait 30 minutes"
        description:
          type: string
          nullable: true
          description: Description of what this node does
        node_type:
          type: string
          const: delay
        delay_type:
          type: string
          enum: ["fixed", "dynamic", "relative_to"]
          description: "Type of delay. Determines how the duration is calculated. \n\n**Fixed**: Static duration added as XXdXXhXXmXXs.\n\n **Dynamic**: duration is passed as variable in your trigger payload in jq format. Eg. `.delay_duration`, `$recipient.delay_duration`, `$actor.delay_duration`, `$tenant.delay_duration`.\n\n **Relative to**: delay is relative to a future timestamp passed in your trigger payload. Eg. `.start_time` before 15m."
        duration:
          type: string
          description: "Duration value. Required for 'fixed' and 'dynamic' delay types."
          examples:
            fixed_duration:
              summary: "Fixed duration example"
              value: "30s"
            dynamic_duration:
              summary: "Dynamic duration from trigger payload"
              value: ".delay_duration"
            recipient_duration:
              summary: "Dynamic duration from recipient properties"
              value: "$recipient.delay_duration"
        relative_to:
          type: object
          description: "Relative delay configuration. Required when delay_type is 'relative_to'."
          properties:
            pivot_expr:
              type: string
              description: "(jq-expression) variable defining the future timestamp from trigger payload relative to which delay is calculated."
              example: ".start_time"
            offset_type:
              type: string
              enum: ["before", "after"]
              description: "Whether offset is to be added or subtracted from pivot_expr."
            offset_value_type:
              type: string
              enum: ["fixed", "dynamic"]
              description: "Defines if the offset value is fixed or dynamic. \n\n**Fixed**: Static duration added as XXdXXhXXmXXs. Eg. 15m before meeting_start_time. \n\n**Dynamic**: offset is passed as variable in your trigger payload or recipient, tenant properties in jq format. Eg. `$recipient.reminder_offset` before meeting_start_time."
            offset_value:
              type: string
              description: "Offset value"
              examples:
                fixed_offset:
                  summary: "Fixed duration offset"
                  value: "15m"
                dynamic_offset:
                  summary: "Dynamic offset from recipient properties"
                  value: "$recipient.reminder_offset"

    BatchNode:
      title: Batch
      type: object
      description: "[**Batch**](https://docs.suprsend.com/docs/batch): Batches incoming workflow triggers/events for a duration to send consolidated notifications."
      required:
        - node_type
        - name
        - mode
        - window_type
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Batch notifications"
        description:
          type: string
          nullable: true
          description: Description of what this node does
        node_type:
          type: string
          const: batch
        mode:
          type: string
          enum: ["accumulate_all", "flush_leading_item"]
          description: "**accumulate_all**: All events are accumulated in the batch and notification is sent once after batch window closes. \n\n**flush_leading_item**: Notification is sent immediately for the first event in the batch and rest of the events are batched and sent after batch window closes. Eg. Send anomaly alert with first notification sent at the occurrence of first error and next alert sent after 30 minutes if there are further errors."
        window_type:
          type: string
          enum: ["fixed", "dynamic", "relative_to"]
          description: "Type of batching window. \n\n**fixed**: Static window duration added as XXdXXhXXmXXs. Eg. 30s, 1h, 1d. \n\n**dynamic**: Batch window duration is passed as variable in your trigger payload. Add the variable in jq format. Eg. `.window_duration`, `$recipient.batch_duration`, `$actor.window_duration`, `$tenant.window_duration`. \n\n**relative_to**: Batch window is relative to a future timestamp passed in your trigger payload. Eg. 15 m before `.task_end_time`."
        fixed_window:
          type: string
          description: "Batch window when window_type is 'fixed'. Static batch window for all users. Format: XXdXXhXXmXXs."
          example: "30s"
        dynamic_window_expr:
          type: string
          description: "Batch window when window_type is 'dynamic'. jq-expression for deriving batch window duration at runtime."
          examples:
            trigger_payload:
              summary: "From trigger payload"
              value: ".window_duration"
            recipient_property:
              summary: "From recipient properties"
              value: "$recipient.batch_duration"
            actor_property:
              summary: "From actor properties"
              value: "$actor.window_duration"
            tenant_property:
              summary: "From tenant properties"
              value: "$tenant.window_duration"
        relative_to:
          type: object
          description: "Batch window when window_type is 'relative_to'. Batch window is calculated relative to a future timestamp."
          properties:
            pivot_expr:
              type: string
              description: "(jq-expression) variable defining the future timestamp from trigger payload relative to which batch window is calculated."
              examples:
                trigger_payload:
                  summary: "From trigger payload"
                  value: ".start_time"
                recipient_property:
                  summary: "From recipient properties"
                  value: "$recipient.task_end_time"
            offset_type:
              type: string
              enum: ["before", "after"]
              description: "Whether offset is to be added or subtracted from pivot timestamp."
            offset_value_type:
              type: string
              enum: ["fixed", "dynamic"]
              description: "Defines if the offset value is fixed or dynamic. \n\n**Fixed**: Static duration added as XXdXXhXXmXXs. Eg. 15m before meeting_start_time. \n\n**Dynamic**: offset is passed as variable in your trigger payload or recipient, tenant properties in jq format. Eg. `$recipient.reminder_offset` before meeting_start_time."
            offset_value:
              type: string
              description: "Offset value."
              examples:
                fixed_offset:
                  summary: "Fixed duration offset"
                  value: "15m"
                dynamic_offset:
                  summary: "Dynamic offset from recipient properties"
                  value: "$recipient.reminder_offset"
        retain_count:
          type: integer
          minimum: 1
          maximum: 100
          description: "Maximum number of items to retain after batch closes (1-100). The output variable set will have the latest or first n items based on the retain_order."
        retain_order:
          type: string
          enum: ["first", "last"] 
          description: "Retain items in this order when retain_count is specified."
        batch_key:
          type: string
          description: "jq-expression used to group events into separate batches. For example, when sending batched notifications for comments on different documents, use `.document_id` as the batch key to ensure comments from different documents are not combined into the same batch."
          example: ".document_id"

    HttpApiWebhookNode:
      title: Webhook
      type: object
      description: "[**Webhook**](https://docs.suprsend.com/docs/webhook): Makes an HTTP API request to an endpoint."
      required:
        - node_type
        - name
        - http_method
        - url
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Notify internal CRM"
        node_type:
          type: string
          const: httpapi_webhook
        description:
          type: string
          nullable: true
          description: Description of what this node does
        http_method:
          type: string
          enum: ["GET", "PUT", "POST", "PATCH", "DELETE"]
          description: "HTTP method of the API call."
        url:
          type: string
          format: uri
          description: "Endpoint URL of the API call. You can add variables in JSONNET format. Eg. `\"https://api.example.com/webhook?id=\"+data[\"$recipient\"].id`"
          example: "https://api.example.com/webhook"
        headers:
          type: array
          description: "List of headers as key-value pairs. You can add variables in JSONNET format. Eg. `\"Bearer\"+data[\"$tenant\"].api_key`"
          items:
            type: object
            properties:
              key:
                type: string
                description: "header key"
                example: ["\"Authorization\"", "\"Content-Type\""]
              value:
                type: string
                description: "header value"
                example: ["\"Bearer \"+data[\"$tenant\"].api_key", "\"application/json\""]
        body_content_type:
          type: string
          default: "application/json"
          description: "Content type for the body."
        body:
          type: string
          description: "JSONNET script to evaluate request body."
        query_params:
          type: array
          description: "List of query parameters as key-value pairs. You can add variables in JSONNET format. Eg. `data[\"$recipient\"].id`"
          items:
            type: object
            properties:
              key:
                type: string
                description: "Query Parameter Key"
              value:
                type: string
                description: "Query Parameter Value"
        output_key:
          type: string
          description: "Optional key to store the response body of API call. If not provided, the response will be appended at the root of the workflow payload. It's recommended to provide a unique key here to avoid overwriting existing data."

    HttpApiFetchNode:
      title: Fetch
      type: object
      description: "[**Fetch**](https://docs.suprsend.com/docs/fetch): Fetches data from an API endpoint using GET method only."
      required:
        - node_type
        - name
        - http_method
        - url
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Fetch user data"
        node_type:
          type: string
          const: httpapi_fetch
        description:
          type: string
          nullable: true
          description: Description of what this node does
        http_method:
          type: string
          const: "GET"
          description: "HTTP method to use. Only GET is supported for fetch operations."
        url:
          type: string
          description: "Endpoint URL to fetch data from."
          example: "https://api.example.com/data"
        headers:
          type: array
          description: "List of headers as key-value pairs. You can add variables in JSONNET format. Eg. `\"Bearer\"+data[\"$tenant\"].api_key`"
          items:
            type: object
            properties:
              key:
                type: string
                description: "header key"
                examples:
                  authorization:
                    summary: "Authorization header"
                    value: "\"Authorization\""
                  content_type:
                    summary: "Content-Type header"
                    value: "Content-Type"
              value:
                type: string
                description: "header value"
                example: ["\"Bearer \"+data[\"$tenant\"].api_key", "\"application/json\""]
        query_params:
          type: array
          description: "List of query parameters as key-value pairs. You can add variables in JSONNET format. Eg. `data[\"$recipient\"].id`"
          items:
            type: object
            properties:
              key:
                type: string
                description: "Query Parameter Key"
                examples:
                  id_param:
                    summary: "ID parameter"
                    value: "id"
                  name_param:
                    summary: "Name parameter"
                    value: "name"
              value:
                type: string
                description: "Query Parameter Value"
                examples:
                  data_id:
                    summary: "Data ID from payload"
                    value: "data.id"
                  recipient_name:
                    summary: "Recipient name from data"
                    value: "data[\"$recipient\"].name"
        output_key:
          type: string
          description: "Optional key to store the response of API call. If not provided, the response will be appended at the root of the workflow payload. It's recommended to provide a unique key here to avoid overwriting existing data."

    BranchWaitUntilNode:
      title: Wait Until
      type: object
      description: "[**Wait Until**](https://docs.suprsend.com/docs/wait-until): Waits until a condition is met or the maximum time is reached. Uses branch structure with conditions."
      required:
        - node_type
        - name
        - branches
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Wait for approval"
        node_type:
          type: string
          const: branch_waituntil
        description:
          type: string
          nullable: true
          description: Description of what this node does
        branches:
          type: array
          description: "Array of branches with conditions to evaluate. Minimum 2 branches required."
          minItems: 2
          maxItems: 2
          items:
            type: object
            properties:
              name:
                type: string
                description: "Name of the branch for identification."
              description:
                type: string
                description: "Description of what this branch does."
              is_default:
                type: boolean
                description: "Whether this is the default branch. In case of wait until, branch with condition->type as 'delay' (max time) should always be the default branch."
              conditions:
                type: array
                description: "Array of conditions to evaluate for this branch."
                items:
                  type: object
                  properties:
                    type:
                      type: string
                      enum: ["future_event", "delay"]
                      description: "Type of condition to evaluate."
                    event_name:
                      type: string
                      description: "Name of the future event to wait for. Eg. `\"request_approved\"`"
                      maxLength: 255
                    event_conditions:
                      type: array
                      description: "Additional conditions to evaluate when the future event occurs."
                      items:
                        type: object
                        properties:
                          variable_ns:
                            type: string
                            description: "Namespace for the variable on left-hand side of expression."
                            allowed_values:
                              - "": "Default namespace (payload data)"
                              - "$tenant": "tenant/brand properties"
                              - "$actor": "user properties of the actor"
                              - "$recipient": "user properties of the recipient"
                              - "$future_event": "Future event properties"
                            required: false
                          variable:
                            type: string
                            description: "Variable name on left-hand side of expression."
                            required: true
                            example: "status"
                          op:
                            type: string
                            description: "Comparison operator for the expression."
                            allowed_values:
                              - "==": "Equal to"
                              - "!=": "Not equal to"
                              - ">": "Greater than"
                              - "<": "Less than"
                              - ">=": "Greater than or equal to"
                              - "<=": "Less than or equal to"
                              - "EMPTY": "Empty"
                              - "NON_EMPTY": "Not empty"
                              - "CONTAINS": "Contains"
                              - "NOT_CONTAINS": "Does not contain"
                              - "DATETIME_EQUALS": "Date time equals"
                              - "DATETIME_LT": "Date time less than"
                              - "DATETIME_GT": "Date time greater than"
                          value:
                            type: string
                            description: "Right-hand side operand."
                            example: "approved"
                    delay_properties:
                      type: object
                      description: "Timeout value after which the branch will be executed. Required when condition->type is 'delay'."
                      properties:
                        delay_type:
                          type: string
                          enum: ["fixed", "dynamic", "relative_to"]
                          description: "Type of delay calculation. \n\n**fixed**: Static duration added as XXdXXhXXmXXs. \n\n**dynamic**: duration is passed as variable in your trigger payload in jq format. Eg. `.delay_duration`, `$recipient.delay_duration`, `$actor.delay_duration`, `$tenant.delay_duration`. \n\n**relative_to**: delay is relative to a future timestamp passed in your trigger payload. Eg. `.start_time` before 15m."
                        value:
                          type: string
                          description: "Delay value. Required for 'fixed' and 'dynamic' delay types."
                          examples:
                            fixed_duration:
                              summary: "Fixed duration example"
                              value: "30s"
                            dynamic_duration:
                              summary: "Dynamic duration from trigger payload"
                              value: ".delay_duration"
                            recipient_duration:
                              summary: "Dynamic duration from recipient properties"
                              value: "$recipient.delay_duration"
                        relative_to:
                          type: object
                          description: "Relative delay configuration. Required when delay_type is 'relative_to'."
                          example: {
                            "pivot_expr": ".start_time",
                            "offset_type": "before",
                            "offset_value_type": "fixed",
                            "offset_value": "15m"
                          }
                          properties:
                            pivot_expr:
                              type: string
                              description: "(jq-expression) variable defining the future timestamp from trigger payload relative to which delay is calculated."
                            offset_type:
                              type: string
                              enum: ["before", "after"]
                              description: "Whether to add or subtract offset from pivot."
                            offset_value_type:
                              type: string
                              enum: ["fixed", "dynamic"]
                              description: "How to determine offset value. \n\n**fixed**: Static duration added as XXdXXhXXmXXs. Eg. 15m before meeting_start_time. \n\n**dynamic**: offset is passed as variable in your trigger payload or recipient, tenant properties in jq format. Eg. `$recipient.reminder_offset` before meeting_start_time."
                            offset_value:
                              type: string
                              description: "Offset value. Required for 'fixed' and 'dynamic' offset_value_types."
                              examples:
                                fixed_offset:
                                  summary: "Fixed duration offset"
                                  value: "15m"
                                dynamic_offset:
                                  summary: "Dynamic offset from recipient properties"
                                  value: "$recipient.reminder_offset"
              nodes:
                type: array
                description: "Array of nodes to execute when this branch condition is met. Minimum 1 node required."

    BranchNode:
      title: Branch
      type: object
      description: "[**Branch**](https://docs.suprsend.com/docs/branch): Divides the workflow in different branches and executes the first branch that matches the branch condition."
      required:
        - node_type
        - name
        - branches
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Check user type"
        node_type:
          type: string
          const: branch
        description:
          type: string
          nullable: true
          description: Description of what this node does
        branches:
          type: array
          description: "Array of branches with conditions to evaluate. Minimum 2 branches required."
          minItems: 2
          maxItems: 10
          items:
            type: object
            properties:
              name:
                type: string
                description: "Name of the branch for identification."
              description:
                type: string
                description: "Description of what this branch does."
              is_default:
                type: boolean
                description: "Whether this is the default branch. Default branch is executed if no other branch conditions are met."
              conditions:
                type: array
                description: "Array of conditions to evaluate for this branch."
                items:
                  type: object
                  properties:
                    type:
                      type: string
                      const: "expression_v1"
                      description: "Type of condition to evaluate. Only expression_v1 is supported for regular branch nodes."
                    expression_v1:
                      type: object
                      description: "Boolean expression evaluation structure."
                      properties:
                        op:
                          type: string
                          enum: ["AND", "OR"]
                          description: "Logical operator for combining conditions."
                        args:
                          type: array
                          description: "Array of individual condition expressions or nested logical expressions."
                          items:
                            type: object
                            properties:
                              variable_ns:
                                type: string
                                description: "Namespace for the variable on left-hand side of expression. Allowed values: \"\" (Default namespace - payload data), \"$tenant\" (tenant/brand properties), \"$actor\" (user properties of the actor), \"$recipient\" (user properties of the recipient), \"$future_event\" (Future event properties), \"$workflow\" (Workflow properties)."
                                required: false
                                enum: ["", "$tenant", "$actor", "$recipient", "$future_event", "$workflow"]
                              variable:
                                type: string
                                description: "Variable name on left-hand side of expression."
                              op:
                                type: string
                                enum: ["==", "!=", ">", ">=", "<", "<=", "EMPTY", "NON_EMPTY", "CONTAINS", "NOT_CONTAINS", "DATETIME_EQUALS", "DATETIME_LT", "DATETIME_GT"]
                                description: "Comparison operator for the expression."
                              value:
                                type: string
                                description: "Right-hand side operand."
                              args:
                                type: array
                                description: "Array of conditions for nested logical expressions."
              nodes:
                type: array
                description: "Array of nodes to execute when this branch condition is met."

    TransformNode:
      title: Data Transform
      type: object
      description: "[**Data Transform**](https://docs.suprsend.com/docs/data-transform): Transforms data or generates/overrides variables using scripting languages like JSONNET or Handlebars."
      required:
        - node_type
        - name
        - variables
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Transform data"
        node_type:
          type: string
          const: transform
        description:
          type: string
          nullable: true
          description: Description of what this node does
        variables:
          type: array
          description: "Array of variables to generate or override. Each variable must have a unique key."
          minItems: 1
          items:
            type: object
            properties:
              key:
                type: string
                description: "Literal string key for the variable."
                minLength: 1
              value_lang:
                type: string
                enum: ["jsonnet", "handlebars"]
                description: "Scripting language to use for deriving the variable value at runtime."
              value:
                type: string
                description: "Script in the selected language to derive the value of the variable at runtime."
                minLength: 1

    TimeWindowNode:
      title: Time Window
      type: object
      description: "[**Time Window**](https://docs.suprsend.com/docs/time-window): Restricts workflow execution to specific time windows based on recurrence rules."
      required:
        - node_type
        - name
        - windows
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Business hours only"
        node_type:
          type: string
          const: timewindow
        description:
          type: string
          nullable: true
          description: Description of what this node does
        windows:
          type: array
          description: "Array of time windows defined using recurrence rule structure."
          minItems: 1
          items:
            type: object
            properties:
              frequency:
                type: string
                enum: ["daily", "weekly_mo2fr", "weekly", "monthly"]
                description: "Frequency of the time window recurrence."
              weekdays:
                type: array
                description: "Which days to include when frequency is 'weekly'."
                items:
                  type: string
                  enum: ["su", "mo", "tu", "we", "th", "fr", "sa"]
              monthdays:
                type: array
                description: "Which days to include when frequency is 'monthly'."
                items:
                  type: object
                  properties:
                    pos:
                      type: integer
                      minimum: -31
                      maximum: 31
                      description: "Day number (-31 to 31)."
                    day:
                      type: string
                      enum: [null, "su", "mo", "tu", "we", "th", "fr", "sa"]
                      description: "Weekday when specifying nth weekday of month. Negative values indicate the nth last occurrence of the weekday in the month."
              stime:
                type: string
                description: "Clock start time of the window in HH:MM format (24-hour)."
                example: "08:00"
              etime:
                type: string
                description: "Clock end time of the window in HH:MM format (24-hour)."
                example: "17:00"
        tz_selection:
          type: string
          enum: ["fixed", "recipient"]
          description: "Where to pick timezone from for calculating datetime from recurrence rule. \n\n**fixed**: Use a fixed timezone. \n\n**recipient**: Use the timezone set in recipient properties."
        tz_fixed:
          type: string
          description: "Fixed IANA timezone for calculating datetime in recurrence rule."
          example: "America/New_York"

    SubscriberListOperationAddUserNode:
      title: Add User to List
      type: object
      description: "[**Add User to List**](https://docs.suprsend.com/docs/add-user-to-list): Adds users (actor or recipient) to a subscriber list. Can create the list if it doesn't exist."
      required:
        - node_type
        - name
        - list_id
        - user_selection
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Add to newsletter list"
        node_type:
          type: string
          const: subscriberlistoperation_adduser
        description:
          type: string
          nullable: true
          description: Description of what this node does
        is_list_id_dynamic:
          type: boolean
          default: false
          description: "Whether list_id is a static literal string or a handlebars expression."
        list_id:
          type: string
          description: "List identifier. Can be a static literal string or a handlebars expression added as {{list_id}}."
          minLength: 1
        create_list_if_missing:
          type: boolean
          default: false
          description: "Whether to create the list if it doesn't exist."
        list_name:
          type: string
          description: "Name for the list when creating it. Pass when `create_list_if_missing` is true."
          minLength: 1
        user_selection:
          type: array
          description: "Which users to add to the list. Can select actor, recipient, or both."
          minItems: 1
          items:
            type: string
            enum: ["actor", "recipient"]

    SubscriberListOperationRemoveUserNode:
      title: Remove User from List
      type: object
      description: "[**Remove User from List**](https://docs.suprsend.com/docs/remove-user-from-list): Removes users (actor or recipient) from the list. List must exist for the operation to succeed."
      required:
        - node_type
        - name
        - list_id
        - user_selection
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Remove from newsletter list"
        node_type:
          type: string
          const: subscriberlistoperation_removeuser
        description:
          type: string
          nullable: true
          description: Description of what this node does
        is_list_id_dynamic:
          type: boolean
          default: false
          description: "Whether list_id is a static literal string or a handlebars expression."
        list_id:
          type: string
          description: "List identifier. Can be a static literal string or a handlebars expression (to compute the list id at runtime. Eg. {{list_id}})."
          minLength: 1
        user_selection:
          type: array
          description: "Which users to remove from the list. Can select actor, recipient, or both."
          minItems: 1
          items:
            type: string
            enum: ["actor", "recipient"]

    ObjectOperationAddSubscriptionNode:
      title: Subscribe to Object
      type: object
      description: "[**Subscribe to Object**](https://docs.suprsend.com/docs/subscribe-to-object): Adds users (actor or recipient) as subscribers to an object. Can create the object if it doesn't exist."
      required:
        - node_type
        - name
        - object_type
        - object_id
        - user_selection
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Add use to team object"
        node_type:
          type: string
          const: objectoperation_addsubscription
        description:
          type: string
          nullable: true
          description: Description of what this node does
        is_object_id_dynamic:
          type: boolean
          default: false
          description: "Whether object_type and object_id are static literal strings or handlebars expressions."
        object_type:
          type: string
          description: "Type/collection name of the object."
          minLength: 1
        object_id:
          type: string
          description: "Unique identifier of the object within the object_type."
          minLength: 1
        create_object_if_missing:
          type: boolean
          description: "Whether to create the object if it doesn't exist."
        user_selection:
          type: array
          description: "Which users to add as subscribers to the object. Can select actor, recipient, or both."
          minItems: 1
          items:
            type: string
            enum: ["actor", "recipient"]
        subscription_properties:
          type: string
          description: "Additional subscription properties which defines the relationship between object and user. Eg. role, designation, etc. Pass as JSONNET expression."
          example: "{\"role\": \"admin\"}"

    ObjectOperationRemoveSubscriptionNode:
      title: Unsubscribe from Object
      type: object
      description: "[**Unsubscribe from Object**](https://docs.suprsend.com/docs/unsubscribe-from-object): Removes users (actor or recipient) as subscribers from an object. Object must exist for the operation to succeed."
      required:
        - node_type
        - name
        - object_type
        - object_id
        - user_selection
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Unsubscribe from project"
        node_type:
          type: string
          const: objectoperation_removesubscription
        description:
          type: string
          nullable: true
          description: Description of what this node does
        is_object_id_dynamic:
          type: boolean
          default: false
          description: "Whether object_type and object_id are static literal strings or handlebars expressions."
        object_type:
          type: string
          description: "Type/collection name of the object."
          minLength: 1
        object_id:
          type: string
          description: "Unique identifier of the object within the object_type."
          minLength: 1
        user_selection:
          type: array
          description: "Which users to remove as subscribers from the object. Can select actor, recipient, or both."
          minItems: 1
          items:
            type: string
            enum: ["actor", "recipient"]

    UserUpdateNode:
      title: Update User Profile
      type: object
      description: "[**Update User Profile**](https://docs.suprsend.com/docs/update-user-profile): Updates user profile properties for either the actor or recipient using JSONNET expression."
      required:
        - node_type
        - name
        - user_selection
        - properties
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Update user profile"
        node_type:
          type: string
          const: userupdate
        description:
          type: string
          nullable: true
          description: Description of what this node does
        user_selection:
          type: string
          enum: ["actor", "recipient"]
          description: "Select which user to update - actor who triggered the workflow or the recipient of the workflow."
        properties:
          type: string
          description: "JSONNET script that evaluates at runtime to a map/dictionary of user properties to update."
          minLength: 1
          example: "{\"name\": \"John Doe\", \"email\": \"john.doe@example.com\"}"

    InvokeWorkflowNode:
      title: Invoke Workflow
      type: object
      description: "[**Invoke Workflow**](https://docs.suprsend.com/docs/invoke-workflow): Triggers another workflow using data from the current workflow run. Generally used when you have to notify different recipients at different stages of the workflow."
      required:
        - node_type
        - name
        - workflow
        - recipient_selection
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Escalate to the manager"
        node_type:
          type: string
          const: invokeworkflow
        description:
          type: string
          nullable: true
          description: Description of what this node does
        workflow:
          type: string
          description: "Slug of the workflow to invoke."
          minLength: 1
          maxLength: 255
          pattern: "^[a-z0-9-_]+$"
        actor_selection:
          type: string
          enum: [null, "recipient", "actor", "expression"]
          description: "Where to pick the actor from for the invoke-workflow payload. \n\n**recipient**: Use the recipient of the current workflow run. \n\n**actor**: Use the actor who triggered the current workflow run. \n\n**expression**: Use a JSONNET expression to derive the actor at runtime using data from the current workflow run."
        actor_expression:
          type: string
          description: "JSONNET expression to derive the actor at runtime for the invoked workflow. Pass when `actor_selection` is 'expression'. Eg. `data[\"$recipient\"].id`"
          minLength: 1
        recipient_selection:
          type: string
          enum: ["recipient", "actor", "expression"]
          description: "Where to pick the recipient from for the invoke-workflow payload. \n\n**recipient**: Use the recipient of the current workflow run. \n\n**actor**: Use the actor who triggered the current workflow run. \n\n**expression**: Use a JSONNET expression to derive the recipient at runtime using data from the current workflow run."
        recipient_expression:
          type: string
          description: "JSONNET expression to derive the recipient at runtime for the invoked workflow. Pass when `recipient_selection` is 'expression'. Eg. `data[\"$recipient\"].manager_id`"
          minLength: 1
        data:
          type: string
          description: "JSONNET expression to derive the data field for the invoke-workflow payload."
        append_current_run_data:
          type: boolean
          description: "Whether the current workflow-run data should be passed as payload of the invoked workflow."

    SendEmailNode:
      title: Send Email
      type: object
      description: "[**Email**](https://docs.suprsend.com/docs/delivery-single-channel): Sends email notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send welcome email"
        node_type:
          type: string
          const: send_email
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendSmsNode:
      title: Send SMS
      type: object
      description: "[**SMS**](https://docs.suprsend.com/docs/delivery-single-channel)): Sends SMS text message notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send OTP SMS"
        node_type:
          type: string
          const: send_sms
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for SMS notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"


    SendWhatsappNode:
      title: Send WhatsApp
      type: object
      description: "[**WhatsApp**](https://docs.suprsend.com/docs/delivery-single-channel): Sends WhatsApp message notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send WhatsApp order confirmation"
        node_type:
          type: string
          const: send_whatsapp
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for WhatsApp notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendMobilePushNode:
      title: Send Mobile Push
      type: object
      description: "[**Mobile Push**](https://docs.suprsend.com/docs/delivery-single-channel): Sends push notifications to mobile devices (Android and iOS) using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send mobile push notification"
        node_type:
          type: string
          const: send_mobile_push
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for mobile push notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendInboxNode:
      title: Send Inbox
      type: object
      description: "[**Inbox**](https://docs.suprsend.com/docs/delivery-single-channel): Sends in-app inbox notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send in-app notification"
        node_type:
          type: string
          const: send_inbox
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for in-app inbox notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendWebpushNode:
      title: Send Web Push
      type: object
      description: "[**Web Push**](https://docs.suprsend.com/docs/delivery-single-channel): Sends web push notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send web push notification"
        node_type:
          type: string
          const: send_webpush
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for web push notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendSlackNode:
      title: Send Slack
      type: object
      description: "[**Slack**](https://docs.suprsend.com/docs/delivery-single-channel): Sends Slack message notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send Slack notification"
        node_type:
          type: string
          const: send_slack
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for Slack notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendMsTeamsNode:
      title: Send Microsoft Teams
      type: object
      description: "[**Microsoft Teams**](https://docs.suprsend.com/docs/delivery-single-channel): Sends Microsoft Teams chat notifications using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send Teams notification"
        node_type:
          type: string
          const: send_ms_teams
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for Microsoft Teams notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"

    SendMultiChannelNode:
      title: Send Multi-Channel
      type: object
      description: "[**Multi-Channel**](https://docs.suprsend.com/docs/delivery-multi-channel): Sends notifications across multiple channels simultaneously using a specified template."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send multi-channel notification"
        node_type:
          type: string
          const: send_multi_channel
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for notification content across all channels."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"
        channels:
          type: array
          description: "Specific channels to use when sending multi-channel notification. If not provided, all channels will be used."
          required: true
          items:
            type: string
            enum: ["sms", "email", "androidpush", "iospush", "webpush", "inbox", "whatsapp", "slack", "ms_teams"]
        channels_expr:
          type: string
          description: "jq-expression for preparing channel list dynamically at runtime."
          minLength: 2

    SendSmartChannelRoutingNode:
      title: Smart Channel Routing
      type: object
      description: "[**Smart Channel Routing**](https://docs.suprsend.com/docs/smart-delivery): Sends notification subsequently at each consecutive channel with a delay (computed using time-to-live) between each channel."
      required:
        - node_type
        - name
        - template
      properties:
        name:
          type: string
          description: Human-readable name of the node
          example: "Send smart channel notification"
        node_type:
          type: string
          const: send_smart_channel_routing
        description:
          type: string
          nullable: true
          description: Description of what this node does
        template:
          type: string
          description: "Slug of the template used for smart channel routing notification content."
          minLength: 1
          maxLength: 120
          pattern: "^[a-z0-9-_]+$"
        channels:
          type: array
          description: "Available channels for smart routing algorithm to choose from."
          items:
            type: string
            enum: ["sms", "email", "androidpush", "iospush", "webpush", "inbox", "whatsapp", "slack", "ms_teams"]
        channels_expr:
          type: string
          description: "jq-expression for preparing available channel list dynamically at runtime."
          minLength: 2
        success:
          type: string
          description: "Success metric to track for smart channel routing."
          examples:
            delivered:
              summary: "Notification delivered"
              value: "delivered"
            seen:
              summary: "Notification seen"
              value: "seen"
            interacted:
              summary: "User clicked the notification"
              value: "interacted"
            custom_event:
              summary: "Custom event name"
              value: "<custom_event_name>"
        success_is_event:
          type: boolean
          description: "Whether the success metric is a custom event. If not, notification status will be used to determine success."
        ttl_value:
          type: string
          description: "Time-to-live value for the smart channel routing notification in static duration format."
          example: "1h"
        mandatory_channels:
          type: array
          description: "Channels that will be sent immediately regardless of smart routing logic."
          items:
            type: string
            enum: ["sms", "email", "androidpush", "iospush", "webpush", "inbox", "whatsapp", "slack", "ms_teams"]
        routing_basis:
          type: string
          enum: ["cost_low_to_high"]
          description: "Basis for smart channel routing. Determines the order in which channels are tried. Right now only `cost_low_to_high` is supported. We'll be adding more routing rules like in the order of engagement in future."
        
    WorkflowCreateUpdate:
      type: object
      required:
        - name
        - trigger_type
        - category
        - tree
      properties:
        name:
          type: string
          description: Human-readable name of the workflow. Workflow slug is generated from this name for new workflows.
          example: "Welcome Sequence"
        description:
          type: string
          nullable: true
          description: Description explaining the usecase of the workflow
        is_enabled:
          type: boolean
          default: true
          description: Whether the workflow should be enabled
        category:
          type: string
          description: Notification category of the workflow. Used to apply category-specific settings and preferences.
          example: "transactional"
        tags:
          type: array
          items:
            type: string
          description: Tags are used for grouping and filtering workflows in list.
          example: "onboarding-sequence"
        trigger_type:
          type: string
          enum: ["event", "api"]
          description: You can trigger a workflow either via API by passing its slug directly, or through an event-based system where the workflow runs when a specific event occurs. You can compare both methods [here](https://docs.suprsend.com/docs/event-vs-api-trigger). If the workflow should run when a user enters or exits a list, use `trigger_type = event`.
        payload_schema:
          type: object
          nullable: true
          properties:
            schema:
              type: string
              description: Linked schema slug. You can create a schema via [Create Schema](/reference/create-schema) endpoint and then link it here.
              example: "onboarding-sequence-schema"
            version_no:
              type: integer
              description: Schema version number to link. By default, live version is always picked for validation
              example: 1
          description: Schema to validate workflow api data structure. Used only when trigger_type = api.
        trigger_events:
          type: array
          items:
            type: string
          description: Events that trigger this workflow (required if trigger_type = event). In case of list entry/exit, event names will be `$USER_ENTERED_LIST - <list_id>` and `$USER_EXITED_LIST - <list_id>` respectively.
        ratelimit:
          type: object
          nullable: true
          description: Throttle settings for the workflow. This is used to limit the number of times a workflow can be executed per user in a given time period.
          properties:
            count:
              type: integer
              description: Maximum number of executions allowed within the sliding window
              example: 4
            sliding_window:
              type: string
              description: Time window for rate limiting to be passed in format `00d00h00m00s`, d (days), h (hours), m (minutes), s (seconds). Rate limit is applied within this window.
              example: "6m"
        conditions:
          type: array
          nullable: true
          description: Trigger Conditions. Workflow will be executed if any of the conditions in this array evaluate to true.
          items:
            type: object
            properties:
              type:
                type: string
                description: Type of condition expression. Currently only `expression_v1` is supported.
                example: "expression_v1"
                enum: ["expression_v1"]
              expression_v1:
                type: object
                description: Expression object containing the condition logic
                properties:
                  op:
                    type: string
                    description: Logical operator to combine conditions. Currently only `AND` is supported.
                    enum: ["AND"]
                  args:
                    type: array
                    description: Array of conditions. Each condition is defined as key (variable) <op> value. Refer to [how to construct a condition here](https://docs.suprsend.com/docs/branch#constructing-a-condition).
                    items:
                      type: object
                      properties:
                        op:
                          type: string
                          description: Comparison operator between variable and value. Refer to list of [comparison operators here](https://docs.suprsend.com/docs/branch#key-value-pair).
                          example: "=="
                          enum: ["==", "!=", ">", "<", ">=", "<=", "EMPTY", "NON_EMPTY", "CONTAINS", "NOT_CONTAINS", "ARRAY_INTERSECTS", "NOT_ARRAY_INTERSECTS", "DATETIME_EQUALS", "DATETIME_LT", "DATETIME_GT"]
                        value:
                          type: string
                          description: Value to compare against. Can add fixed value as ".." or variable in JSONNET format as data.<prop>.
                          example: "\"admin\""
                        variable:
                          type: string
                          description: key from your trigger payload to compare the value against. Direct key name is passed here.
                          example: "role"
                        variable_ns:
                          type: string
                          description: Variable namespace (empty for data passed in trigger, `$recipient` for recipient or object subscription properties, `$tenant` for tenant properties)
                          example: "$recipient"
                          enum: ["", "$recipient", "$tenant"]
        override_recipients_type:
          type: string
          description: Override recipients using a property from the trigger payload. Type defines if the workflow should run for a list of users or a single [object](https://docs.suprsend.com/docs/objects). Only applicable for trigger_type = `event`.
          example: "user"
          enum: ["user", "single_object_fields"]
        override_recipients_user_expr:
          type: string
          nullable: true
          description: JQ expression to override recipients when override_recipients_type = `user`. Only applicable for trigger_type = `event`.
          example: ".distinct_id"
        override_recipients_single_object_fields_expr:
          type: object
          nullable: true
          description: JQ expression to override recipients with object when override_recipients_type = `single_object_fields`. Only applicable for trigger_type = `event`.
          properties:
            id:
              type: string
              description: JQ expression to extract object ID from trigger payload
              example: ".object_id"
            object_type:
              type: string
              description: JQ expression to extract object type from trigger payload. You can also pass fixed value as "..".
              example: ".object_type"
            "$object_subscriptions_query.depth":
              type: string
              description: Depth [Optional] is used to specify how deep to traverse object subscriptions. `depth=0`  would only send notification to object channels and not its subscribers,  `depth=1`  would fetch 1 level of subscriptions, `depth=2`  (maximum) → Also fetches subscriptions of child objects, eg. <department -> teams -> team members>.
              example: "2"
          example:
            id: ".object_id"
            object_type: ".object_type"
            "$object_subscriptions_query.depth": "2"
        override_actor_user_expr:
          type: string
          nullable: true
          description: JQ expression to override actor. Only applicable for trigger_type = `event`.
          example: ".actor_id"
        override_tenant_expr:
          type: string
          nullable: true
          description: JQ expression to override [tenant](https://docs.suprsend.com/docs/tenants). Only applicable for trigger_type = `event`.
          example: ".tenant_id"
        tree:
          type: object
          properties:
            nodes:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/DelayNode'
                  - $ref: '#/components/schemas/BatchNode'
                  - $ref: '#/components/schemas/DigestNode'
                  - $ref: '#/components/schemas/HttpApiWebhookNode'
                  - $ref: '#/components/schemas/HttpApiFetchNode'
                  - $ref: '#/components/schemas/BranchWaitUntilNode'
                  - $ref: '#/components/schemas/BranchNode'
                  - $ref: '#/components/schemas/TransformNode'
                  - $ref: '#/components/schemas/TimeWindowNode'
                  - $ref: '#/components/schemas/SubscriberListOperationAddUserNode'
                  - $ref: '#/components/schemas/SubscriberListOperationRemoveUserNode'
                  - $ref: '#/components/schemas/ObjectOperationAddSubscriptionNode'
                  - $ref: '#/components/schemas/ObjectOperationRemoveSubscriptionNode'
                  - $ref: '#/components/schemas/UserUpdateNode'
                  - $ref: '#/components/schemas/InvokeWorkflowNode'
                  - $ref: '#/components/schemas/SendEmailNode'
                  - $ref: '#/components/schemas/SendSmsNode'
                  - $ref: '#/components/schemas/SendWhatsappNode'
                  - $ref: '#/components/schemas/SendMobilePushNode'
                  - $ref: '#/components/schemas/SendInboxNode'
                  - $ref: '#/components/schemas/SendWebpushNode'
                  - $ref: '#/components/schemas/SendSlackNode'
                  - $ref: '#/components/schemas/SendMsTeamsNode'
                  - $ref: '#/components/schemas/SendMultiChannelNode'
                  - $ref: '#/components/schemas/SendSmartChannelRoutingNode'
              description: Array of nodes in the workflow tree structure.
          description: Node tree structure of the workflow. Contains the nodes array with all workflow nodes and their configuration.
        
        
    ErrorResponse:
      type: object
      properties:
        code:
          type: integer
          description: HTTP status code
        error_code:
          type: string
          description: Specific error code identifier
        type:
          type: string
          description: Error type classification
        message:
          type: string
          description: Human-readable error message
        detail:
          type: string
          description: Additional error details

    MessageResponse:
      type: object
      description: A single notification delivery attempt produced by a workflow trigger or broadcast.
      properties:
        message_id:
          type: string
          description: Message-id to update.
        created_at:
          type: string
          format: date-time
          description: Time when the message entry was created.
        updated_at:
          type: string
          format: date-time
          description: Time when the message entry was last updated (for example, on a status or timestamp change).
        triggered_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the message was handovered to vendor by SuprSend.
        delivered_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the vendor confirmed successful delivery. Null if the message has not been delivered yet. If you're not getting delivery events for email, SMS and Whatsapp, make sure to configure SuprSend webhook URL in vendor portal.
        seen_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the recipient first saw or opened the message. Seen tracking is available for all channels accept Slack, MS Teams and SMS.
        clicked_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the recipient clicked or interacted with the message. Tracked for Email, Push and Inbox.
        dismissed_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the recipient dismissed or cleared the message. Only application for mobile push notifications.
        read_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the message was marked as read. Only applicable for Inbox channel.
        unread_at:
          type: string
          format: date-time
          nullable: true
          description: Time when a previously read message was marked unread. Only applicable for Inbox channel.
        archived_at:
          type: string
          format: date-time
          nullable: true
          description: Time when the message was archived. Only applicable for Inbox channel.
        unarchived_at:
          type: string
          format: date-time
          nullable: true
          description: Time when a previously archived message was unarchived. Only applicable for Inbox channel.
        is_read:
          type: boolean
          description: Whether the message is currently in the read state. Only applicable for Inbox channel.
        is_archived:
          type: boolean
          description: Whether the message is currently archived. Only applicable for Inbox channel.
        status:
          type: string
          description: |
            Current message status. Other than `archived`, all actions translate to a status. Archived is just a flag on the message.

            - `triggered` - Message has been triggered by SuprSend and queued for delivery to the vendor.
            - `trigger_failed` - Vendor reported failure in response to delivery API call itself.
            - `trigger_blocked` - Test mode is enabled and this channel was not part of allowed channel list.
            - `not_to_be_triggered` - Message was intentionally skipped (generally happens in smart delivery when success metric is achieved)
            - `to_be_triggered` - Message is queued and waiting to be triggered (generally happens when there is a wait added in smart delivery)
            - `sent_by_vendor` - Vendor accepted the message for delivery; final delivery confirmation is pending.
            - `delivered` - Vendor confirmed successful delivery to the recipient.
            - `delivery_failure` - Vendor reported a delivery failure (for example, bounce or invalid recipient).
            - `seen` - Recipient saw or opened the message.
            - `clicked` - Recipient clicked or interacted with the message.
            - `dismissed` - Recipient dismissed the message without acting on it.
            - `read` - Inbox message was marked as read by the recipient.
          enum:
            - triggered
            - trigger_failed
            - trigger_blocked
            - not_to_be_triggered
            - to_be_triggered
            - sent_by_vendor
            - delivered
            - delivery_failure
            - seen
            - clicked
            - dismissed
            - read
        channel:
          type: string
          description: Channel through which the message was sent.
          enum: 
            - sms
            - email
            - whatsapp
            - inbox
            - androidpush
            - iospush
            - webpush
            - slack
            - ms_teams
        idempotency_key:
          type: string
          description: Idempotency key supplied at trigger time to prevent duplicate sends for the same logical event.
        failure_reason:
          type: string
          description: Human-readable reason describing why delivery failed. Empty when the message did not fail.
        recipient:
          type: object
          description: "Recipient of the message. Either a user (`$type: user`) or an object (`$type: object`)."
          properties:
            $type:
              type: string
              description: Recipient type - `user` for a user recipient or `object` for an object recipient.
              enum:
                - user
                - object
            distinct_id:
              type: string
              description: Distinct ID of the user recipient. Present when `$type` is `user`.
            object_type:
              type: string
              description: Object type slug. Present when `$type` is `object`.
            id:
              type: string
              description: Object ID. Present when `$type` is `object`.
        parent_entity_id:
          type: string
          description: ID of the parent entity (object)
        parent_entity_type:
          type: string
          description: Type of the parent entity that originated this message (object)
        vendor:
          type: object
          description: Delivery vendor that handled this message.
          properties:
            name:
              type: string
              description: Internal name of the vendor integration (for example, `sendgrid`, `twilio`).
            nickname:
              type: string
              description: User-defined nickname for the vendor integration in the SuprSend dashboard.
        execution_id:
          type: string
          description: ID of the workflow execution this message belongs to.
        parent_execution_id:
          type: string
          description: ID of the parent execution, when this message was produced as fanout on object trigger.
        is_campaign:
          type: boolean
          description: true when message was sent as part of a broadcast.
        tenant_id:
          type: string
          description: ID of the tenant the message was sent under.
        workflow:
          type: object
          description: Workflow that produced the message.
          properties:
            slug:
              type: string
              description: Unique slug of the workflow.
            version_id:
              type: string
              description: ID of the specific workflow version that ran.
            name:
              type: string
              description: Human-readable name of the workflow.
            node_ref:
              type: string
              description: Slug to the specific node within the workflow that emitted this message.
        template:
          type: object
          description: Template used to render the message.
          properties:
            name:
              type: string
              description: Human-readable name of the template.
            slug:
              type: string
              description: Unique slug of the template.
            version_no:
              type: integer
              description: Version number of the template that was used to render the message.
            variant_id:
              type: string
              description: ID of the template variant used to render the message. `default` for the base variant.
        content:
          type: object
          additionalProperties: true
          description: Rendered message content. Only present when `include_content=true` is passed as a query parameter.
        channel_identity:
          type: object
          additionalProperties: true
          description: Channel-specific recipient identity that the message was delivered to (for example, the phone number for SMS, email address for email). Credential keys (`access_token`, `keys`, `incoming_webhook`) are stripped from the response.
          example:
            sms: "+15555550100"
        category:
          type: string
          description: Notification category slug associated with this message.

    CursorPagination:
      type: object
      properties:
        count:
          type: integer
          description: Total matching records (ignores cursor position).
        limit:
          type: integer
          description: Maximum number of results returned per page.
        has_prev:
          type: boolean
          description: True when the previous page (newer logs) exists.
        before:
          type: string
          nullable: true
          description: Cursor to pass as `before=` to retrieve the previous page (newer logs). Null on the first page or when `has_prev` is false.
        has_next:
          type: boolean
          description: True when an next page (older logs) exist.
        after:
          type: string
          nullable: true
          description: Cursor to pass as `after=` to retrieve the next page (older logs). Null when `has_next` is false.

    BulkPatchItemResult:
      type: object
      description: Per-message outcome from the bulk patch endpoint. Success is implied by a null `error` field.
      properties:
        message_id:
          type: string
          description: Message-id to update.
        status_code:
          type: integer
          description: |
            Per-item status code:
            - `202` - success
            - `404` - `not_found`
            - `422` - `status_blocked` or `action_not_supported`
            - `500` - `internal_error`
        error:
          type: object
          nullable: true
          description: Null on success, populated on failure.
          required:
            - type
            - message
          properties:
            type:
              type: string
              description: |
                Machine-readable key for why the item failed:
                - `not_found` - message_id not found in this workspace
                - `status_blocked` - message is in a terminal state (`trigger_failed`, `trigger_blocked`, `failure_by_vendor`, `not_to_be_triggered`) that cannot be overridden
                - `action_not_supported` - action is invalid for the message's channel (for example, `dismissed` on inbox, `read` on sms)
                - `internal_error` - Internal error at SuprSend end. Reach out to support if you get this error code.
              enum:
                - not_found
                - status_blocked
                - action_not_supported
                - internal_error
            message:
              type: string
              description: Human-readable detail. Do not parse programmatically.

    WorkspaceCreate:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Workspace name
        description:
          type: string
          description: Optional human-readable description

    WorkspaceApiKeyCreate:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Label for the API key
        description:
          type: string
          description: Optional notes for operators

    DisableWorkspaceApiKeyRequest:
      type: object
      required:
        - is_disabled
      properties:
        is_disabled:
          type: boolean
          description: Set to true to disable the API key

    WorkspacePublicKeyCreate:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Label for the public key
        description:
          type: string
          description: Optional notes

    PatchWorkspacePublicKeyRequest:
      type: object
      required:
        - is_secure_mode_enabled
      properties:
        is_secure_mode_enabled:
          type: boolean
          description: Enable or disable secure mode for this public key

    RollWorkspaceSigningKeyRequest:
      type: object
      properties:
        expiry_at:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the previous signing key material should expire

    ManagementListMeta:
      type: object
      description: Pagination metadata (when applicable)
      properties:
        count:
          type: integer
          description: Total items matching the query
        limit:
          type: integer
          nullable: true
          description: Maximum number of results returned per page.
        offset:
          type: integer
          nullable: true
          description: Starting position of the returned results.

    ManagementActor:
      type: object
      description: Identity that performed an action (created, updated, rolled, deleted, rotated).
      nullable: true
      properties:
        name:
          type: string
          description: Display name of the actor.
          example: "System User"
        email:
          type: string
          description: Email address of the actor.
          example: "user@example.com"

    ManagementWorkspace:
      type: object
      description: Workspace record returned by the Management API.
      properties:
        uid:
          type: string
          description: Unique workspace identifier.
          example: "wksp_exampleUid01"
        slug:
          type: string
          description: Workspace slug used in API paths (e.g. `staging`, `production`).
          example: "staging"
        data_center:
          type: object
          description: Data center metadata associated with the workspace.
          additionalProperties: true
        is_expired:
          type: boolean
          description: Indicates whether the workspace has expired.
        has_limit_reached:
          type: boolean
          description: Indicates whether the workspace has reached its plan limit.
        name:
          type: string
          description: Human-readable workspace name.
          example: "Staging"
        description:
          type: string
          nullable: true
          description: Optional workspace description.
        mode:
          type: string
          description: Workspace mode. **sandbox** is pre-created by SuprSend for early testing with pre-configured vendors, **staging** will be your testing workspace and **production** will be the one you'll use to send to your actual users.
          enum: [sandbox, production]

    ManagementWorkspaceListResponse:
      type: object
      properties:
        meta:
          $ref: '#/components/schemas/ManagementListMeta'
        results:
          type: array
          items:
            $ref: '#/components/schemas/ManagementWorkspace'

    WorkspaceCreateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Workspace name.
          example: "my-workspace"
        description:
          type: string
          nullable: true
          description: Optional workspace description.
          example: "Testing workspace API"

    WorkspaceConfig:
      type: object
      description: Workspace-level configuration flags.
      properties:
        user_inbox_preference_enabled:
          type: boolean
          description: If you are using the Inbox channel, enable this to show the Inbox channel in the preference centre.
          example: true
        sms_vendor_type:
          type: string
          enum: [basic, dlt]
          description: SMS delivery mode for the workspace. Use `dlt` for India DLT-compliant sends; `basic` for standard sends.
          example: "basic"
        user_tenancy_mode:
          type: string
          enum: [shared, exclusive]
          description: |
            Constraint on user-tenant associations for this workspace.
            - `shared` — a user can belong to any number of tenants.
            - `exclusive` — a user can belong to at most one tenant. The associate call rejects users that already have a mapping.

            New workspaces default to `exclusive`; workspaces that existed before this setting was introduced default to `shared`.
          example: "exclusive"
        user_tenancy_channel_fallback_mode:
          type: string
          enum: [all, allowlist]
          description: |
            Controls which channels a tenant-scoped profile is allowed to inherit from the user's global profile when the tenant has no override for that channel.
            - `all` — every channel falls back to global (default; reproduces a straight shallow merge).
            - `allowlist` — only the channels listed in `user_tenancy_channel_fallback` fall back; every other channel is dropped from the send when the tenant has no override for it. Prevents identities like `$androidpush` or `$slack` from leaking across tenants.
          example: "all"
        user_tenancy_channel_fallback:
          type: array
          items:
            type: string
          description: |
            Channel keys allowed to fall back from the global profile when `user_tenancy_channel_fallback_mode = allowlist`. Ignored when the mode is `all`.

            Typical setup: `["$email", "$sms", "$whatsapp"]` — safe to fall back — while excluding `$androidpush`, `$iospush`, `$webpush`, `$inbox`, and `$slack`.
          example: ["$email", "$sms", "$whatsapp"]
        user_tenancy_channel_fallback_applies_to_default_tenant:
          type: boolean
          default: false
          description: |
            Whether the fallback rule above also governs sends that carry no `tenant_id` (the default-tenant path).
            - `false` (default) — the default-tenant path always falls back for every channel, regardless of the allowlist.
            - `true` — the default-tenant path follows the same `user_tenancy_channel_fallback_mode` + `user_tenancy_channel_fallback` rule as other tenants.
          example: false

    WorkspaceConfigUpdateRequest:
      type: object
      description: |
        Body for `PATCH /v1/workspace/{workspace_slug}/config/`. Include only the fields you want to change — omitted fields are left untouched.
      properties:
        user_inbox_preference_enabled:
          type: boolean
          description: If you are using the Inbox channel, enable this to show the Inbox channel in the preference centre.
          example: true
        sms_vendor_type:
          type: string
          enum: [basic, dlt]
          description: Switch the workspace's SMS delivery mode. Confirm with your SMS provider before switching to or from `dlt`.
          example: "basic"
        user_tenancy_mode:
          type: string
          enum: [shared, exclusive]
          description: |
            Change how users are constrained across tenants. See [User-tenant mapping](/docs/user-tenant-mapping) for the effects of switching this value.
          example: "shared"
        user_tenancy_channel_fallback_mode:
          type: string
          enum: [all, allowlist]
          description: Switch between `all` (every channel falls back from global) and `allowlist` (only channels in `user_tenancy_channel_fallback` fall back).
          example: "allowlist"
        user_tenancy_channel_fallback:
          type: array
          items:
            type: string
          description: Channel keys allowed to fall back when `user_tenancy_channel_fallback_mode = allowlist`. Ignored otherwise.
          example: ["$email", "$sms", "$whatsapp"]
        user_tenancy_channel_fallback_applies_to_default_tenant:
          type: boolean
          description: When true, the fallback rule above also governs sends with no `tenant_id`.
          example: false

    ManagementWorkspaceApiKey:
      type: object
      description: Workspace-scoped REST API key (server-side secret).
      properties:
        id:
          type: string
          description: Unique identifier of the API key.
          example: "ws_apik_exampleId01"
        masked_api_key:
          type: string
          description: Masked preview of the API key used in list responses.
          example: "SS.XXXXXXX*****"
        is_deleted:
          type: boolean
          description: Indicates whether the API key has been deleted.
        name:
          type: string
          description: Label for the API key.
          example: "backend-prod"
        allowed_domains:
          type: array
          items:
            type: string
          description: Domains allowed to use this key.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the API key was created.
        created_by:
          $ref: '#/components/schemas/ManagementActor'
        deleted_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the API key was deleted, if applicable.
        deleted_by:
          $ref: '#/components/schemas/ManagementActor'

    ManagementWorkspaceApiKeyCreateResponse:
      allOf:
        - $ref: '#/components/schemas/ManagementWorkspaceApiKey'
        - type: object
          properties:
            api_key:
              type: string
              description: Full secret API key. Returned only once at creation - store it securely and never commit to source control.
              example: "SS.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

    ManagementWorkspaceApiKeyListResponse:
      type: object
      properties:
        meta:
          $ref: '#/components/schemas/ManagementListMeta'
        results:
          type: array
          items:
            $ref: '#/components/schemas/ManagementWorkspaceApiKey'

    WorkspaceApiKeyCreateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Label for the API key.
          example: "backend-prod"
        description:
          type: string
          nullable: true
          description: Optional notes for operators.

    ManagementWorkspacePublicKey:
      type: object
      description: Workspace public key used by client SDKs.
      properties:
        id:
          type: string
          description: Unique identifier of the public key.
          example: "ws_pubk_exampleId01"
        api_key:
          type: string
          description: Public key value exposed to clients.
          example: "SS.PUBK.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        name:
          type: string
          description: Label for the public key.
          example: "web-app"
        allowed_domains:
          type: array
          nullable: true
          items:
            type: string
          description: Domains allowed to use this public key.
        is_secure_mode_enabled:
          type: boolean
          description: Indicates whether secure mode is enabled for this key.
        is_deleted:
          type: boolean
          description: Indicates whether the public key has been deleted.
        is_default:
          type: boolean
          description: Indicates whether this is the default public key for the workspace.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the public key was created.
        created_by:
          $ref: '#/components/schemas/ManagementActor'
        rotated_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the public key was last rotated.
        rotated_by:
          $ref: '#/components/schemas/ManagementActor'
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the public key was last updated.
        updated_by:
          $ref: '#/components/schemas/ManagementActor'

    ManagementWorkspacePublicKeyListResponse:
      type: object
      properties:
        meta:
          $ref: '#/components/schemas/ManagementListMeta'
        results:
          type: array
          items:
            $ref: '#/components/schemas/ManagementWorkspacePublicKey'

    WorkspacePublicKeyCreateRequest:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Label for the public key.
          example: "web-app"
        description:
          type: string
          nullable: true
          description: Optional notes.

    WorkspacePublicKeyPatchRequest:
      type: object
      required:
        - is_secure_mode_enabled
      properties:
        is_secure_mode_enabled:
          type: boolean
          description: Enable or disable secure mode for this public key.

    ManagementWorkspaceSigningKey:
      type: object
      description: Signing key used to verify signed payloads.
      properties:
        id:
          type: string
          description: Unique identifier of the signing key.
          example: "ws_signk_exampleId01"
        uid:
          type: string
          description: Signing key uid used in path parameters for roll/delete.
          example: "signing_key_exampleUid01"
        status:
          type: string
          description: Status of the signing key.
          enum: [active, rolled]
        allowed_domains:
          type: array
          nullable: true
          items:
            type: string
          description: Domains allowed to use this signing key.
        expiry_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the signing key expires.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the signing key was created.
        created_by:
          $ref: '#/components/schemas/ManagementActor'
        rolled_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the signing key was rolled.
        rolled_by:
          $ref: '#/components/schemas/ManagementActor'
        deleted_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the signing key was deleted.
        deleted_by:
          $ref: '#/components/schemas/ManagementActor'

    ManagementWorkspaceSigningKeyCreateResponse:
      allOf:
        - $ref: '#/components/schemas/ManagementWorkspaceSigningKey'
        - type: object
          properties:
            private_key_pem:
              type: string
              description: PEM-encoded private key. Returned only at creation and on roll - store it securely and never commit to source control.
              example: "-----BEGIN PRIVATE KEY-----\n...redacted...\n-----END PRIVATE KEY-----\n"
            private_key_base64:
              type: string
              description: Base64-encoded private key. Returned only at creation and on roll.
              example: "LS0tLS1CRUdJTi...redacted..."

    ManagementWorkspaceSigningKeyListResponse:
      type: object
      properties:
        meta:
          $ref: '#/components/schemas/ManagementListMeta'
        results:
          type: array
          items:
            $ref: '#/components/schemas/ManagementWorkspaceSigningKey'
    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]

  responses:
    NotFoundError:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: 404
            error_code: "not_found"
            type: "NotFound"
            message: "workspace 'demo' not found"
            detail: "workspace 'demo' not found"
    
    AuthenticationError:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: 401
            error_code: "authentication_failed"
            type: "AuthenticationFailed"
            message: "Invalid service token."
            detail: "Invalid service token."

    UnauthorizedError:
      description: Not Authenticated - could not find Workspace details
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    BadRequestError:
      description: Bad request - invalid input data
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ValidationError:
      description: Validation error - data validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ConflictError:
      description: Conflict - resource already exists or state conflict
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            code: 401
            error_code: "unauthorized"
            type: "Unauthorized"
            message: "Not Authenticated - could not find Workspace details"
            detail: "Authentication failed"

security:
  - sec0: []
  - BearerAuth: []
paths:
  /event/:
    post:
      summary: Trigger an Event
      security:
        - BearerAuth: []
      description: API to pass an event, which in turn triggers workflows where that event is defined as the trigger.
      operationId: event-api
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - distinct_id
                - event
              properties:
                distinct_id:
                  type: string
                  description: distinct_id of recipient who should receive the notification
                  default: _distinct_id_
                event:
                  type: string
                  description: string identifier for the event like `product_purchased`
                  default: _event_name_
                properties:
                  type: object
                  description: Properties are used to render template or workflow variables in the trigger.
                  properties:
                    $attachments:
                      type: array
                      description: Use this key to pass email attachment in the trigger. You can either pass attachment as a public URL or as a base64-encoded file (limit < 50KB).
                      items:
                        oneOf:
                          - type: object
                            title: "publicly accessible URL"
                            description: "**Option 1: Pass file as publicly accessible URL** (No limit on file size)"
                            required: [url]
                            properties:
                              url:
                                type: string
                                format: uri
                                description: Publicly accessible URL of the file
                                example: "https://bitcoincore.org/bitcoin.pdf"
                              filename:
                                type: string
                                description: Filename to be shown in email
                                example: "billing.pdf"
                              ignore_if_error:
                                type: boolean
                                description: Ignore the attachment if it fails to load

                          - type: object
                            title: "base64-encoded file"
                            description: Pass file as a **base-64 file** (supported limit < 50KB)
                            required: [data]
                            properties:
                              data:
                                type: string
                                description: Base64-encoded content of the file
                              filename:
                                type: string
                                description: Filename to be shown in email
                              contentType:
                                type: string
                                example: application/pdf
                  additionalProperties:
                    type: string
                tenant_id:
                  type: string
                  description: string identifier of the tenant this event is associated with
                $idempotency_key:
                  type: string
                  description: Idempotency key (valid for 24hours)
            examples:
              SHIPMENT ARRIVAL:
                value:
                  distinct_id: 0fxxx8f74-xxxx-41c5-8752-xxxcb6911fb08
                  event: ON SHIPMENT ARRIVAL
                  properties:
                    amount: 3780$
                    number: TRXC1034
                    vehicle: Truck
                    locations: San Francisco
      responses:
        '202':
          description: '202 - Accepted'
          content:
            application/json:
              examples:
                Result:
                  value: OK
              schema:
                type: object
                description: Confirmation that the event was accepted for processing.
                properties:
                  message:
                    type: string
                    description: Status message indicating the event was accepted.
                    example: OK
      deprecated: false
  /v1/tenant/{tenant_id}/:
    post:
      summary: Create / Update Tenants
      security:
        - BearerAuth: []
      description: API to create a new Tenant OR update an existing Tenant
      operationId: create-tenants
      parameters:
        - name: tenant_id
          in: path
          description: "Tenant identifier to create or update. Max 64 chars; allowed characters `[a-z0-9_.-]`."
          schema:
            type: string
            pattern: "^[a-z0-9_.-]+$"
            maxLength: 64
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: "Tenant display name. Replaces the legacy `tenant_name` field; both are accepted."
                  default: Awesome Tenant
                tenant_name:
                  type: string
                  description: "Will be deprecated in future. Use `name` instead."
                parent_id:
                  type: string
                  nullable: true
                  description: "ID of the parent tenant if you want to add this tenant as a sub-tenant. Skip this field, or pass `null` or `\"\"` to create the tenant as a root. Setting it on an existing tenant re-parents it or leave it `null` to delink existing parent. Must reference an existing tenant. See [Sub-tenants](/docs/sub-tenants)."
                  example: acme-corp
                blocked_channels:
                  type: array
                  items:
                    type: string
                  nullable: true
                  description: "Channels turned off for this tenant. Notifications on these channels won't be sent to any user of the tenant — including on [root categories](/docs/notification-category#root-categories) (which users normally can't unsubscribe from) — and users can't override this. If [sub-tenants](/docs/sub-tenants) are used, a block set here also applies to every sub-tenant below and can't be removed lower down. Allowed: `email`, `sms`, `whatsapp`, `androidpush`, `iospush`, `webpush`, `slack`, `ms_teams`, `inbox`."
                  example: ["sms"]
                logo:
                  type: string
                  description: Tenant logo URL.
                  default: https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend-only-logo_c8aa27faef118418e8c5bd7b31a1cafc74e09200.png
                primary_color:
                  type: string
                  description: Primary brand color, used in the tenant's email header, buttons, and footer. If left empty on create, it's copied from the default tenant.
                  default: '#ff0000'
                secondary_color:
                  type: string
                  description: Secondary brand color. Not part of the default tenant component but can be used in templates as `{{$tenant.secondary_color}}`. If left empty on create, it's copied from the default tenant.
                  example: '#00ff00'
                tertiary_color:
                  type: string
                  description: Tertiary brand color. Not part of the default tenant component but can be used in templates as `{{$tenant.tertiary_color}}`. If left empty on create, it's copied from the default tenant.
                  example: '#0000ff'
                preference_page_url:
                  type: string
                  description: URL of your product's preference page.
                social_links:
                  type: object
                  description: Tenant's social media URLs. Pass `""` to clear a link (not `null`).
                  properties:
                    website:
                      type: string
                      description: Website URL.
                      default: https://suprsend.com
                    facebook:
                      type: string
                      description: Facebook page URL.
                    LinkedIn:
                      type: string
                      description: LinkedIn page URL.
                    x:
                      type: string
                      description: X (formerly Twitter) page URL.
                    instagram:
                      type: string
                      description: Instagram page URL.
                    medium:
                      type: string
                      description: Medium page URL.
                    discord:
                      type: string
                      description: Discord URL.
                    telegram:
                      type: string
                      description: Telegram URL.
                    youtube:
                      type: string
                      description: YouTube channel URL.
                    tiktok:
                      type: string
                      description: TikTok URL.
                properties:
                  type: object
                  description: Custom tenant properties. Merged per top-level key on update — keys not in the payload are kept as-is.
                  additionalProperties:
                    type: string
      responses:
        '201':
          description: '201 - Created'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "id": "acme-corp",
                    "name": "Awesome Tenant",
                    "tenant_id": "acme-corp",
                    "tenant_name": "Awesome Tenant",
                    "parent_id": null,
                    "ancestors": [],
                    "level": 0,
                    "children_count": 0,
                    "logo": "https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend-only-logo_c8aa27faef118418e8c5bd7b31a1cafc74e09200.png",
                    "timezone": null,
                    "blocked_channels": ["sms"],
                    "embedded_preference_url": "https://app.suprsend.com/settings",
                    "hosted_preference_domain": "preferences.suprsend.com",
                    "primary_color": "#ff0000",
                    "secondary_color": "#0000ff",
                    "tertiary_color": "#00ffff",
                    "social_links": {
                      "website": "https://suprsend.com",
                      "facebook": "",
                      "linkedin": "",
                      "x": "",
                      "instagram": "",
                      "medium": "",
                      "discord": "",
                      "telegram": "",
                      "youtube": ""
                    },
                    "properties": {
                      "region": "US",
                      "support_email": "help@example.com"
                    },
                    "updated_at": "2026-08-27T21:01:35.359787Z"
                  }
              schema:
                type: object
                description: "Tenant object returned. Fields hold the tenant's own local values — values not set on this tenant come back as `null` (or as empty objects/arrays). For flat tenants (no [sub-tenants](/docs/sub-tenants)), unset fields stay unresolved and the tenant simply has no value for them. For [sub-tenants](/docs/sub-tenants), unset fields still return `null` here, but are resolved from the closest ancestor that has a value set at trigger time."
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 400,
                    "error_code": "error",
                    "type": "ValidationError",
                    "message": "{\"tenant_name\": [\"Ensure this field contains non-html text\"]}",
                    "detail": {
                      "tenant_name": [
                        "Ensure this field contains non-html text"
                      ]
                    }
                  }
              schema:
                type: object
                description: error code and message detailing the error
      deprecated: false
    get:
      summary: Get Tenant
      security:
        - BearerAuth: []
      description: API to fetch properties and blocked channel settingcorresponding to a tenant_id. To create or update tenant data, use the [Create/Update Tenant](#operation/create-tenants) endpoint.
      operationId: get-tenant
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant you want to get the details for
          schema:
            type: string
          required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "id": "eu-sales",
                    "name": "EU Sales",
                    "tenant_id": "eu-sales",
                    "tenant_name": "EU Sales",
                    "parent_id": "eu",
                    "ancestors": ["acme-corp", "eu"],
                    "level": 2,
                    "children_count": 0,
                    "logo": null,
                    "timezone": null,
                    "blocked_channels": null,
                    "embedded_preference_url": "https://app.suprsend.com/en/user-settings/notifications",
                    "hosted_preference_domain": "preferences.suprsend.com",
                    "primary_color": "#ff0055",
                    "secondary_color": null,
                    "tertiary_color": null,
                    "social_links": {
                      "website": "https://sales.example.eu"
                    },
                    "properties": {
                      "team_size": 42
                    },
                    "updated_at": "2026-08-27T21:01:35.359787Z"
                  }
              schema:
                type: object
                description: "Tenant object returned. Fields hold the tenant's own local values — values not set on this tenant come back as `null` (or as empty objects/arrays). For flat tenants (no [sub-tenants](/docs/sub-tenants)), unset fields stay unresolved and the tenant simply has no value for them. For [sub-tenants](/docs/sub-tenants), unset fields still return `null` here, but are resolved from the closest ancestor that has a value set at trigger time."
                properties:
                  id:
                    type: string
                    description: "Tenant `id`. Replaces the legacy `tenant_id` field; both are returned."
                    example: eu-sales
                  name:
                    type: string
                    description: "Tenant display name. Replaces the legacy `tenant_name` field; both are returned."
                    example: EU Sales
                  tenant_id:
                    type: string
                    description: "Will be deprecated in future. Use `id` instead."
                    example: eu-sales
                  tenant_name:
                    type: string
                    description: "Will be deprecated in future. Use `name` instead."
                    example: EU Sales
                  parent_id:
                    type: string
                    nullable: true
                    description: "Parent tenant `id` when this tenant is a [sub-tenant](/docs/sub-tenants). `null` for root tenants (including flat tenants that aren't part of a hierarchy)."
                    example: eu
                  ancestors:
                    type: array
                    items:
                      type: string
                    description: "For [sub-tenants](/docs/sub-tenants): ancestor tenant `id`s from root down to the immediate parent (excludes the tenant itself). Empty for root and flat tenants."
                    example: ["acme-corp", "eu"]
                  level:
                    type: integer
                    description: "For [sub-tenants](/docs/sub-tenants): depth in the tree. Root = 0, max = 4. Flat tenants always report `0`."
                    example: 2
                  children_count:
                    type: integer
                    description: "For [sub-tenants](/docs/sub-tenants): number of direct children. `0` for tenants with no sub-tenants."
                    example: 0
                  logo:
                    type: string
                    format: uri
                    nullable: true
                    description: Tenant logo URL.
                    example: https://logo.png
                  timezone:
                    type: string
                    nullable: true
                    description: Tenant timezone. Used as a fallback when the recipient user has no timezone set.
                    example: America/New_York
                  blocked_channels:
                    type: array
                    items:
                      type: string
                    nullable: true
                    description: "Channels turned off for this tenant. Notifications on these channels won't be sent to any user of the tenant — including on [root categories](/docs/notification-category#root-categories) (which users normally can't unsubscribe from) — and users can't override this. If [sub-tenants](/docs/sub-tenants) are used, a block set here also applies to every sub-tenant below and can't be removed lower down."
                    example: ["sms"]
                  embedded_preference_url:
                    type: string
                    format: uri
                    description: URL of your product's preference page.
                    example: https://app.suprsend.com/en/user-settings/notifications
                  hosted_preference_domain:
                    type: string
                    description: Domain of the SuprSend-hosted preference page.
                    example: preferences.suprsend.com
                  primary_color:
                    type: string
                    nullable: true
                    description: Primary brand color, used in the tenant's email header, buttons, and footer. If left empty on create, it's copied from the default tenant.
                    example: "#ff0055"
                  secondary_color:
                    type: string
                    nullable: true
                    description: Secondary brand color. Not part of the default tenant component but can be used in templates as `{{$tenant.secondary_color}}`. If left empty on create, it's copied from the default tenant.
                    example: "#00ff00"
                  tertiary_color:
                    type: string
                    nullable: true
                    description: Tertiary brand color. Not part of the default tenant component but can be used in templates as `{{$tenant.tertiary_color}}`. If left empty on create, it's copied from the default tenant.
                    example: "#0000ff"
                  social_links:
                    type: object
                    description: Tenant's social media URLs.
                    properties:
                      website:
                        type: string
                        example: https://suprsend.com
                      facebook:
                        type: string
                        example: ""
                      linkedin:
                        type: string
                        example: ""
                      x:
                        type: string
                        example: ""
                      instagram:
                        type: string
                        example: ""
                      medium:
                        type: string
                        example: ""
                      discord:
                        type: string
                        example: ""
                      telegram:
                        type: string
                        example: ""
                      youtube:
                        type: string
                        example: ""
                      tiktok:
                        type: string
                        example: ""
                  properties:
                    type: object
                    description: Custom tenant properties (local values only). Inherited values from ancestors are resolved at trigger time.
                    additionalProperties: true
                    example: {"team_size": 42}
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the tenant was last updated.
                    example: "2026-08-27T21:01:35.359787Z"
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "No tenant found for tenant_id tenant",
                    "detail": "No tenant found for tenant_id tenant"
                  }
              schema:
                type: object
                description: error code and message detailing the error
      deprecated: false
    delete:
      summary: Delete Tenant
      security:
        - BearerAuth: []
      description: "Delete a tenant by passing it's ID. Deletion does not affect in-flight notifications, which complete with the settings that were in effect at trigger time. When the tenant has sub-tenants, use `children_action` in the request body to control what happens to them."
      operationId: delete-tenant
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant to delete
          schema:
            type: string
          required: true
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                children_action:
                  type: string
                  enum: [orphan, reassign, delete]
                  description: "Only applies when the tenant has [sub-tenants](/docs/sub-tenants). `orphan` (default) promotes sub-tenants to root tenants. `reassign` moves sub-tenants under `reassign_to` tenant. `delete` deletes every sub-tenant in the subtree. Ignored for tenants with no sub-tenants."
                  default: orphan
                  example: reassign
                reassign_to:
                  type: string
                  description: "Target parent when `children_action = reassign`. Required in that case; must reference an existing tenant. See [sub-tenants](/docs/sub-tenants)."
                  example: acme-corp
      responses:
        '204':
          description: '204 - No Content'
        '400':
          description: '400 - Bad Request. Returned when `reassign_to` is missing on a reassign, sent on a delete, references a non-existent tenant, or when the resulting move would exceed the 5-level limit.'
          content:
            application/json:
              examples:
                MissingReassignTo:
                  value: {
                    "code": 400,
                    "error_code": "error",
                    "type": "ValidationError",
                    "message": "{\"reassign_to\": [\"This field may not be blank.\"]}",
                    "detail": {
                      "reassign_to": [
                        "This field may not be blank."
                      ]
                    }
                  }
              schema:
                type: object
                description: error code and message detailing the error
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "No tenant found for tenant_id 12",
                    "detail": "No tenant found for tenant_id 12"
                  }
              schema:
                type: object
                description: error code and message detailing the error
      deprecated: false
  /v1/tenant/{tenant_id}/properties/:
    patch:
      summary: Update Tenant Properties
      security:
        - BearerAuth: []
      description: |
        Update a tenant's custom `properties` in one of two ways:

        - **Replace entire payload** — send `{ "properties": { ... } }` to replace the entire custom properties object with the payload. Any custom property key not in the payload is removed.
        - **Update individual properties** — send `{ "operations": [ ... ] }` with `$set` and `$unset` operators to add, update, or remove individual property keys without touching the rest. Use `$set` to add new keys or overwrite the value of existing keys. Use `$unset` to delete existing keys.

        Only custom `properties` are affected by this endpoint. Use the [Create / Update Tenants](/reference/create-update-tenants) endpoint to update reserved fields such as branding, `blocked_channels`, or `parent_id`.
      operationId: update-tenant-properties
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant whose properties you want to update
          schema:
            type: string
          required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  title: Replace entire payload
                  description: Replace the entire custom properties object with the payload.
                  required:
                    - properties
                  properties:
                    properties:
                      type: object
                      description: The new custom properties object. Replaces the tenant's existing custom properties in full.
                      additionalProperties: true
                - type: object
                  title: Update individual properties
                  description: Update individual property keys with `$set` / `$unset` operators.
                  required:
                    - operations
                  properties:
                    operations:
                      type: array
                      description: Ordered list of operations to apply.
                      items:
                        type: object
                        properties:
                          $set:
                            type: object
                            description: Add or update these keys in the tenant's custom properties.
                            additionalProperties: true
                          $unset:
                            type: array
                            description: Pass property keys to remove.
                            items:
                              type: string
            examples:
              Replace entire payload:
                summary: Replace entire payload
                value:
                  properties:
                    region: "US"
                    team: "Web"
              Update individual properties:
                summary: Update individual properties
                value:
                  operations:
                    - $set:
                        division: "Engineering"
                    - $unset: ["region"]
      responses:
        '200':
          description: Tenant properties updated. Returns the tenant's identifier fields and its updated `properties` object.
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "id": "tenant-1",
                    "name": "SuprSend UAT",
                    "logo": "https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend_341e8336ac2e1fbeaeae8d92e1b32bc484440f42.png",
                    "properties": {
                      "p1": "Q1"
                    }
                  }
              schema:
                type: object
                description: The tenant with its updated local custom `properties`.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "No tenant found for tenant_id tenant-1",
                    "detail": "No tenant found for tenant_id tenant-1"
                  }
              schema:
                type: object
                description: error code and message detailing the error
      deprecated: false
  /v1/tenant/:
    get:
      summary: List Tenants
      security:
        - BearerAuth: []
      description: API to fetch a paginated list of tenants available in your workspace.
      operationId: get-tenant-list
      parameters:
        - name: limit
          in: query
          description: Number of tenants to return per page.
          schema:
            type: integer
            default: 20
        - name: offset
          in: query
          description: Number of tenants to skip.
          schema:
            type: integer
        - name: parent_id
          in: query
          description: "Returns only direct children of the given tenant."
          required: false
          schema:
            type: string
          example: acme-corp
        - name: ancestor[]
          in: query
          description: "Returns the given tenant and all its descendants at any depth."
          required: false
          schema:
            type: array
            items:
              type: string
          example: ["acme-corp"]
        - name: level[]
          in: query
          description: "Returns tenants at the given level(s). Root = 0, max = 4. Repeat the param to combine levels."
          required: false
          schema:
            type: array
            items:
              type: integer
          example: [0]
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 28,
                      "limit": 20,
                      "offset": 0
                    },
                    "results": [
                      {
                        "id": "acme-corp",
                        "name": "Acme Corp",
                        "tenant_id": "acme-corp",
                        "tenant_name": "Acme Corp",
                        "parent_id": null,
                        "ancestors": [],
                        "level": 0,
                        "children_count": 2,
                        "logo": "https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend-only-logo_c8aa27faef118418e8c5bd7b31a1cafc74e09200.png",
                        "timezone": null,
                        "blocked_channels": null,
                        "embedded_preference_url": "https://app.suprsend.com/en/user-settings/notifications",
                        "hosted_preference_domain": "preferences.suprsend.com",
                        "primary_color": "#ff0000",
                        "secondary_color": null,
                        "tertiary_color": null,
                        "social_links": {
                          "website": "https://suprsend.com",
                          "facebook": "",
                          "linkedin": "",
                          "x": "",
                          "instagram": "",
                          "medium": "",
                          "discord": "",
                          "telegram": "",
                          "youtube": ""
                        },
                        "properties": {},
                        "updated_at": "2026-08-27T20:57:16.935605Z"
                      }]
                    }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 28
                        description: Total number of results returned.
                      limit:
                        type: integer
                        example: 20
                        description: Maximum number of results per page.
                      offset:
                        type: integer
                        example: 0
                        description: offset passed in request
                  results:
                    type: array
                    description: "List of tenants available in the workspace. Tenant JSON is the same shape as the [create/update tenant](/reference/create-update-tenants) response, including the `parent_id`, `ancestors`, `level`, and `children_count` fields introduced with [sub-tenants](/docs/sub-tenants)."
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: "Tenant `id`. Replaces the legacy `tenant_id` field; both are returned."
                          example: acme-corp
                        name:
                          type: string
                          description: "Tenant display name. Replaces the legacy `tenant_name` field; both are returned."
                          example: Acme Corp
                        tenant_id:
                          type: string
                          description: "Will be deprecated in future. Use `id` instead."
                          example: acme-corp
                        tenant_name:
                          type: string
                          description: "Will be deprecated in future. Use `name` instead."
                          example: Awesome Tenant
                        logo:
                          type: string
                          format: uri
                          description: Tenant logo URL.
                          example: https://logo.png
                        timezone:
                          type: string
                          nullable: true
                          description: Tenant timezone. Used as a fallback when the recipient user has no timezone set.
                          example: America/New_York
                        blocked_channels:
                          type: string
                          nullable: true
                          examples:
                            email:
                              summary: "Email channel"
                              value: "email"
                            sms:
                              summary: "SMS channel"
                              value: "sms"
                          description: "Channels turned off for this tenant. Notifications on these channels won't be sent to any user of the tenant — including on [root categories](/docs/notification-category#root-categories) (which users normally can't unsubscribe from) — and users can't override this. If [sub-tenants](/docs/sub-tenants) are used, a block set here also applies to every sub-tenant below and can't be removed lower down."
                        embedded_preference_url:
                          type: string
                          format: uri
                          example: https://app.suprsend.com/en/user-settings/notifications
                          description: URL of your product's preference page.
                        hosted_preference_domain:
                          type: string
                          example: preferences.suprsend.com
                          description: Domain of the SuprSend-hosted preference page.
                        primary_color:
                          type: string
                          description: Primary brand color, used in the tenant's email header, buttons, and footer. If left empty on create, it's copied from the default tenant.
                          example: "#ff0000"
                        secondary_color:
                          type: string
                          nullable: true
                          description: Secondary brand color. Not part of the default tenant component but can be used in templates as `{{$tenant.secondary_color}}`. If left empty on create, it's copied from the default tenant.
                          example: "#ff0000"
                        tertiary_color:
                          type: string
                          nullable: true
                          description: Tertiary brand color. Not part of the default tenant component but can be used in templates as `{{$tenant.tertiary_color}}`. If left empty on create, it's copied from the default tenant.
                          example: "#ff0000"
                        social_links:
                          type: object
                          description: Tenant's social media URLs.
                          properties:
                            website:
                              type: string
                              example: https://suprsend.com
                            facebook:
                              type: string
                              example: ""
                            linkedin:
                              type: string
                              example: ""
                            x:
                              type: string
                              example: ""
                            instagram:
                              type: string
                              example: ""
                            medium:
                              type: string
                              example: ""
                            discord:
                              type: string
                              example: ""
                            telegram:
                              type: string
                              example: ""
                            youtube:
                              type: string
                              example: ""
                        properties:
                          type: object
                          description: Custom tenant properties (local values only). Inherited values from ancestors are resolved at trigger time.
                          additionalProperties: true
                          example: {"region": "US"}
                        parent_id:
                          type: string
                          nullable: true
                          description: "Parent tenant `id` when this tenant is a [sub-tenant](/docs/sub-tenants). `null` for root tenants (including flat tenants that aren't part of a hierarchy)."
                          example: null
                        ancestors:
                          type: array
                          items:
                            type: string
                          description: "For [sub-tenants](/docs/sub-tenants): ancestor tenant `id`s from root down to the immediate parent (excludes the tenant itself). Empty for root and flat tenants."
                          example: []
                        level:
                          type: integer
                          description: "For [sub-tenants](/docs/sub-tenants): depth in the tree. Root = 0, max = 4. Flat tenants always report `0`."
                          example: 0
                        children_count:
                          type: integer
                          description: "For [sub-tenants](/docs/sub-tenants): number of direct children. `0` for tenants with no sub-tenants."
                          example: 2
                        updated_at:
                          type: string
                          format: date-time
                          description: Timestamp when the tenant was last updated.
                          example: "2026-08-27T20:57:16.935605Z"
      deprecated: false
  /v1/subscriber_list/{list_id}/subscriber/remove/:
    post:
      summary: Remove Subscribers from List
      security:
        - BearerAuth: []
      description: API to remove users from a list by passing their distinct_ids.
      operationId: remove-users-from-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list to which user needs to be updated
          required: true
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                distinct_ids:
                  type: array
                  description: Array of subscriber_ids, uniquely identifying the subscribers to be removed from the list.
                  default:
                    - _distinct_id1_
                  items:
                    type: string
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true,
                    "affected_count": 0
                  }
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the operation was successful.
                    example: true
                  affected_count:
                    type: integer
                    description: Number of subscribers affected by the operation.
                    example: 0
                required:
                  - success
                  - affected_count
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "list_id: _list_id_ not found",
                    "detail": "list_id: _list_id_ not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  error_code:
                    type: string
                    description: Machine-readable error code.
                    example: not_found
                  type:
                    type: string
                    description: Error type classification.
                    example: NotFound
                  message:
                    type: string
                    description: Human-readable error message.
                    example: "list_id: _list_id_ not found"
                  detail:
                    type: string
                    description: Detailed error information.
                    example: "list_id: _list_id_ not found"
      deprecated: false
  /v1/subscriber_list/:
    get:
      summary: Get all Lists
      security:
        - BearerAuth: []
      description: API to fetch a paginated list of all lists created in your workspace.
      operationId: get-all-lists
      parameters:
        - name: limit
          in: query
          description: number of results to be returned in API response
          schema:
            type: integer
            default: 20
        - name: offset
          in: query
          description: starting position of tenant list
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 53,
                      "limit": 2,
                      "offset": 0
                    },
                    "results": [
                      {
                        "drafts": null,
                        "source": null,
                        "status": "active",
                        "list_id": "list_01",
                        "list_name": "sample list 01",
                        "list_type": "static_list",
                        "created_at": "2025-04-04T07:33:06.943+00:00",
                        "updated_at": "2025-04-04T07:33:06.943+00:00",
                        "version_id": null,
                        "is_readonly": false,
                        "track_user_exit": false,
                        "list_description": "_some sample description_",
                        "track_user_entry": false,
                        "subscribers_count": 0,
                        "requested_for_delete": false
                      },
                      {
                        "drafts": null,
                        "source": "database_sync",
                        "status": "active",
                        "list_id": "list_02",
                        "list_name": "sample list 02",
                        "list_type": "static_list",
                        "created_at": "2024-12-20T12:09:28.727+00:00",
                        "updated_at": "2025-04-04T07:32:32.127275+00:00",
                        "version_id": null,
                        "is_readonly": false,
                        "track_user_exit": true,
                        "list_description": "_some sample description_",
                        "track_user_entry": true,
                        "subscribers_count": 31,
                        "requested_for_delete": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of lists available.
                        example: 53
                      limit:
                        type: integer
                        description: Maximum number of results per page.
                        example: 2
                      offset:
                        type: integer
                        description: Starting position of the results.
                        example: 0
                  results:
                    type: array
                    items:
                      type: object
                      description: List object similar to list upsert function.
        '401':
          description: '401'
          content:
            application/json:
              examples:
                Result:
                  value: Not Authenticated - could not find Workspace details
              schema:
                type: object
                description: error message details
      deprecated: false
    post:
      summary: Create a List
      security:
        - BearerAuth: []
      description: "API to create / manage lists to send notification to a bulk list of users. To create a [Segment List](/docs/segment-lists) — a list whose membership is driven by a SQL query against your `users` and `events` tables — pass `list_type: dynamic_list` along with the `query`."
      operationId: create-list
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - list_id
              properties:
                list_id:
                  type: string
                  description: "Unique string identifier of the list. Add an id which defines the type of users who are part of the list. Allowed characters: lowercase letters, digits, hyphens, and underscores."
                  pattern: "^[a-z0-9_-]+$"
                  default: _list_id_
                list_name:
                  type: string
                  description: Name of the List. Add a name which defines the type of users in the list.
                  default: _list_name_
                list_description:
                  type: string
                  description: Brief description of the list and the type of users in it.
                  default: _some sample description_
                list_type:
                  type: string
                  description: Type of the list. Use `dynamic_list` to create a [Segment List](/docs/segment-lists) whose membership is driven by a SQL query. Defaults to `static_list`.
                  enum: ["static_list", "dynamic_list"]
                  default: "static_list"
                query:
                  type: string
                  description: "SQL query defining the segment. **Required when `list_type: dynamic_list`.** Must return a `distinct_id` column and reference only the `users` and `events` tables. See the [Segment Lists doc](/docs/segment-lists) for the full dialect reference."
                  example: "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500"
                is_enabled:
                  type: boolean
                  description: Only applies to `dynamic_list`. When `true`, the segment starts syncing immediately after create. When `false`, the query is saved but the segment does not refresh until you enable it.
                  default: true
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Static list:
                  value: {
                    "list_id": "product_updates",
                    "list_name": "Product Update",
                    "list_description": "Users subscribed to the newsletter",
                    "list_type": "static_list",
                    "subscribers_count": 3,
                    "source": "database_sync",
                    "is_readonly": false,
                    "status": "active",
                    "track_user_entry": false,
                    "track_user_exit": false,
                    "requested_for_delete": false,
                    "created_at": "2024-02-21T19:10:01.906000Z",
                    "updated_at": "2025-04-04T07:25:43.186475Z",
                    "drafts": null
                  }
                Segment (dynamic) list:
                  value: {
                    "list_id": "high_ltv_q1",
                    "list_name": "High LTV Q1",
                    "list_description": "Users with lifetime value >= 2500",
                    "list_type": "dynamic_list",
                    "subscribers_count": 30,
                    "source": "suprsend",
                    "is_readonly": false,
                    "is_enabled": true,
                    "query": "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500",
                    "status": "active",
                    "track_user_entry": false,
                    "track_user_exit": false,
                    "requested_for_delete": false,
                    "created_at": "2026-07-14T13:25:07.883000Z",
                    "updated_at": "2026-07-14T13:28:33.405495Z",
                    "drafts": null,
                    "sync_task": {
                      "id": "01KXGCBW5W29TC5FJ47JPA982W",
                      "name": "high_ltv_q1-01KXGCBW5G9WA1D6Y6081KGCMF",
                      "is_enabled": true,
                      "auto_refresh": true,
                      "refresh_interval": null,
                      "draft_version": null,
                      "active_version": {
                        "id": "st_v_01KXGCR07KCG2PS48PRYJ5EPQP",
                        "query": "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500",
                        "version_no": 1,
                        "ai_description": "Users whose lifetime value is at least 2500."
                      }
                    }
                  }
              schema:
                type: object
                properties:
                  list_id:
                    type: string
                    description: Unique identifier of the list.
                    example: "product_updates"
                  list_name:
                    type: string
                    description: Name of the list.
                    example: "Product Update"
                  list_description:
                    type: string
                    description: Brief description of the list.
                    example: "Users subscribed to the newsletter"
                  list_type:
                    type: string
                    description: Type of the list.
                    enum: ["static_list", "dynamic_list"]
                  subscribers_count:
                    type: integer
                    description: number of users in the list
                  source:
                    type: string
                    description: source info on how the list is updated
                    example: "database_sync"
                  is_readonly:
                    type: boolean
                    description: Indicates whether the list is read-only.
                    example: false
                  is_enabled:
                    type: boolean
                    description: For `dynamic_list` only. Whether the segment is actively refreshing.
                    example: true
                  query:
                    type: string
                    description: For `dynamic_list` only. The committed SQL query that defines the segment.
                    example: "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500"
                  status:
                    type: string
                    description: Current status of the list (active or draft).
                    example: "active"
                  track_user_entry:
                    type: boolean
                    description: Event `$USER_ENTERED_LIST - <list_id>` is generated when user is added this list. Use this to trigger workflow on user entry.
                  track_user_exit:
                    type: boolean
                    description: Event `$USER_EXITED_LIST - <list_id>` is generated when user is removed from this list. Use this to trigger workflow on user exit.
                  requested_for_delete:
                    type: boolean
                    description: Indicates whether the list has been requested for deletion.
                    example: false
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the list was created.
                    example: "2024-02-21T19:10:01.906000Z"
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the list was last updated.
                    example: "2025-04-04T07:25:43.186475Z"
                  drafts:
                    type: string
                    nullable: true
                    description: would show the draft list created to replace list users.
                  sync_task:
                    type: object
                    nullable: true
                    description: For `dynamic_list` only. Metadata about the sync task that runs the segment query, including the currently active version and any uncommitted draft.
                    properties:
                      id:
                        type: string
                        description: Sync task identifier.
                      name:
                        type: string
                        description: Sync task name (derived from `list_id`).
                      is_enabled:
                        type: boolean
                        description: Whether the sync task is currently running.
                      auto_refresh:
                        type: boolean
                        description: Whether the segment refreshes automatically as data changes.
                      refresh_interval:
                        type: string
                        nullable: true
                        description: Refresh cadence, if configured.
                      draft_version:
                        type: object
                        nullable: true
                        description: The uncommitted draft version, if any. Populated when a new query has been saved but not yet committed.
                        properties:
                          id:
                            type: string
                            description: Unique identifier of the draft version.
                          query:
                            type: string
                            description: SQL query text saved in this draft.
                          ai_description:
                            type: string
                            nullable: true
                            description: AI-generated natural-language summary of what the draft query matches.
                      active_version:
                        type: object
                        nullable: true
                        description: The currently live (committed) version of the segment query that drives list membership.
                        properties:
                          id:
                            type: string
                            description: Unique identifier of the active version.
                          query:
                            type: string
                            description: SQL query text currently committed and used to compute list membership.
                          version_no:
                            type: integer
                            description: Monotonically increasing version number of the active query. Increments each time a new version is committed.
                          ai_description:
                            type: string
                            nullable: true
                            description: AI-generated natural-language summary of what the active query matches.
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 400,
                    "error_code": "error",
                    "type": "ValidationError",
                    "message": "{\"list_id\": [\"This field may not be blank.\"]}",
                    "detail": {
                      "list_id": [
                        "This field may not be blank."
                      ]
                    }
                  }
              schema:
                type: object
                description: error code and related message detailing out the error
      deprecated: false
  /v1/subscriber_list/~/dry_run/:
    post:
      summary: Dry-run a segment query (sample rows)
      security:
        - BearerAuth: []
      description: Preview the rows a [Segment List](/docs/segment-lists) SQL query would match, without committing it to a list. Returns up to the top 10 matched rows for the columns selected. Use this to spot-check a query before creating a Segment List or committing a new version.
      operationId: segment-dry-run
      x-codeSamples:
        - lang: cURL
          label: Dry-run (sample rows)
          source: |
            curl -X POST "https://hub.suprsend.com/v1/subscriber_list/~/dry_run/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "query": "SELECT distinct_id, active_emails FROM users LIMIT 40"
              }'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - query
              properties:
                query:
                  type: string
                  description: The SQL query to preview. Must return a `distinct_id` column and reference only the `users` and `events` tables. See the [Segment Lists doc](/docs/segment-lists) for the dialect, available columns, and query rules.
                  example: "SELECT distinct_id, active_emails FROM users LIMIT 40"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "data": [
                      { "distinct_id": "01KN7Q7NS31C01S6CR4Y9EDKPX", "active_emails": [] },
                      { "distinct_id": "01KN7Q7NS31C01S6CR4Y9EDKPT", "active_emails": [] },
                      { "distinct_id": "01KRWTYB7MX8B7HTK619XHMHJK", "active_emails": [] }
                    ]
                  }
              schema:
                type: object
                properties:
                  data:
                    type: array
                    description: Up to the top 10 matched rows, each containing `distinct_id` and any additional columns you selected.
                    items:
                      type: object
                      properties:
                        distinct_id:
                          type: string
                          description: The user identifier.
                      additionalProperties: true
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Schema error:
                  value: {
                    "code": 400,
                    "error_code": "error",
                    "type": "ValidationError",
                    "message": "{\"query\": \"Schema error: No field named name. Valid fields are users.distinct_id, users.created_at, users.updated_at, users.language, users.locale, users.timezone, users.user_properties, users.active_channels, users.active_emails, users.active_phone_numbers\"}",
                    "detail": {
                      "query": "Schema error: No field named name. Valid fields are users.distinct_id, users.created_at, users.updated_at, users.language, users.locale, users.timezone, users.user_properties, users.active_channels, users.active_emails, users.active_phone_numbers"
                    }
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  error_code:
                    type: string
                    example: "error"
                  type:
                    type: string
                    example: "ValidationError"
                  message:
                    type: string
                    description: Human-readable error message. Common causes — column doesn't exist, missing `distinct_id` in the SELECT, referencing a table other than `users` or `events`, or missing a bounded time filter on `events.requested_at`.
                  detail:
                    type: object
                    description: Structured error detail keyed by field.
      deprecated: false
  /v1/subscriber_list/~/dry_run/count/:
    post:
      summary: Dry-run a segment query (count only)
      security:
        - BearerAuth: []
      description: Return the total number of users a [Segment List](/docs/segment-lists) SQL query would match, without returning the rows. Use this when you only need to size the audience.
      operationId: segment-dry-run-count
      x-codeSamples:
        - lang: cURL
          label: Dry-run (count only)
          source: |
            curl -X POST "https://hub.suprsend.com/v1/subscriber_list/~/dry_run/count/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "query": "SELECT distinct_id FROM users WHERE user_properties ->> '\''plan'\'' = '\''enterprise'\''"
              }'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - query
              properties:
                query:
                  type: string
                  description: The SQL query to count. Must return a `distinct_id` column and reference only the `users` and `events` tables.
                  example: "SELECT distinct_id FROM users WHERE user_properties ->> 'plan' = 'enterprise'"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "count": 4812
                  }
              schema:
                type: object
                properties:
                  count:
                    type: integer
                    description: Number of distinct users matched by the query.
                    example: 4812
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Schema error:
                  value: {
                    "code": 400,
                    "error_code": "error",
                    "type": "ValidationError",
                    "message": "{\"query\": \"Schema error: No field named name. Valid fields are users.distinct_id, users.created_at, users.updated_at, users.language, users.locale, users.timezone, users.user_properties, users.active_channels, users.active_emails, users.active_phone_numbers\"}",
                    "detail": {
                      "query": "Schema error: No field named name. Valid fields are users.distinct_id, users.created_at, users.updated_at, users.language, users.locale, users.timezone, users.user_properties, users.active_channels, users.active_emails, users.active_phone_numbers"
                    }
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  error_code:
                    type: string
                    example: "error"
                  type:
                    type: string
                    example: "ValidationError"
                  message:
                    type: string
                    description: Human-readable error message.
                  detail:
                    type: object
                    description: Structured error detail keyed by field.
      deprecated: false
  /{workspace_key}/trigger/:
    post:
      summary: Dynamic Workflow Trigger
      security:
        - BearerAuth: []
      description: API to dynamically create and trigger a single step workflow.
      operationId: dynamic-workflow-trigger
      parameters:
        - name: workspace_key
          in: path
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - template
                - notification_category
                - users
              properties:
                name:
                  type: string
                  description: Unique name of the workflow. The workflow name should be easily identifiable for your reference at a later stage. You can see workflow-related analytics on the workflow page (how many notifications were sent, delivered, clicked or interacted).
                  default: _workflow_name_
                template:
                  type: string
                  description: Unique slug of the template created on SuprSend dashboard. You can get this by clicking on the clipboard icon next to the Template name on SuprSend templates page.
                  default: _template_slug_
                notification_category:
                  type: string
                  description: Used to apply user category level [preferences]("/docs/user-preferences") on notification trigger.
                  default: transactional
                users:
                  type: array
                  description: Array object of target users.
                  items:
                    properties:
                      distinct_id:
                        type: string
                        description: unique identifier of the user
                        default: _distinct_id_
                      $channels:
                        type: array
                        description: send notification on selected channels in user profile. Following channel keys can be used - email, sms, whatsapp, androidpush, iospush, slack, webpush
                        default: []
                        items:
                          type: string
                      $email:
                        type: array
                        description: To trigger notification on a particular email
                        default: []
                        items:
                          type: string
                      $sms:
                        type: array
                        description: Send SMS on a particular number.
                        default: []
                        items:
                          type: string
                      $whatsapp:
                        type: array
                        description: Send Whatsapp on a particular number.
                        default: []
                        items:
                          type: string
                      $androidpush:
                        type: array
                        description: Send androidpush on the given push token
                        items:
                          type: string
                      $iospush:
                        type: array
                        description: Send iOSpush on the given push token
                        items:
                          type: string
                      $slack:
                        type: array
                        description: Slack channel configuration
                        items:
                          oneOf:
                            - type: object
                              title: "user email_id"
                              required: [email, access_token]
                              properties:
                                email:
                                  type: string
                                  format: email
                                  description: User email address
                                  example: "user@example.com"
                                access_token:
                                  type: string
                                  description: Slack bot access token
                                  example: "xoxb-XXXXXXXX"
                            - type: object
                              title: "user member_id"
                              required: [user_id, access_token]
                              properties:
                                user_id:
                                  type: string
                                  description: Slack user ID (U/WXXXXXXXX format)
                                  example: "U/WXXXXXXXX"
                                access_token:
                                  type: string
                                  description: Slack bot access token
                                  example: "xoxb-XXXXXXXX"
                            - type: object
                              title: "Slack channel"
                              required: [channel, access_token]
                              properties:
                                channel:
                                  type: string
                                  description: Slack channel ID (CXXXXXXXX format)
                                  example: "CXXXXXXXX"
                                access_token:
                                  type: string
                                  description: Slack bot access token
                                  example: "xoxb-XXXXXX"
                            - type: object
                              title: "Using incoming webhook"
                              required: [incoming_webhook]
                              properties:
                                incoming_webhook:
                                  type: object
                                  required: [url]
                                  properties:
                                    url:
                                      type: string
                                      format: uri
                                      description: Slack incoming webhook URL
                                      example: "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"
                      $ms_teams:
                        type: array
                        description: Microsoft Teams channel configuration
                        items:
                          oneOf:
                            - type: object
                              title: "MS Teams using conversation ID"
                              required: [tenant_id, service_url, conversation_id]
                              properties:
                                tenant_id:
                                  type: string
                                  description: Microsoft Teams tenant ID
                                  example: "c1981ab2-9aaf-xxxx-xxxx"
                                service_url:
                                  type: string
                                  format: uri
                                  description: Microsoft Teams service URL
                                  example: "https://smba.trafficmanager.net/amer"
                                conversation_id:
                                    type: string
                                    description: Microsoft Teams conversation ID
                                    example: "19:c1524d7c-a06f-456f-8abe-xxxx"
                            - type: object
                              title: "MS Teams using user ID"
                              required: [tenant_id, service_url, user_id]
                              properties:
                                tenant_id:
                                  type: string
                                  description: Microsoft Teams tenant ID
                                  example: "c1981ab2-9aaf-xxxx-xxxx"
                                service_url:
                                  type: string
                                  format: uri
                                  description: Microsoft Teams service URL
                                  example: "https://smba.trafficmanager.net/amer"
                                user_id:
                                  type: string
                                  description: Microsoft Teams user ID
                                  example: "29:1nsLcmJ2RKtYH6Cxxxx-xxxx"
                            - type: object
                              title: "MS Teams using incoming webhook"
                              required: [incoming_webhook]
                              properties:
                                incoming_webhook:
                                  type: object
                                  required: [url]
                                  properties:
                                    url:
                                      type: string
                                      format: uri
                                      description: Microsoft Teams incoming webhook URL
                                      example: "https://wnk1z.webhook.office.com/webhookb2/XXXXXXXXX"
                    required:
                      - distinct_id
                    type: object
                data:
                  type: object
                  description: variable data required to render dynamic template content or workflow properties like dynamic delay or channel override in send node.
                  properties:
                    $attachments:
                      type: array
                      description: Use this key to pass email attachment in the trigger. You can either pass attachment as a public URL or as a base64-encoded file (limit < 50KB).
                      items:
                        oneOf:
                          - type: object
                            title: "publicly accessible URL"
                            description: Pass file as **publicly accessible URL** (No limit on file size)
                            required: [url]
                            properties:
                              url:
                                type: string
                                format: uri
                                description: Publicly accessible URL of the file
                                example: "https://bitcoincore.org/bitcoin.pdf"
                              filename:
                                type: string
                                description: Filename to be shown in email
                                example: "billing.pdf"
                              ignore_if_error:
                                type: boolean
                                description: Ignore the attachment if it fails to load

                          - type: object
                            title: "base64-encoded file"
                            description: Pass file as a **base-64 file** (supported limit < 50KB)
                            required: [data]
                            properties:
                              data:
                                type: string
                                description: Base64-encoded content of the file
                              filename:
                                type: string
                                description: Filename to be shown in email
                              contentType:
                                type: string
                                example: application/pdf
                  additionalProperties:
                    type: string
                delivery:
                  type: object
                  description: delivery instructions for the workflow. You can set [Smart Delivery](https://docs.suprsend.com/docs/smart-delivery) preference by setting "smart":true
                  properties:
                    smart:
                      type: boolean
                      description: You can enable smart delivery by setting it true
                      default: false
                    success:
                      type: string
                      description: Success event for stopping further notification in case smart is set to true. You can set notification status like delivery, interaction or custom success event
                      default: seen
                    time_to_live:
                      type: string
                      description: |
                        Time window to define delay between subsequent channel trigger in case of smart delivery.
                        Delay = `time_to_live / (number_of_channels - 1)`. Format - `XXdXXhXXmXXs` or if its number (n) then delay is in seconds (n)
                    mandatory_channels:
                      type: array
                      description: Channels on which notification has to be sent immediately in case of smart delivery. Following channel keys can be used - email, sms, whatsapp, androidpush, iospush, slack, webpush
                      items:
                        type: string
                delay:
                  type: string
                  description: Workflow will be halted for the time mentioned in delay, and become active once the delay period is over. Format - `XXdXXhXXmXXs` or if its number (n) then delay is in seconds (n)
                trigger_at:
                  type: string
                  description: Trigger workflow on a specific date-time. Format - date string in ISO 8601 e.g. "2022-08-27T20:14:51.643Z"
                  format: date
                tenant_id:
                  type: string
                  description: string identifier of the tenant this workflow is associated with
                $idempotency_key:
                  type: string
                  description: Unique identifier of the request (deduplicates request for 24hrs)
      x-codeSamples:
        - lang: cURL
          label: Dynamic Workflow Trigger
          source: |
            curl -X POST "https://hub.suprsend.com/{workspace_key}/dynamic-workflow/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "name": "Welcome Email Workflow",
                "template": "welcome-email-template",
                "notification_category": "transactional",
                "users": [
                  {
                    "distinct_id": "user123",
                    "$email": ["user@example.com"],
                    "$channels": ["email"]
                  }
                ],
                "data": {
                  "user_name": "John Doe",
                  "welcome_message": "Welcome to our platform!"
                }
              }'
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: Accepted - OK
              schema:
                type: string
                example: "Accepted - OK"
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "status": "fail",
                    "message": "BAD REQUEST"
                  }
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "fail"
                    description: "Indicates the failure status of the request."
                  message:
                    type: string
                    example: "BAD REQUEST"
                    description: "Describes the reason for the failure."
      deprecated: false
  /v1/user/{distinct_id}/preference/category/:
    get:
      summary: All Categories
      security:
        - BearerAuth: []
      description: API to fetch user preferences across all categories.
      operationId: get-user-preference-all-categories
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be fetched
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
        - name: show_opt_out_channels
          in: query
          description: set this flag to `true` if you want to fetch channel list for opt-out categories.
          schema:
            type: boolean
            default: false
        - name: tags
          in: query
          description: >
            Filter preference categories with tags assigned to them. Used to filter preference categories relevant to the user on UI based on their roles, department or teams.

            You can apply single tag filter like `tags=tag1` or build nested conditions using logical operators - `and`, `or`, `not`, `exists`.


            Example:

            ```

            tags=admin

            tags={"or":[{"and":["admin","sales"]},{"and":["admin","manager"]}]}

            tags={"not":"admin"}

            tags={"exists":true}
          schema:
            type: string
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file. 
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 12,
                      "limit": 10,
                      "offset": 0
                    },
                    "results": [
                      {
                        "name": "Newsletter",
                        "category": "newsletter",
                        "description": "Send me updates on new product updates",
                        "original_preference": null,
                        "preference": "opt_in",
                        "is_editable": false,
                        "channels": [
                          {
                            "channel": "email",
                            "preference": "opt_in",
                            "is_editable": false
                          },
                          {
                            "channel": "ms_teams",
                            "preference": "opt_in",
                            "is_editable": false
                          }
                        ]
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 12
                      limit:
                        type: integer
                        example: 10
                      offset:
                        type: integer
                        example: 0
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          description: Display name of the notification category.
                          type: string
                          example: Newsletter
                        category:
                          description: Slug of the notification category.
                          type: string
                          example: newsletter
                        description:
                          description: Description of the notification category.
                          type: string
                          example: Send me updates on new product updates
                        original_preference:
                          type: string
                          description: "default preference of the category"
                          nullable: true
                          example: null
                        preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          example: opt_in
                          description: "updated user preference of the category"
                        is_editable:
                          type: boolean
                          description: "false when category default preference is set to `can't unsubscribe`"
                          example: false
                        channels:
                          type: array
                          description: "channel level preference in the category"
                          items:
                            type: object
                            properties:
                              channel:
                                type: string
                                description: channel name
                                example: email
                              preference:
                                type: string
                                description: user preference for this channel (opt_in, opt_out)
                                example: opt_in
                              is_editable:
                                type: boolean
                                description: whether the user can edit this channel preference
                                example: false
                        digest_schedule_options:
                          type: object
                          nullable: true
                          description: All digest schedule options configured on the category, with the recipient's current selection. `null` if digest schedule is not enabled on the category.
                          properties:
                            options:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    type: string
                                    description: Display label shown to the recipient for this option.
                                  frequency:
                                    type: string
                                    description: Frequency of the digest schedule.
                                    enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    type: object
                                    description: Time of day to send the digest, with its edit policy and the recipient's override.
                                    properties:
                                      edit_policy:
                                        type: string
                                        enum: ["locked", "editable"]
                                        description: "`editable` means the recipient can change this value; `locked` means it is fixed."
                                      default_value:
                                        type: string
                                        description: "Default time in HH:MM (24-hour) format."
                                      value:
                                        type: string
                                        nullable: true
                                        description: Recipient's overridden value, if any.
                                  weekdays:
                                    type: object
                                    description: Days of the week to send on (for `weekly` frequency), with edit policy and recipient override.
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: string
                                      value:
                                        type: array
                                        nullable: true
                                        items:
                                          type: string
                                  monthdays:
                                    type: object
                                    description: Days of the month to send on (for `monthly` frequency), with edit policy and recipient override.
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            pos:
                                              description: "Position in the month (1-31; use a negative value to count from the end)."
                                              type: integer
                                            day:
                                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                              type: string
                                      value:
                                        type: array
                                        nullable: true
                                        items:
                                          type: object
                                  dtstart:
                                    type: object
                                    description: Start datetime from which the recurring schedule is calculated, with edit policy and recipient override.
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                        format: date-time
                                      value:
                                        type: string
                                        nullable: true
                                  is_default:
                                    type: boolean
                                    description: Whether this option is the category default.
                                  is_user_selected:
                                    type: boolean
                                    description: Whether the recipient has selected this option.
                        digest_schedule:
                          type: object
                          nullable: true
                          description: The recipient's currently active digest schedule, resolved in order recipient selection -> tenant default -> category default. `null` if digest schedule is not enabled on the category.
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                              enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              type: string
                              description: "Resolved time in HH:MM (24-hour) format."
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: array
                              items:
                                type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: array
                              items:
                                type: object
                                properties:
                                  pos:
                                    description: "Position in the month (1-31; use a negative value to count from the end)."
                                    type: integer
                                  day:
                                    description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                    type: string
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                            is_user_selected:
                              type: boolean
                        properties:
                          type: array
                          nullable: true
                          description: Category condition properties with the recipient's overrides. Referenced in workflows as `$category.properties.<key>`.
                          items:
                            type: object
                            properties:
                              key:
                                description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                type: string
                              label:
                                type: string
                                description: Display label for the property.
                              value_type:
                                description: "Data type of the property value."
                                type: string
                                enum: ["integer", "string", "string_choice", "list_choice", "string_dynamic", "list_dynamic"]
                              default_value:
                                nullable: true
                                description: Default value applied when the recipient has not set a value.
                              is_optional:
                                description: "Whether this property is optional."
                                type: boolean
                              edit_policy:
                                type: string
                                enum: ["locked", "editable"]
                                description: "`editable` means the recipient can override the value; `locked` means it is fixed."
                              is_overridden:
                                type: boolean
                                description: Whether the recipient has overridden the default value.
                              value:
                                nullable: true
                                description: Recipient-overridden value, if any.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "user [distinct_id: 'user1'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "user [distinct_id: 'user1'] not found"          
      deprecated: false
  /v1/subscriber_list/{list_id}/subscriber/add/:
    post:
      summary: Add Users to List
      security:
        - BearerAuth: []
      description: API to add users to the list by passing their distinct_ids.
      operationId: add-subscribers-to-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list to which user needs to be updated
          required: true
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                distinct_ids:
                  type: array
                  description: Array of subscriber_ids, uniquely identifying the subscribers to be added to the list.
                  default:
                    - _distinct_id1_
                  items:
                    type: string
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true,
                    "affected_count": 0
                  }
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the operation was successful.
                    example: true
                  affected_count:
                    type: integer
                    description: Number of subscribers affected by the operation.
                    example: 2
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "list_id: _list_id_ not found",
                    "detail": "list_id: _list_id_ not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  error_code:
                    type: string
                    description: Machine-readable error code.
                    example: not_found
                  type:
                    type: string
                    description: Error type classification.
                    example: NotFound
                  message:
                    type: string
                    description: Human-readable error message.
                    example: "list_id: _list_id_ not found"
                  detail:
                    type: string
                    description: Detailed error information.
                    example: "list_id: _list_id_ not found"
      deprecated: false
  /v1/subscriber_list/{list_id}/:
    get:
      summary: Get List configuration
      security:
        - BearerAuth: []
      description: "API to fetch list metadata like list type, count, source, and status. Doesn't include users in the list. For [Segment Lists](/docs/segment-lists) (`list_type: dynamic_list`), the response also includes the committed `query` and the `sync_task` block with the live version."
      operationId: get-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list.
          required: true
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Static list:
                  value: {
                    "list_id": "product_updates",
                    "list_name": "Product Update",
                    "list_description": "Users subscribed to the newsletter",
                    "list_type": "static_list",
                    "subscribers_count": 3,
                    "source": "database_sync",
                    "is_readonly": false,
                    "status": "active",
                    "track_user_entry": false,
                    "track_user_exit": false,
                    "requested_for_delete": false,
                    "created_at": "2024-02-21T19:10:01.906000Z",
                    "updated_at": "2025-04-04T07:25:43.186475Z",
                    "drafts": null
                  }
                Segment (dynamic) list:
                  value: {
                    "list_id": "high_ltv_q1",
                    "list_name": "High LTV Q1",
                    "list_description": "Users with lifetime value >= 2500",
                    "list_type": "dynamic_list",
                    "subscribers_count": 30,
                    "source": "suprsend",
                    "is_readonly": false,
                    "is_enabled": true,
                    "query": "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500",
                    "status": "active",
                    "track_user_entry": false,
                    "track_user_exit": false,
                    "requested_for_delete": false,
                    "created_at": "2026-07-14T13:25:07.883000Z",
                    "updated_at": "2026-07-14T13:28:33.405495Z",
                    "drafts": null,
                    "sync_task": {
                      "id": "01KXGCBW5W29TC5FJ47JPA982W",
                      "name": "high_ltv_q1-01KXGCBW5G9WA1D6Y6081KGCMF",
                      "is_enabled": true,
                      "auto_refresh": true,
                      "refresh_interval": null,
                      "draft_version": null,
                      "active_version": {
                        "id": "st_v_01KXGCR07KCG2PS48PRYJ5EPQP",
                        "query": "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500",
                        "version_no": 1,
                        "ai_description": "Users whose lifetime value is at least 2500."
                      }
                    }
                  }
              schema:
                type: object
                properties:
                  list_id:
                    type: string
                    description: Unique identifier of the list.
                    example: "product_updates"
                  list_name:
                    type: string
                    description: Name of the list.
                    example: "Product Update"
                  list_description:
                    type: string
                    description: Brief description of the list.
                    example: "Users subscribed to the newsletter"
                  list_type:
                    type: string
                    description: Type of the list.
                    enum: ["static_list", "dynamic_list"]
                  subscribers_count:
                    type: integer
                    description: number of users in the list
                  source:
                    type: string
                    description: source info on how the list is updated
                    example: "database_sync"
                  is_readonly:
                    type: boolean
                    description: Indicates whether the list is read-only.
                    example: false
                  is_enabled:
                    type: boolean
                    description: For `dynamic_list` only. Whether the segment is actively refreshing.
                    example: true
                  query:
                    type: string
                    description: For `dynamic_list` only. The committed SQL query that defines the segment.
                    example: "SELECT distinct_id FROM users WHERE CAST(user_properties ->> 'lifetime_value' AS DOUBLE PRECISION) >= 2500"
                  status:
                    type: string
                    description: Current status of the list (active or draft).
                    example: "active"
                  track_user_entry:
                    type: boolean
                    description: Event `$USER_ENTERED_LIST - <list_id>` is generated when user is added this list. Use this to trigger workflow on user entry.
                  track_user_exit:
                    type: boolean
                    description: Event `$USER_EXITED_LIST - <list_id>` is generated when user is removed from this list. Use this to trigger workflow on user exit.
                  requested_for_delete:
                    type: boolean
                    description: Indicates whether the list has been requested for deletion.
                    example: false
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the list was created.
                    example: "2024-02-21T19:10:01.906000Z"
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the list was last updated.
                    example: "2025-04-04T07:25:43.186475Z"
                  drafts:
                    type: string
                    nullable: true
                    description: would show the draft list created to replace list users.
                  sync_task:
                    type: object
                    nullable: true
                    description: For `dynamic_list` only. Metadata about the sync task that runs the segment query, including the currently active version and any uncommitted draft.
                    properties:
                      id:
                        type: string
                        description: Sync task identifier.
                      name:
                        type: string
                        description: Sync task name (derived from `list_id`).
                      is_enabled:
                        type: boolean
                        description: Whether the sync task is currently running.
                      auto_refresh:
                        type: boolean
                        description: Whether the segment refreshes automatically as data changes.
                      refresh_interval:
                        type: string
                        nullable: true
                        description: Refresh cadence, if configured.
                      draft_version:
                        type: object
                        nullable: true
                        description: The uncommitted draft version, if any. Populated when a new query has been saved but not yet committed.
                        properties:
                          id:
                            type: string
                            description: Unique identifier of the draft version.
                          query:
                            type: string
                            description: SQL query text saved in this draft.
                          ai_description:
                            type: string
                            nullable: true
                            description: AI-generated natural-language summary of what the draft query matches.
                      active_version:
                        type: object
                        nullable: true
                        description: The currently live (committed) version of the segment query that drives list membership.
                        properties:
                          id:
                            type: string
                            description: Unique identifier of the active version.
                          query:
                            type: string
                            description: SQL query text currently committed and used to compute list membership.
                          version_no:
                            type: integer
                            description: Monotonically increasing version number of the active query. Increments each time a new version is committed.
                          ai_description:
                            type: string
                            nullable: true
                            description: AI-generated natural-language summary of what the active query matches.
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "list_id: list_id_01 not found",
                    "detail": "list_id: list_id_01 not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  error_code:
                    type: string
                    description: Machine-readable error code.
                    example: "not_found"
                  type:
                    type: string
                    description: Error type classification.
                    example: "NotFound"
                  message:
                    type: string
                    description: Human-readable error message.
                    example: "list_id: list_id_01 not found"
                  detail:
                    type: string
                    description: Detailed error information.
                    example: "list_id: list_id_01 not found"
                required:
                  - code
                  - error_code
                  - type
                  - message
                  - detail      
      deprecated: false
  /{workspace_key}/broadcast/:
    post:
      summary: Trigger Broadcast
      security:
        - BearerAuth: []
      description: API to trigger broadcast notification to list users.
      operationId: trigger-broadcast
      x-codeSamples:
        - lang: cURL
          label: Trigger Broadcast
          source: |
            curl -X POST "https://hub.suprsend.com/{workspace_key}/broadcast/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "list_id": "_list_id_",
                "template": "_template_slug_",
                "notification_category": "transactional",
                "data": {
                  "user_name": "John Doe",
                  "product_name": "Premium Plan"
                }
              }'
      parameters:
        - name: workspace_key
          in: path
          description: unique identifier of your workspace
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - list_id
                - template
                - notification_category
              properties:
                list_id:
                  type: string
                  description: unique identifier to user list that you want to send broadcast messages to.
                  pattern: "^[a-z0-9_-]+$"
                  default: _list_id_
                template:
                  type: string
                  description: Unique slug name of the template created on SuprSend dashboard. You can get this by clicking on the clipboard icon next to the Template name on SuprSend templates page.
                  default: _template_slug_
                notification_category:
                  type: string
                  description: Category in which your notification belongs. You can understand more about them in the [Notification Category](https://docs.suprsend.com/docs/notification-category) documentation
                  default: transactional
                channels:
                  type: array
                  description: If set, broadcast will be sent only on the channels defined here irrespective of communication channels present in user profile.
                  items:
                    type: string
                data:
                  type: object
                  properties: {}
                  description: Mock data to replace the template variables.
                delay:
                  type: string
                  description: Broadcast will be halted for the time mentioned in delay, and become active once the delay period is over. Format - `XXdXXhXXmXXs` or if its number (n) then delay is in seconds (n)
                trigger_at:
                  type: string
                  description: Trigger broadcast on a specific date-time. Format - date string in ISO 8601 e.g. "2022-08-27T20:14:51.643Z"
                  format: date
                tenant_id:
                  type: string
                  description: string identifier of the tenant this broadcast is associated with
      responses:
        '202':
          description: '202 - Accepted'
          content:
            application/json:
              examples:
                Result:
                  value: Ok
              schema:
                type: object
                description: Confirmation that the broadcast request was accepted for processing.
                properties:
                  message:
                    type: string
                    description: Status message indicating the broadcast was accepted.
                    example: "Accepted - OK"
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value: BAD REQUEST
              schema:
                type: string
                description: Error in case the API request is missing mandatory fields.
      deprecated: false
  /v1/user/{distinct_id}/preference/channel_preference/:
    get:
      summary: All Channels
      security:
        - BearerAuth: []
      description: API to retrieve user preferences for all channels.
      operationId: get-user-preference-channel
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be fetched
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "channel_preferences": [
                      {
                        "channel": "androidpush",
                        "is_restricted": false
                      },
                      {
                        "channel": "email",
                        "is_restricted": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          description: channel name
                          example: "androidpush"
                        is_restricted:
                          type: boolean
                          description: True means notification will be sent in categories where this channel is marked as mandatory channel. False means opt_in on channel.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "user [distinct_id: 'user1'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "user [distinct_id: 'user1'] not found"
      deprecated: false
    patch:
      summary: Overall Channel level
      security:
        - BearerAuth: []
      description: API to update user preferences across all channels.
      operationId: update-user-preference-channel
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be fetched
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channel_preferences:
                  type: array
                  description: Use this to update channel level user preferences. Set `is_restricted - true` if the channel is opted_out by the user. This will only send critical notifications to the user which can't be opted out
                  items:
                    properties:
                      channel:
                        type: string
                        description: Add channel as `email`, `inbox`, `sms`, `whatsapp`, `androidpush`, `slack`, `iospush`, `webpush`
                        default: email
                      is_restricted:
                        type: boolean
                        description: set `is_restricted = true` if user wants to receive notification in mandatory categories on this channel. Mandatory categories are `can't unsubscribe` categories and the above channel is added as `mandatory channel` in that category
                        default: false
                    type: object
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "channel_preferences": [
                      {
                        "channel": "email",
                        "is_restricted": true
                      },
                      {
                        "channel": "inbox",
                        "is_restricted": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          example: "email"
                        is_restricted:
                          type: boolean
                          example: "true"
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value:  {
                    "code": 400,
                    "detail": {
                      "channel_preferences[0].channel": "must be one of [\"sms\", \"email\", \"androidpush\" \"iospush\", \"webpush\", \"inbox\", \"whatsapp\", \"slack\", \"ms_teams\"]"
                    },
                    "message": "{\"channel_preferences[0].channel\": must be one of [\"sms\", \"email\", \"androidpush\" \"iospush\", \"webpush\", \"inbox\", \"whatsapp\", \"slack\", \"ms_teams\"]"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  detail:
                    type: object
                    description: error details
                  message:
                    type: string
                    description: error message
      deprecated: false
  /v1/user/{distinct_id}/preference/category/{category_slug}/:
    patch:
      summary: Category and Channel within Category
      security:
        - BearerAuth: []
      description: API to update user preferences for a specific notification category.
      operationId: update-user-preference-category
      x-codeSamples:
        - lang: cURL
          label: Update User Category Preference - Opt Out Channel
          source: |
            curl -X PATCH "https://hub.suprsend.com/v1/user/user123/preference/status-update-alert/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "preference": "opt_in",
                "opt_out_channels": ["email", "slack"]
              }'
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be fetched
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
        - name: category_slug
          in: path
          description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
          schema:
            type: string
          required: true
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch translated category and section names and descriptions. 
            When provided, the API returns category and section names and descriptions in the specified language if translations are available. 
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                preference:
                  type: string
                  description: 'choose one of the options: `opt_in` if the user has allowed notification in this category and `opt_out` if user wants to discontinue notification in this category'
                  default: opt_in
                opt_out_channels:
                  type: array
                  description: Add array of channels if user wants to unsubscribe from particular channels in this category. Add channels as `email`, `sms`, `whatsapp`, `androidpush`, `inbox`, `iospush`, `slack`, `webpush`
                  items:
                    type: string
                opt_in_channels:
                  type: array
                  description: You can either pass opt_out_channels when user opts out from a channel in the category or opt_in_channels when user opts in to a channel in the category. Add channels as `email`, `sms`, `whatsapp`, `androidpush`, `inbox`, `iospush`, `slack`, `webpush`
                  items:
                    type: string
                digest_schedule:
                  type: object
                  nullable: true
                  description: >
                    User's preferred digest schedule for this category. Set to `null` to fall back to tenant's default.
                  properties:
                    id:
                      type: string
                      description: ID of the selected digest schedule option
                    time:
                      type: string
                      description: "Override time if applicable and edit_policy is `editable`. Format: HH:MM"
                    dtstart:
                      type: string
                      format: date-time
                      description: Override start date if applicable and edit_policy is `editable`
                    weekdays:
                      type: array
                      description: Override weekdays if applicable and edit_policy is `editable`
                      items:
                        type: string
                        enum: ["mo", "tu", "we", "th", "fr", "sa", "su"]
                    monthdays:
                      type: array
                      description: Override monthdays if applicable and edit_policy is `editable`
                      items:
                        type: object
                        properties:
                          pos:
                            description: "Position in the month (1-31; use a negative value to count from the end)."
                            type: integer
                          day:
                            description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                            type: string
                properties:
                  type: array
                  description: Override values for category condition properties. Only properties with edit_policy `editable` can be overridden. The datatype of value must match the property's `value_type`.
                  items:
                    type: object
                    properties:
                      key:
                        type: string
                        description: Property key identifier
                      value:
                        description: Override value for the property
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "name": "Weekly Activity Digest",
                    "category": "weekly-activity-digest",
                    "description": "Summary of recent activity in your workspace",
                    "tags": [
                      "digest",
                      "activity"
                    ],
                    "effective_tags": [
                      "digest",
                      "activity"
                    ],
                    "original_preference": "opt_in",
                    "preference": "opt_in",
                    "is_editable": true,
                    "channels": [
                      {
                        "channel": "email",
                        "preference": "opt_in",
                        "is_editable": true
                      }
                    ],
                    "digest_schedule_options": {
                      "options": [
                        {
                          "id": "instant",
                          "label": "Instant",
                          "frequency": "instantly",
                          "is_default": false,
                          "is_user_selected": false
                        },
                        {
                          "id": "daily-summary",
                          "label": "Daily summary at 9:00 AM",
                          "frequency": "daily",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "09:00",
                            "value": ""
                          },
                          "is_default": true,
                          "is_user_selected": false
                        },
                        {
                          "id": "weekly-on-weekdays",
                          "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                          "frequency": "weekly_mo2fr",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "09:00",
                            "value": "10:00"
                          },
                          "weekdays": {
                            "edit_policy": "locked",
                            "default_value": ["mo", "tu", "we", "th", "fr"],
                            "value": ["mo", "tu", "we", "th", "fr"]
                          },
                          "is_default": false,
                          "is_user_selected": true
                        }
                      ]
                    },
                    "digest_schedule": {
                      "id": "weekly-on-weekdays",
                      "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                      "frequency": "weekly_mo2fr",
                      "interval": 1,
                      "time": "10:00",
                      "weekdays": ["mo", "tu", "we", "th", "fr"],
                      "is_default": false,
                      "is_user_selected": true
                    },
                    "properties": [
                      {
                        "key": "threshold",
                        "label": "Minimum activity count",
                        "value_type": "string",
                        "default_value": "100",
                        "is_optional": false,
                        "edit_policy": "editable",
                        "is_overridden": true,
                        "value": "500"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  name:
                    description: Display name of the notification category.
                    type: string
                    example: Weekly Activity Digest
                  category:
                    description: Slug of the notification category.
                    type: string
                    example: weekly-activity-digest
                  description:
                    description: Description of the notification category.
                    type: string
                    example: Summary of recent activity in your workspace
                  tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  effective_tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  original_preference:
                    type: string
                    description: default preference of the category
                    example: opt_in
                  preference:
                    type: string
                    description: final user preference of the category
                    example: opt_in
                  is_editable:
                    type: boolean
                    description: "false for categories where default preference is set to can't unsubscribe"
                    example: true
                  channels:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          example: email
                        preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          example: opt_in
                        is_editable:
                          type: boolean
                          example: true
                  digest_schedule_options:
                    type: object
                    nullable: true
                    description: All available digest schedule options for this category, showing user selections
                    properties:
                      options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              description: "Time of day to send the digest, with its edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                value:
                                  type: string
                                  nullable: true
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: object
                            dtstart:
                              description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                                value:
                                  type: string
                                  nullable: true
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                            is_user_selected:
                              type: boolean
                  digest_schedule:
                    type: object
                    nullable: true
                    description: The user's currently active digest schedule selection
                    properties:
                      id:
                        description: "Unique identifier of the digest schedule option."
                        type: string
                      label:
                        description: "Display label shown to the recipient."
                        type: string
                      frequency:
                        description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                        type: string
                      interval:
                        description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                        type: integer
                      time:
                        description: "Time of day to send the digest, with its edit policy and value."
                        type: string
                      weekdays:
                        description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                        type: array
                        items:
                          type: string
                      monthdays:
                        description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                        type: array
                        items:
                          type: object
                          properties:
                            pos:
                              description: "Position in the month (1-31; use a negative value to count from the end)."
                              type: integer
                            day:
                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                              type: string
                      is_default:
                        description: "Whether this option is the default selection."
                        type: boolean
                      is_user_selected:
                        type: boolean
                  properties:
                    type: array
                    nullable: true
                    description: Category condition properties with user overrides
                    items:
                      type: object
                      properties:
                        key:
                          description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                          type: string
                        label:
                          description: "Display label shown to the recipient."
                          type: string
                        value_type:
                          description: "Data type of the property value."
                          type: string
                        default_value:
                          description: "Default value applied when not overridden."
                          type: string
                        is_optional:
                          description: "Whether this property is optional."
                          type: boolean
                        edit_policy:
                          description: "`editable` means the value can be overridden; `locked` means it is fixed."
                          type: string
                          enum: ["locked", "editable"]
                        is_overridden:
                          type: boolean
                          description: Whether the user has overridden the default value
                        value:
                          description: User-overridden value, if any
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "category '_category_slug_' not found"
                  }
              schema:
                type: object
                description: error code and message detailing the error
      deprecated: false
    get:
      summary: Single Category
      security:
        - BearerAuth: []
      description: API to fetch user preferences for a given category.
      operationId: get-user-preferences-single-category
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be fetched
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
        - name: category_slug
          in: path
          description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
          schema:
            type: string
          required: true
        - name: show_opt_out_channels
          in: query
          description: set this flag to `true` if you want to fetch channel list for opt-out categories.
          schema:
            type: boolean
            default: false
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file.

            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "name": "Newsletter",
                    "category": "newsletter",
                    "description": "Send me updates on new product updates",
                    "original_preference": null,
                    "preference": "opt_in",
                    "is_editable": false,
                    "channels": [
                      {
                        "channel": "email",
                        "preference": "opt_in",
                        "is_editable": false
                      },
                      {
                        "channel": "ms_teams",
                        "preference": "opt_in",
                        "is_editable": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  name:
                    type: string
                    description: name of the notification category
                    example: Newsletter
                  category:
                    type: string
                    description: category slug identifier
                    example: newsletter
                  description:
                    type: string
                    description: description of the notification category
                    example: Send me updates on new product updates
                  original_preference:
                    type: string
                    description: "default preference of the category"
                    nullable: true
                    example: null
                  preference:
                    type: string
                    description: "updated user preference of the category"
                    example: opt_in
                  is_editable:
                    type: boolean
                    description: "false when category default preference is set to `can't unsubscribe`"
                    example: false
                  channels:
                    type: array
                    description: "channel level preference in the category"
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          description: channel name
                          example: email
                        preference:
                          type: string
                          description: user preference for this channel (opt_in, opt_out)
                          example: opt_in
                        is_editable:
                          type: boolean
                          description: whether the user can edit this channel preference
                          example: false
                  digest_schedule_options:
                    type: object
                    nullable: true
                    description: All digest schedule options configured on the category, with the recipient's current selection. `null` if digest schedule is not enabled on the category.
                    properties:
                      options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              type: string
                              description: Display label shown to the recipient for this option.
                            frequency:
                              type: string
                              description: Frequency of the digest schedule.
                              enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              type: object
                              description: Time of day to send the digest, with its edit policy and the recipient's override.
                              properties:
                                edit_policy:
                                  type: string
                                  enum: ["locked", "editable"]
                                  description: "`editable` means the recipient can change this value; `locked` means it is fixed."
                                default_value:
                                  type: string
                                  description: "Default time in HH:MM (24-hour) format."
                                value:
                                  type: string
                                  nullable: true
                                  description: Recipient's overridden value, if any.
                            weekdays:
                              type: object
                              description: Days of the week to send on (for `weekly` frequency), with edit policy and recipient override.
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: string
                            monthdays:
                              type: object
                              description: Days of the month to send on (for `monthly` frequency), with edit policy and recipient override.
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: object
                            dtstart:
                              type: object
                              description: Start datetime from which the recurring schedule is calculated, with edit policy and recipient override.
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                                value:
                                  type: string
                                  nullable: true
                            is_default:
                              type: boolean
                              description: Whether this option is the category default.
                            is_user_selected:
                              type: boolean
                              description: Whether the recipient has selected this option.
                  digest_schedule:
                    type: object
                    nullable: true
                    description: The recipient's currently active digest schedule, resolved in order recipient selection -> tenant default -> category default. `null` if digest schedule is not enabled on the category.
                    properties:
                      id:
                        description: "Unique identifier of the digest schedule option."
                        type: string
                      label:
                        description: "Display label shown to the recipient."
                        type: string
                      frequency:
                        description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                        type: string
                        enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                      interval:
                        description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                        type: integer
                      time:
                        type: string
                        description: "Resolved time in HH:MM (24-hour) format."
                      weekdays:
                        description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                        type: array
                        items:
                          type: string
                      monthdays:
                        description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                        type: array
                        items:
                          type: object
                          properties:
                            pos:
                              description: "Position in the month (1-31; use a negative value to count from the end)."
                              type: integer
                            day:
                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                              type: string
                      is_default:
                        description: "Whether this option is the default selection."
                        type: boolean
                      is_user_selected:
                        type: boolean
                  properties:
                    type: array
                    nullable: true
                    description: Category condition properties with the recipient's overrides. Referenced in workflows as `$category.properties.<key>`.
                    items:
                      type: object
                      properties:
                        key:
                          description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                          type: string
                        label:
                          type: string
                          description: Display label for the property.
                        value_type:
                          description: "Data type of the property value."
                          type: string
                          enum: ["integer", "string", "string_choice", "list_choice", "string_dynamic", "list_dynamic"]
                        default_value:
                          nullable: true
                          description: Default value applied when the recipient has not set a value.
                        is_optional:
                          description: "Whether this property is optional."
                          type: boolean
                        edit_policy:
                          type: string
                          enum: ["locked", "editable"]
                          description: "`editable` means the recipient can override the value; `locked` means it is fixed."
                        is_overridden:
                          type: boolean
                          description: Whether the recipient has overridden the default value.
                        value:
                          nullable: true
                          description: Recipient-overridden value, if any.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "category 'category_slug' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "category 'category_slug' not found"
      deprecated: false
  /v1/subscriber_list/{list_id}/delete/:
    patch:
      summary: Delete List
      security:
        - BearerAuth: []
      description: API to permanently delete a list.
      operationId: delete-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list which you want to delete
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true
                  }
              schema:
                type: object
                description: Success message when the list is successfully deleted
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "list_id: <list_id> not found",
                    "detail": "list_id: <list_id> not found"
                  }
              schema:
                type: object
                description: Error message that the list requested for delete is not found
      deprecated: false
  /v1/tenant/{tenant_id}/preference/:
    get:
      summary: Get Tenant Full Preference
      security:
        - BearerAuth: []
      description: API to fetch tenant preferences across all categories with translated names and descriptions.
      operationId: get-tenant-full-preference
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant you want to get preferences for
          schema:
            type: string
          required: true
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file. 
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "root_categories": [
                      {
                        "root_category": "system",
                        "sections": [
                          {
                            "name": "section système",
                            "slug": "system-section",
                            "description": "section système",
                            "tags": ["wwr"],
                            "categories": [
                              {
                                "name": "Sous-catégorie",
                                "category": "sub-category",
                                "description": "Description de la sous-catégorie",
                                "tags": ["gjhgjhfjfjgfdjthdhtdhdhdyrhdyrdyrdrh", "aaaaeeee"],
                                "effective_tags": ["aaaaeeee", "gjhgjhfjfjgfdjthdhtdhdhdyrhdyrdyrdrh", "wwr"],
                                "default_preference": "cant_unsubscribe",
                                "default_mandatory_channels": ["email"],
                                "default_opt_in_channels": ["inbox"],
                                "enabled_for_tenant": true,
                                "visible_to_subscriber": true,
                                "preference": "opt_in",
                                "mandatory_channels": null,
                                "opt_in_channels": null,
                                "blocked_channels": ["sms"],
                                "updated_at": "2025-12-04T10:45:39.061095+00:00"
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  root_categories:
                    type: array
                    items:
                      type: object
                      properties:
                        root_category:
                          description: Root category (system, transactional, or promotional) this sub-category belongs to.
                          type: string
                          enum: ["system", "transactional", "promotional"]
                        sections:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                                nullable: true
                              slug:
                                type: string
                                nullable: true
                              description:
                                type: string
                                nullable: true
                              tags:
                                type: array
                                nullable: true
                                items:
                                  type: string
                              categories:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    name:
                                      type: string
                                    category:
                                      type: string
                                    description:
                                      type: string
                                      nullable: true
                                    tags:
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    effective_tags:
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    default_preference:
                                      description: Category-level default preference, inherited when the tenant has not overridden it.
                                      type: string
                                      enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                                    default_mandatory_channels:
                                      description: Category-level mandatory channels (applies when the default preference is `cant_unsubscribe`).
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    default_opt_in_channels:
                                      description: Category-level opt-in channels, used when only selective channels are opted in by default.
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    enabled_for_tenant:
                                      description: Whether the category is enabled for this tenant. When false, the category is hidden from the tenant's users and notifications are not sent in it.
                                      type: boolean
                                    visible_to_subscriber:
                                      description: Whether the category appears on the tenant users' preference page.
                                      type: boolean
                                    preference:
                                      description: Tenant's overridden preference for this category. `null` if the tenant has not overridden the category default.
                                      type: string
                                      nullable: true
                                      enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                                    mandatory_channels:
                                      description: Channels the user cannot unsubscribe from (when preference is `cant_unsubscribe`), as overridden for this tenant.
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    opt_in_channels:
                                      description: Channels opted in by default for this category, as overridden for this tenant.
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    blocked_channels:
                                      description: Channels opted out across all categories for this tenant.
                                      type: array
                                      nullable: true
                                      items:
                                        type: string
                                    updated_at:
                                      description: Timestamp when the tenant preference for this category was last updated.
                                      type: string
                                      format: date-time
                                      nullable: true
                                    digest_schedule:
                                      type: object
                                      nullable: true
                                      description: Digest schedule configuration with tenant overrides and original options
                                      properties:
                                        options:
                                          type: array
                                          description: Tenant-modified digest schedule options (merged with original options by id)
                                          items:
                                            type: object
                                            properties:
                                              id:
                                                description: "Unique identifier of the digest schedule option."
                                                type: string
                                              label:
                                                description: "Display label shown to the recipient."
                                                type: string
                                              frequency:
                                                description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                                type: string
                                              interval:
                                                description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                                type: integer
                                              time:
                                                description: "Time of day to send the digest, with its edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                    enum: ["locked", "editable"]
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: string
                                              weekdays:
                                                description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                    enum: ["locked", "editable"]
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: array
                                                    items:
                                                      type: string
                                              monthdays:
                                                description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                    enum: ["locked", "editable"]
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: array
                                                    items:
                                                      type: object
                                                      properties:
                                                        pos:
                                                          description: "Position in the month (1-31; use a negative value to count from the end)."
                                                          type: integer
                                                        day:
                                                          description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                                          type: string
                                              dtstart:
                                                description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                    enum: ["locked", "editable"]
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: string
                                                    format: date-time
                                              is_default:
                                                description: "Whether this option is the default selection."
                                                type: boolean
                                        original_options:
                                          type: array
                                          description: Original digest schedule options as configured at the category level
                                          items:
                                            type: object
                                            properties:
                                              id:
                                                description: "Unique identifier of the digest schedule option."
                                                type: string
                                              label:
                                                description: "Display label shown to the recipient."
                                                type: string
                                              frequency:
                                                description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                                type: string
                                              interval:
                                                description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                                type: integer
                                              time:
                                                description: "Time of day to send the digest, with its edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: string
                                              weekdays:
                                                description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: array
                                                    items:
                                                      type: string
                                              monthdays:
                                                description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: array
                                                    items:
                                                      type: object
                                                      properties:
                                                        pos:
                                                          description: "Position in the month (1-31; use a negative value to count from the end)."
                                                          type: integer
                                                        day:
                                                          description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                                          type: string
                                              dtstart:
                                                description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                                                type: object
                                                properties:
                                                  edit_policy:
                                                    description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                                    type: string
                                                  default_value:
                                                    description: "Default value applied when not overridden."
                                                    type: string
                                                    format: date-time
                                              is_default:
                                                description: "Whether this option is the default selection."
                                                type: boolean
                                    properties:
                                      type: array
                                      nullable: true
                                      description: Category condition properties with tenant overrides
                                      items:
                                        type: object
                                        properties:
                                          key:
                                            description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                            type: string
                                          label:
                                            description: "Display label shown to the recipient."
                                            type: string
                                          value_type:
                                            description: "Data type of the property value."
                                            type: string
                                          default_value:
                                            description: "Default value applied when not overridden."
                                            type: string
                                          is_optional:
                                            description: "Whether this property is optional."
                                            type: boolean
                                          edit_policy:
                                            description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                            type: string
                                            enum: ["locked", "editable"]
                                          is_overridden:
                                            type: boolean
                                            description: Whether the tenant has overridden the default value
                                          value:
                                            description: Tenant-overridden value, if any
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'tenant_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant 'tenant_id' not found"
      deprecated: false
  /v1/tenant/{tenant_id}/preference/category/:
    get:
      summary: Get Tenant Preference All Categories
      security:
        - BearerAuth: []
      description: API to get tenant preferences for all categories with translated names and descriptions.
      operationId: get-tenant-preference-all-categories
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant you want to get preferences for
          schema:
            type: string
          required: true
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file. 
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
        - name: limit
          in: query
          description: Number of results to return per page
          schema:
            type: integer
            default: 10
        - name: offset
          in: query
          description: Number of results to skip
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 29,
                      "limit": 10,
                      "offset": 0
                    },
                    "results": [
                      {
                        "name": "sreehari_test",
                        "category": "sreehari_test",
                        "description": null,
                        "tags": null,
                        "effective_tags": ["wwr"],
                        "root_category": "system",
                        "default_preference": "cant_unsubscribe",
                        "default_mandatory_channels": ["email"],
                        "default_opt_in_channels": ["slack"],
                        "enabled_for_tenant": true,
                        "visible_to_subscriber": true,
                        "preference": null,
                        "mandatory_channels": null,
                        "opt_in_channels": null,
                        "blocked_channels": null,
                        "updated_at": null
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                      limit:
                        type: integer
                      offset:
                        type: integer
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        category:
                          type: string
                        description:
                          type: string
                          nullable: true
                        tags:
                          type: array
                          nullable: true
                          items:
                            type: string
                        effective_tags:
                          type: array
                          nullable: true
                          items:
                            type: string
                        root_category:
                          description: Root category (system, transactional, or promotional) this sub-category belongs to.
                          type: string
                          enum: ["system", "transactional", "promotional"]
                        default_preference:
                          description: Category-level default preference, inherited when the tenant has not overridden it.
                          type: string
                          enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                        default_mandatory_channels:
                          description: Category-level mandatory channels (applies when the default preference is `cant_unsubscribe`).
                          type: array
                          nullable: true
                          items:
                            type: string
                        default_opt_in_channels:
                          description: Category-level opt-in channels, used when only selective channels are opted in by default.
                          type: array
                          nullable: true
                          items:
                            type: string
                        enabled_for_tenant:
                          description: Whether the category is enabled for this tenant. When false, the category is hidden from the tenant's users and notifications are not sent in it.
                          type: boolean
                        visible_to_subscriber:
                          description: Whether the category appears on the tenant users' preference page.
                          type: boolean
                        preference:
                          description: Tenant's overridden preference for this category. `null` if the tenant has not overridden the category default.
                          type: string
                          nullable: true
                          enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                        mandatory_channels:
                          description: Channels the user cannot unsubscribe from (when preference is `cant_unsubscribe`), as overridden for this tenant.
                          type: array
                          nullable: true
                          items:
                            type: string
                        opt_in_channels:
                          description: Channels opted in by default for this category, as overridden for this tenant.
                          type: array
                          nullable: true
                          items:
                            type: string
                        blocked_channels:
                          description: Channels opted out across all categories for this tenant.
                          type: array
                          nullable: true
                          items:
                            type: string
                        updated_at:
                          description: Timestamp when the tenant preference for this category was last updated.
                          type: string
                          format: date-time
                          nullable: true
                        digest_schedule:
                          type: object
                          nullable: true
                          description: Digest schedule configuration with tenant overrides and original options
                          properties:
                            options:
                              type: array
                              description: Tenant-modified digest schedule options (merged with original options by id)
                              items:
                                type: object
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    description: "Time of day to send the digest, with its edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            pos:
                                              description: "Position in the month (1-31; use a negative value to count from the end)."
                                              type: integer
                                            day:
                                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                              type: string
                                  dtstart:
                                    description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                        format: date-time
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                            original_options:
                              type: array
                              description: Original digest schedule options as configured at the category level
                              items:
                                type: object
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    description: "Time of day to send the digest, with its edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            pos:
                                              description: "Position in the month (1-31; use a negative value to count from the end)."
                                              type: integer
                                            day:
                                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                              type: string
                                  dtstart:
                                    description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                        format: date-time
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                        properties:
                          type: array
                          nullable: true
                          description: Category condition properties with tenant overrides
                          items:
                            type: object
                            properties:
                              key:
                                description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                type: string
                              label:
                                description: "Display label shown to the recipient."
                                type: string
                              value_type:
                                description: "Data type of the property value."
                                type: string
                              default_value:
                                description: "Default value applied when not overridden."
                                type: string
                              is_optional:
                                description: "Whether this property is optional."
                                type: boolean
                              edit_policy:
                                description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                type: string
                                enum: ["locked", "editable"]
                              is_overridden:
                                type: boolean
                                description: Whether the tenant has overridden the default value
                              value:
                                description: Tenant-overridden value, if any
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'tenant_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant 'tenant_id' not found"
      deprecated: false
  /v1/tenant/{tenant_id}/preference/category/{category}/:
    get:
      summary: Get Tenant Preference Single Category
      security:
        - BearerAuth: []
      description: API to get tenant preference for a specific category.
      operationId: get-tenant-preference-single-category
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant you want to get preferences for
          schema:
            type: string
          required: true
        - name: category
          in: path
          description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
          schema:
            type: string
          required: true
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file. 
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "name": "tests",
                    "category": "tests",
                    "description": "asdf",
                    "tags": [
                      "asdasdasdasderrfjfsdihdaisjaisljdaskjdlkasdlkasdkasdlkasldajsldkajsdaksdasd",
                      "checktag"
                    ],
                    "effective_tags": [
                      "asdasdasdasderrfjfsdihdaisjaisljdaskjdlkasdlkasdkasdlkasldajsldkajsdaksdasd",
                      "checktag"
                    ],
                    "root_category": "system",
                    "default_preference": "cant_unsubscribe",
                    "default_mandatory_channels": null,
                    "default_opt_in_channels": null,
                    "enabled_for_tenant": true,
                    "visible_to_subscriber": true,
                    "preference": null,
                    "mandatory_channels": null,
                    "opt_in_channels": null,
                    "blocked_channels": null,
                    "updated_at": null
                  }
              schema:
                type: object
                properties:
                  name:
                    type: string
                  category:
                    type: string
                  description:
                    type: string
                    nullable: true
                  tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  effective_tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  root_category:
                    description: Root category (system, transactional, or promotional) this sub-category belongs to.
                    type: string
                    enum: ["system", "transactional", "promotional"]
                  default_preference:
                    description: Category-level default preference, inherited when the tenant has not overridden it.
                    type: string
                    enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                  default_mandatory_channels:
                    description: Category-level mandatory channels (applies when the default preference is `cant_unsubscribe`).
                    type: array
                    nullable: true
                    items:
                      type: string
                  default_opt_in_channels:
                    description: Category-level opt-in channels, used when only selective channels are opted in by default.
                    type: array
                    nullable: true
                    items:
                      type: string
                  enabled_for_tenant:
                    description: Whether the category is enabled for this tenant. When false, the category is hidden from the tenant's users and notifications are not sent in it.
                    type: boolean
                  visible_to_subscriber:
                    description: Whether the category appears on the tenant users' preference page.
                    type: boolean
                  preference:
                    description: Tenant's overridden preference for this category. `null` if the tenant has not overridden the category default.
                    type: string
                    nullable: true
                    enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                  mandatory_channels:
                    description: Channels the user cannot unsubscribe from (when preference is `cant_unsubscribe`), as overridden for this tenant.
                    type: array
                    nullable: true
                    items:
                      type: string
                  opt_in_channels:
                    description: Channels opted in by default for this category, as overridden for this tenant.
                    type: array
                    nullable: true
                    items:
                      type: string
                  blocked_channels:
                    description: Channels opted out across all categories for this tenant.
                    type: array
                    nullable: true
                    items:
                      type: string
                  updated_at:
                    description: Timestamp when the tenant preference for this category was last updated.
                    type: string
                    format: date-time
                    nullable: true
                  digest_schedule:
                    type: object
                    nullable: true
                    description: Digest schedule configuration with tenant overrides and original options
                    properties:
                      options:
                        type: array
                        description: Tenant-modified digest schedule options (merged with original options by id)
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              description: "Time of day to send the digest, with its edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                            dtstart:
                              description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                      original_options:
                        type: array
                        description: Original digest schedule options as configured at the category level
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              description: "Time of day to send the digest, with its edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                            dtstart:
                              description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                  properties:
                    type: array
                    nullable: true
                    description: Category condition properties with tenant overrides
                    items:
                      type: object
                      properties:
                        key:
                          description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                          type: string
                        label:
                          description: "Display label shown to the recipient."
                          type: string
                        value_type:
                          description: "Data type of the property value."
                          type: string
                        default_value:
                          description: "Default value applied when not overridden."
                          type: string
                        is_optional:
                          description: "Whether this property is optional."
                          type: boolean
                        edit_policy:
                          description: "`editable` means the value can be overridden; `locked` means it is fixed."
                          type: string
                          enum: ["locked", "editable"]
                        is_overridden:
                          type: boolean
                          description: Whether the tenant has overridden the default value
                        value:
                          description: Tenant-overridden value, if any
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'tenant_id' not found or category 'category' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant 'tenant_id' not found or category 'category' not found"
      deprecated: false
    patch:
      summary: Update Tenant Preference Single Category
      security:
        - BearerAuth: []
      description: API to update tenant preference for a specific category.
      operationId: update-tenant-preference-single-category
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant you want to update preferences for
          schema:
            type: string
          required: true
        - name: category
          in: path
          description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled_for_tenant:
                  type: boolean
                  description: Whether the category is enabled for this tenant. Set to `false` to hide the category from the tenant's users and stop sending notifications in it. If [sub-tenants](/docs/sub-tenants) are used, a category disabled on an ancestor stays disabled on every sub-tenant below and can't be re-enabled lower down.
                preference:
                  type: string
                  enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                  description: set `opt_in` to turn on notifications on all or selected channels by default, `opt_out` to turn-off notifications by default, `cant_unsubscribe` if you do not want users to completely opt-out from this category
                visible_to_subscriber:
                  type: boolean
                  description: set it `false` to hide a category from user's preference page
                mandatory_channels:
                  type: array
                  description: Add mandatory channels that the user can't unsubscribe from if preference is `cant_unsubscribe`.
                  items:
                    type: string
                opt_in_channels:
                  type: array
                  description: List of channels to opt-in for this category. Only applicable when preference is `opt_in`.
                  items:
                    type: string
                blocked_channels:
                  type: array
                  description: Channels turned off for this category for this tenant. Notifications on these channels won't be sent to any user of the tenant in this category, and users can't override it. If [sub-tenants](/docs/sub-tenants) are used, a block set on an ancestor also applies to every sub-tenant below and can't be removed lower down.
                  items:
                    type: string
                    enum: [email, sms, whatsapp, androidpush, inbox, iospush, slack, webpush, ms_teams]
                digest_schedule:
                  type: object
                  description: >
                    Tenants can modify some parameters (time, weekdays, monthdays, dtstart, is_default) of existing digest schedules.
                    Users will see merged digest-schedule options (original options + tenant-modified options merged by id).
                  properties:
                    options:
                      type: array
                      description: Array of digest schedule option overrides. Reference existing options by their `id`.
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                            description: ID of an existing digest schedule option to modify
                          time:
                            type: object
                            description: Override the default time value, if applicable
                            properties:
                              default_value:
                                type: string
                                description: "Time in HH:MM format"
                                example: "09:00"
                          weekdays:
                            type: object
                            description: Override the default weekdays, if applicable
                            properties:
                              default_value:
                                description: "Default value applied when not overridden."
                                type: array
                                items:
                                  type: string
                                  enum: ["mo", "tu", "we", "th", "fr", "sa", "su"]
                          monthdays:
                            type: object
                            description: Override the default monthdays, if applicable
                            properties:
                              default_value:
                                description: "Default value applied when not overridden."
                                type: array
                                items:
                                  type: object
                                  properties:
                                    pos:
                                      type: integer
                                      description: Day of month (1-31)
                                    day:
                                      type: string
                                      description: "Optional day of week (e.g. su, mo)"
                          dtstart:
                            type: object
                            description: Override the digest start date, if applicable
                            properties:
                              default_value:
                                type: string
                                format: date-time
                                description: ISO 8601 datetime for the schedule start
                          is_default:
                            type: boolean
                            description: Set to true to make this the default digest option for tenant users
                properties:
                  type: array
                  description: Override default values for category condition properties. Tenants can change the default value shown to their users.
                  items:
                    type: object
                    properties:
                      key:
                        type: string
                        description: Property key identifier
                      value:
                        description: New default value for the property. The datatype must match the property's `value_type`.
            examples:
              Update Preference:
                value: {
                  "preference": "opt_in",
                  "digest_schedule": {
                    "options": [
                      {
                        "id": "daily-summary",
                        "time": {
                          "default_value": "09:00"
                        },
                        "is_default": true
                      }
                    ]
                  },
                  "properties": [
                    {
                      "key": "threshold",
                      "value": "100"
                    }
                  ]
                }
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "name": "Weekly Activity Digest",
                    "category": "weekly-activity-digest",
                    "description": "Summary of recent activity in your workspace",
                    "tags": [
                      "digest",
                      "activity"
                    ],
                    "effective_tags": [
                      "digest",
                      "activity"
                    ],
                    "root_category": "transactional",
                    "default_preference": "opt_in",
                    "default_mandatory_channels": null,
                    "default_opt_in_channels": null,
                    "enabled_for_tenant": true,
                    "visible_to_subscriber": true,
                    "preference": "opt_in",
                    "mandatory_channels": null,
                    "opt_in_channels": null,
                    "blocked_channels": null,
                    "updated_at": "2026-06-29T19:09:04.796887Z",
                    "digest_schedule": {
                      "options": [
                        {
                          "id": "daily-summary",
                          "label": "Daily summary at 9:00 AM",
                          "frequency": "daily",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "09:00"
                          },
                          "is_default": true
                        }
                      ],
                      "original_options": [
                        {
                          "id": "instant",
                          "label": "Instant",
                          "frequency": "instantly",
                          "is_default": true
                        },
                        {
                          "id": "daily-summary",
                          "label": "Daily summary at 9:00 AM",
                          "frequency": "daily",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "00:00"
                          },
                          "is_default": false
                        },
                        {
                          "id": "weekly-on-weekdays",
                          "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                          "frequency": "weekly_mo2fr",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "09:00"
                          },
                          "weekdays": {
                            "edit_policy": "locked",
                            "default_value": ["mo", "tu", "we", "th", "fr"]
                          },
                          "is_default": false
                        },
                        {
                          "id": "monthly-1st",
                          "label": "Every month on the 1st at 9:00 AM",
                          "frequency": "monthly",
                          "interval": 1,
                          "time": {
                            "edit_policy": "locked",
                            "default_value": "09:00"
                          },
                          "monthdays": {
                            "edit_policy": "locked",
                            "default_value": [
                              {"pos": 1}
                            ]
                          },
                          "is_default": false
                        }
                      ]
                    },
                    "properties": [
                      {
                        "key": "threshold",
                        "label": "Minimum activity count",
                        "value_type": "string",
                        "default_value": "10",
                        "is_optional": false,
                        "edit_policy": "editable",
                        "is_overridden": true,
                        "value": "100"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  name:
                    type: string
                  category:
                    type: string
                  description:
                    type: string
                    nullable: true
                  tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  effective_tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  root_category:
                    description: Root category (system, transactional, or promotional) this sub-category belongs to.
                    type: string
                    enum: ["system", "transactional", "promotional"]
                  default_preference:
                    description: Category-level default preference, inherited when the tenant has not overridden it.
                    type: string
                    enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                  default_mandatory_channels:
                    description: Category-level mandatory channels (applies when the default preference is `cant_unsubscribe`).
                    type: array
                    nullable: true
                    items:
                      type: string
                  default_opt_in_channels:
                    description: Category-level opt-in channels, used when only selective channels are opted in by default.
                    type: array
                    nullable: true
                    items:
                      type: string
                  enabled_for_tenant:
                    description: Whether the category is enabled for this tenant. When false, the category is hidden from the tenant's users and notifications are not sent in it.
                    type: boolean
                  visible_to_subscriber:
                    description: Whether the category appears on the tenant users' preference page.
                    type: boolean
                  preference:
                    description: Tenant's overridden preference for this category. `null` if the tenant has not overridden the category default.
                    type: string
                    nullable: true
                    enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                  mandatory_channels:
                    description: Channels the user cannot unsubscribe from (when preference is `cant_unsubscribe`), as overridden for this tenant.
                    type: array
                    nullable: true
                    items:
                      type: string
                  opt_in_channels:
                    description: Channels opted in by default for this category, as overridden for this tenant.
                    type: array
                    nullable: true
                    items:
                      type: string
                  blocked_channels:
                    description: Channels opted out across all categories for this tenant.
                    type: array
                    nullable: true
                    items:
                      type: string
                  updated_at:
                    description: Timestamp when the tenant preference for this category was last updated.
                    type: string
                    format: date-time
                    nullable: true
                  digest_schedule:
                    type: object
                    nullable: true
                    description: Digest schedule configuration with tenant overrides and original options
                    properties:
                      options:
                        type: array
                        description: Tenant-modified digest schedule options (merged with original options by id)
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              description: "Time of day to send the digest, with its edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                            dtstart:
                              description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                      original_options:
                        type: array
                        description: Original digest schedule options as configured at the category level
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              description: "Time of day to send the digest, with its edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                            dtstart:
                              description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                  properties:
                    type: array
                    nullable: true
                    description: Category condition properties with tenant overrides
                    items:
                      type: object
                      properties:
                        key:
                          description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                          type: string
                        label:
                          description: "Display label shown to the recipient."
                          type: string
                        value_type:
                          description: "Data type of the property value."
                          type: string
                        default_value:
                          description: "Default value applied when not overridden."
                          type: string
                        is_optional:
                          description: "Whether this property is optional."
                          type: boolean
                        edit_policy:
                          description: "`editable` means the value can be overridden; `locked` means it is fixed."
                          type: string
                          enum: ["locked", "editable"]
                        is_overridden:
                          type: boolean
                          description: Whether the tenant has overridden the default value
                        value:
                          description: Tenant-overridden value, if any
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'tenant_id' not found or category 'category' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant 'tenant_id' not found or category 'category' not found"
      deprecated: false
  /v1/tenant/{tenant_id}/category/:
    get:
      summary: Get Tenant Default Preference
      security:
        - BearerAuth: []
      description: API to get default tenant preference for all categories.
      operationId: get-tenant-default-preference
      parameters:
        - name: tenant_id
          in: path
          description: unique identifier of the tenant you want to get default preferences for
          schema:
            type: string
          required: true
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file. 
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 12,
                      "limit": 10,
                      "offset": 0
                    },
                    "results": [
                      {
                        "name": "Status Update Alert",
                        "category": "status-update-alert",
                        "description": "Send me updates when account status changes",
                        "root_category": "transactional",
                        "default_preference": "opt_in",
                        "default_mandatory_channels": null,
                        "default_opt_in_channels": null,
                        "visible_to_subscriber": true,
                        "preference": "opt_in",
                        "mandatory_channels": null,
                        "opt_in_channels": null,
                        "blocked_channels": null
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: total number of categories
                        example: 12
                      limit:
                        type: integer
                        description: maximum number of categories returned per request
                        example: 10
                      offset:
                        type: integer
                        description: offset passed in request
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: preference category name
                        category:
                          type: string
                          description: unique preference category slug. You can get it by clicking on category name on SuprSend dashboard -> preference page
                        description:
                          type: string
                          description: description of the notification category
                        root_category:
                          type: string
                          description: root category this sub-category belongs to
                          example: "transactional"
                        default_preference:
                          type: string
                          enum: ["cant_unsubscribe", "opt_in", "opt_out"]
                          description: default preference of the category set while updating the category.
                        default_mandatory_channels:
                          type: array
                          description: default mandatory channels set while updating the category in case default preference is can't unsubscribe
                          items:
                            type: string
                        default_opt_in_channels:
                          type: array
                          nullable: true
                          description: default opt-in channels set to have selective opt-in channels instead of all channels while updating the category.
                          items:
                            type: string
                        opt_in_channels:
                          type: array
                          nullable: true
                          description: opt-in channels overridden for this tenant.
                          items:
                            type: string
                        visible_to_subscriber:
                          type: boolean
                          description: set it `false` to hide a category from user's preference page
                        preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          description: preference setting overridden for this tenant.
                        blocked_channels:
                          type: array
                          description: channels which are opted-out across all categories for this tenant.
                          items:
                            type: string
                            enum: [email, sms, whatsapp, androidpush, inbox, iospush, slack, webpush, ms_teams]
                        digest_schedule:
                          type: object
                          nullable: true
                          description: Digest schedule configuration with tenant overrides and original options
                          properties:
                            options:
                              type: array
                              description: Tenant-modified digest schedule options (merged with original options by id)
                              items:
                                type: object
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    description: "Time of day to send the digest, with its edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            pos:
                                              description: "Position in the month (1-31; use a negative value to count from the end)."
                                              type: integer
                                            day:
                                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                              type: string
                                  dtstart:
                                    description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                        format: date-time
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                            original_options:
                              type: array
                              description: Original digest schedule options as configured at the category level
                              items:
                                type: object
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    description: "Time of day to send the digest, with its edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            pos:
                                              description: "Position in the month (1-31; use a negative value to count from the end)."
                                              type: integer
                                            day:
                                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                              type: string
                                  dtstart:
                                    description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                                    type: object
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                        format: date-time
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                        properties:
                          type: array
                          nullable: true
                          description: Category condition properties with tenant overrides
                          items:
                            type: object
                            properties:
                              key:
                                description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                type: string
                              label:
                                description: "Display label shown to the recipient."
                                type: string
                              value_type:
                                description: "Data type of the property value."
                                type: string
                              default_value:
                                description: "Default value applied when not overridden."
                                type: string
                              is_optional:
                                description: "Whether this property is optional."
                                type: boolean
                              edit_policy:
                                description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                type: string
                                enum: ["locked", "editable"]
                              is_overridden:
                                type: boolean
                                description: Whether the tenant has overridden the default value
                              value:
                                description: Tenant-overridden value, if any
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'brand/tenant_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant 'brand/tenant_id' not found"
  /v1/subscriber_list/{list_id}/version/{version_id}/subscriber/add/:
    post:
      summary: Add Users to Draft List
      security:
        - BearerAuth: []
      description: API to add users in the draft list by passing its `version_id` returned in [Start Sync](/reference/start-sync) API response.
      operationId: add-subscribers-to-draft-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list to which user needs to be updated
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
          required: true
        - name: version_id
          in: path
          description: Unique string identifier of the draft version of the list to which user needs to be updated
          schema:
            type: string
            default: __version_id__
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                distinct_ids:
                  type: array
                  description: Array of subscriber_ids, uniquely identifying the subscribers to be added to the list.
                  default:
                    - user1
                  items:
                    type: string
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true,
                    "affected_count": 0
                  }
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the operation was successful.
                    example: true
                  affected_count:
                    type: integer
                    description: Number of subscribers affected by the operation.
                    example: 2
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "version_id 01JR6PCW8H9K3H40XZV4 not found for list_id 123",
                    "detail": "version_id 01JR6PCW8H9K3H40XZV4 not found for list_id 123"
                  }
              schema:
                type: object
                description: error code and message detailing the reason of failure
      deprecated: false
  /v1/subscriber_list/{list_id}/version/{version_id}/delete/:
    patch:
      summary: Delete Draft List
      security:
        - BearerAuth: []
      description: API to delete draft version of the list. Use this to discard test or interim versions before publishing the final list.
      operationId: delete-draft-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list which you want to delete
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
          required: true
        - name: version_id
          in: path
          description: Unique identifier of the draft version of the list which needs to be deleted
          schema:
            type: string
            default: __version_id__
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true
                  }
              schema:
                type: object
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "version_id 01JR6PCW8H9K3H40XZV4A5R not found for list_id _list_id_",
                    "detail": "version_id 01JR6PCW8H9K3H40XZV4A5R not found for list_id _list_id_"
                  }
              schema:
                type: object
                description: error code and related message
      deprecated: false
  /v1/template/{template_slug}/:
    get:
      summary: Fetch Template details
      security:
        - BearerAuth: []
      description: API to fetch content of a template group (active & draft versions) across all associated channels and languages.
      operationId: fetch-template-details
      parameters:
        - name: template_slug
          in: path
          description: Template group slug you want to fetch content details. You'll get the template slug by clicking on copy button next to template group name on SuprSend dashboard -> template details page.
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value:
                    {
                      "id": "166277",
                      "name": "Task Reminder",
                      "slug": "task-reminder",
                      "description": "Batched template for all pending tasks",
                      "is_active": true,
                      "default_language": {
                        "name": "English",
                        "slug": "en"
                      },
                      "created_at": "2023-01-25T04:53:39.237291Z",
                      "updated_at": "2023-08-28T05:06:22.461443Z",
                      "updated_by": {
                        "name": "team_member",
                        "email": "user@example.com"
                      },
                      "last_triggered_at": "2023-08-10T12:44:03.361158Z",
                      "is_auto_translate_enabled": false,
                      "enabled_languages": ["en", "fr", "es"],
                      "channels": [
                        {
                          "id": "1244",
                          "channel": {
                            "name": "Email",
                            "slug": "email",
                            "is_template_approval_needed": true
                          },
                          "is_active": true,
                          "is_enabled": true,
                          "created_at": "2023-01-25T04:53:39.268299Z",
                          "updated_at": "2023-01-25T04:53:39.404273Z",
                          "disabled_languages": [],
                          "versions": []
                        }
                      ],
                      "tags": [
                        {
                          "id":"01H9HPT1C5ABN61S12D85J9DJ7",
                          "name": "tag"
                        }
                      ]
                    }
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    description: internal template_id
                  name:
                    type: string
                    description: template name given by user
                  slug:
                    type: string
                    description: unique template slug generated from name
                  description:
                    type: string
                    nullable: true
                    description: template description given by user
                  is_active:
                    type: boolean
                    description: "is true when atleast 1 template version is live for the channel"
                  default_language:
                    type: object
                    properties:
                      name:
                        type: string
                        example: "English"
                      slug:
                        type: string
                        example: "en"
                  created_at:
                    type: string
                    format: date-time
                    description: template creation time
                  updated_at:
                    type: string
                    format: date-time
                    description: latest template modification time
                  updated_by:
                    type: object
                    properties:
                      name:
                        type: string
                        description: team member name who last updated the template
                      email:
                        type: string
                        format: email
                        description: team member email who last updated the template
                  last_triggered_at:
                    type: string
                    format: date-time
                    description: time when the workflow was last triggered
                  is_auto_translate_enabled:
                    type: boolean
                    example: false
                  enabled_languages:
                    type: array
                    items:
                      type: string
                    examples:
                      english:
                        summary: "English language"
                        value: "en"
                      french:
                        summary: "French language"
                        value: "fr"
                      spanish:
                        summary: "Spanish language"
                        value: "es"
                  channels:
                    type: array
                    description: array of all template enabled channels along with their language and active status
                    items:
                      type: object
                  tags:
                    type: array
                    description: tags added in the template group
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: unique tag identifier
                          example: "01H9HPT1C5ABN61S12D85J9DJ7"
                        name:
                          type: string
                          description: tag name
                          example: "tag"
      deprecated: false
  /v1/subscriber_list/{list_id}/version/{version_id}/finish_sync/:
    patch:
      summary: Finish Sync
      security:
        - BearerAuth: []
      description: API to finish sync and make the draft list version live.
      operationId: finish-sync
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
          required: true
        - name: version_id
          in: path
          description: Unique string identifier of the draft version of the list which needs to be made active(live)
          schema:
            type: string
            default: __version_id__
          required: true
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "list_id": "_list_id_",
                    "list_name": "_list_name_",
                    "list_description": "a brief of what type of users are part of this list",
                    "list_type": "static_list",
                    "subscribers_count": 0,
                    "source": null,
                    "is_readonly": false,
                    "status": "draft",
                    "track_user_entry": false,
                    "track_user_exit": false,
                    "requested_for_delete": false,
                    "created_at": "2025-04-06T23:18:59.601000Z",
                    "updated_at": "2025-04-06T23:18:59.601000Z",
                    "version_id": null
                  }
              schema:
                type: object
                properties:
                  version_id:
                    type: string
                    description: finish sync makes the draft version with the version_id live as well deletes the draft version.
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "version_id 01JR6PCW8H9K3H40XZV4A5R not found for list_id _list_id_",
                    "detail": "version_id 01JR6PCW8H9K3H40XZV4A5R not found for list_id _list_id_"
                  }
              schema:
                type: object
                description: error code and related message
      deprecated: false
  /v1/subscriber_list/{list_id}/version/{version_id}/subscriber/remove/:
    post:
      summary: Remove Subscribers from Draft List
      security:
        - BearerAuth: []
      description: API to remove users from the draft list by passing its `version_id` returned in [Start Sync](/reference/start-sync) API response.
      operationId: remove-subscribers-from-draft-list
      parameters:
        - name: list_id
          in: path
          description: Unique string identifier of the list to which user needs to be updated
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
          required: true
        - name: version_id
          in: path
          description: Unique string identifier of the draft version of the list to which user needs to be updated
          schema:
            type: string
            default: __version_id__
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                distinct_ids:
                  type: array
                  description: Array of subscriber_ids, uniquely identifying the subscribers to be removed from the list.
                  default:
                    - user1
                  items:
                    type: string
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true,
                    "affected_count": 0
                  }
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates whether the operation was successful.
                    example: true
                  affected_count:
                    type: integer
                    description: Number of subscribers affected by the operation.
                    example: 2
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "version_id 01JR6PCW8H9K3H40XZV4 not found for list_id 123",
                    "detail": "version_id 01JR6PCW8H9K3H40XZV4 not found for list_id 123"
                  }
              schema:
                type: object
                description: error code and message detailing the reason of failure
      deprecated: false
  /v1/subscriber_list/{list_id}/start_sync/:
    post:
      summary: Start Sync
      security:
        - BearerAuth: []
      description: Creates an empty draft version of the list where you can update users to be replaced without affecting the live version.
      operationId: start-sync
      parameters:
        - name: list_id
          in: path
          description: Unique identifier of the list on which the sync needs to start to create a draft version
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: _list_id_
          required: true
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "list_id": "_list_id_",
                    "list_name": "_list_name_",
                    "list_description": "a brief of what type of users are part of this list",
                    "list_type": "static_list",
                    "subscribers_count": 0,
                    "source": null,
                    "is_readonly": false,
                    "status": "draft",
                    "track_user_entry": false,
                    "track_user_exit": false,
                    "requested_for_delete": false,
                    "created_at": "2025-04-06T23:18:59.601000Z",
                    "updated_at": "2025-04-06T23:18:59.601000Z",
                    "version_id": "01JR6PCW8H9K3H40XZV4A5R4KQ"
                  }
              schema:
                type: object
                properties:
                  version_id:
                    type: string
                    description: start sync creates a draft version of the list with version_id. Use this version to update users in the draft list.
        '400':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "list_id: ff not found",
                    "detail": "list_id: ff not found"
                  }
              schema:
                type: object
                description: error code and message detailing the failure reason
      deprecated: false
  /v1/template/{template_slug}/channel/{channel_slug}/:
    get:
      summary: Fetch Template content for a channel
      security:
        - BearerAuth: []
      description: API to fetch content of a particular channel in a template group (live & draft versions).
      operationId: fetch-template-details-channel
      parameters:
        - name: template_slug
          in: path
          description: Template group slug you want to fetch content details. You'll get the template slug by clicking on copy button next to template group name on SuprSend dashboard -> template details page.
          schema:
            type: string
          required: true
        - name: channel_slug
          in: path
          description: add one of the template channels  - `email`, `sms`, `whatsapp`, `inbox`, `slack`, `androidpush`, `iospush`, `webpush`
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "id": 1121,
                    "channel": {
                      "name": "In-App Inbox",
                      "slug": "inbox",
                      "is_template_approval_needed": false
                    },
                    "is_active": true,
                    "is_enabled": true,
                    "created_at": "2022-06-18T04:53:58.690274Z",
                    "updated_at": "2025-01-21T11:49:23.247217Z",
                    "disabled_languages": [],
                    "versions": [
                      {
                        "id": 69989,
                        "templates": [
                          {
                            "id": 74660,
                            "language": {
                              "name": "English",
                              "slug": "en"
                            },
                            "is_enabled": true,
                            "approval_status": "auto_approved",
                            "content": {...},
                            "created_at": "2024-09-15T04:33:22.727005Z",
                            "updated_at": "2024-09-15T04:36:56.103368Z",
                            "updated_by": {
                              "name": "Jane Doe",
                              "email": "user@example.com"
                            },
                            "approval_cycle": null,
                            "is_approval_needed": false,
                            "is_cloned_from_last_version": false
                          }
                        ],
                        "status": "active",
                        "version_tag": "17",
                        "created_at": "2024-09-15T04:33:22.714274Z",
                        "updated_at": "2024-09-15T04:36:58.752580Z",
                        "updated_by": {
                          "name": "Jane Doe",
                          "email": "user@example.com"
                        },
                        "version_tag_user": "v1",
                        "published_languages": [
                          "en"
                        ],
                        "apparent_published_languages": [
                          "en"
                        ],
                        "system_approval_info": {}
                      }]
                  }
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    description: template id generated by SuprSend
                  channel:
                    type: object
                    properties:
                      name:
                        type: string
                        description: channel type
                        example: "In-App Inbox"
                      slug:
                        type: string
                        description: unique slug of the channel
                        example: "inbox"
                      is_template_approval_needed:
                        type: boolean
                        description: "is true for channels like whatsapp where template needs to be pre-approved for sending notification"
                        example: false
                  is_active:
                    type: boolean
                    description: active templates have atleast 1 live version
                  is_enabled:
                    type: boolean
                    description: disabled channels are not picked for sending the message
                    example: true
                  created_at:
                    type: string
                    format: date-time
                    example: "2023-01-25T04:53:40.011112Z"
                  updated_at:
                    type: string
                    format: date-time
                    example: "2023-07-27T14:55:23.939438Z"
                  disabled_languages:
                    type: array
                    items:
                      type: string
                  versions:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          example: 10830
                        templates:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                                example: 11876
                              language:
                                type: object
                                properties:
                                  name:
                                    type: string
                                    description: language name
                                    example: "English"
                                  slug:
                                    type: string
                                    description: language code
                                    example: "en"
                              is_enabled:
                                type: boolean
                                description: whether the template is enabled for this language
                                example: true
                              approval_status:
                                type: string
                                description: approval status of the template (auto_approved, pending, rejected)
                                example: "auto_approved"
                              content:
                                type: object
                                description: json content of the template
                              created_at:
                                type: string
                                format: date-time
                                description: timestamp of template creation
                              updated_at:
                                type: string
                                format: date-time
                                description: timestamp when the template channel content was last updated
                              updated_by:
                                type: object
                                properties:
                                  name:
                                    type: string
                                    description: team member name who last updated the content
                                  email:
                                    type: string
                                    description: email of the team member who last updated the content
                                    example: "user@example.com"
                              approval_cycle:
                                type: string
                                nullable: true
                                description: approval cycle information
                                example: null
                              is_approval_needed:
                                type: boolean
                                description: whether approval is needed for this template
                                example: false
                              is_cloned_from_last_version:
                                type: boolean
                                description: whether this template was cloned from the last version
                                example: false
                        status:
                          type: string
                          description: version status (active, draft, archived)
                          example: "active"
                        version_tag:
                          type: string
                          description: version number
                        created_at:
                          type: string
                          format: date-time
                          example: "2023-01-25T04:53:40.016463Z"
                        updated_at:
                          type: string
                          format: date-time
                          example: "2023-01-25T04:53:40.083969Z"
                        updated_by:
                          type: object
                          description: team member details who last updated the content for the channel
                        version_tag_user:
                          type: string
                          description: version name added on publish
                        published_languages:
                          type: array
                          description: languages last published in the channel
                          items:
                            type: string
                          examples:
                            english:
                              summary: "English language"
                              value: "en"
                        apparent_published_languages:
                          type: array
                          description: languages that appear to be published in the channel
                          items:
                            type: string
                          example: ["en"]
                        system_approval_info:
                          type: object
                          description: system approval information for the template
                          example: {}
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "type": "DoesNotExist",
                    "message": "TemplateGroup matching query does not exist."
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: error code
                  type:
                    type: string
                    description: error type
                  message:
                    type: string
                    description: error message giving reason of the failure      
      deprecated: false
  /v1/template/:
    get:
      summary: Fetch Template List
      security:
        - BearerAuth: []
      description: API to fetch paginated list of all templates in a given workspace.
      operationId: fetch-template-list
      parameters:
        - name: has_tag_ids_any
          in: query
          description: comma separated string of tag ids attached to the template
          schema:
            type: string
        - name: has_channels_any
          in: query
          description: comma separated string of channels. Returns templates which has any of the channels present from the channel string. Use these keys for channels - `email`, `sms`, `whatsapp`, `inbox`, `slack`, `androidpush`, `iospush`, `webpush`
          schema:
            type: string
        - name: is_active
          in: query
          description: Set `true` for published templates, `false` for templates which are in draft. Do not pass this key to return all templates.
          schema:
            type: boolean
        - name: is_archived
          in: query
          description: Set `true` to get archived templates, default = `false`
          schema:
            type: boolean
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 1,
                      "limit": 10,
                      "offset": 0
                    },
                    "results": [
                      {
                        "id": "166277",
                        "name": "Task Reminder",
                        "slug": "task-reminder",
                        "description": "Batched template for all pending tasks",
                        "is_active": true,
                        "default_language": {
                          "name": "English",
                          "slug": "en"
                        },
                        "created_at": "2023-01-25T04:53:39.237291Z",
                        "updated_at": "2023-08-28T05:06:22.461443Z",
                        "updated_by": {
                          "name": "team_member",
                          "email": "user@example.com"
                        },
                        "last_triggered_at": "2023-08-10T12:44:03.361158Z",
                        "is_auto_translate_enabled": false,
                        "enabled_languages": ["en", "fr", "es"],
                        "channels": [
                          {
                            "id": "<integer>",
                            "channel": {
                              "name": "Email",
                              "slug": "email",
                              "is_template_approval_needed": true
                            },
                            "is_active": true,
                            "is_enabled": true,
                            "created_at": "2023-01-25T04:53:39.268299Z",
                            "updated_at": "2023-01-25T04:53:39.404273Z",
                            "disabled_languages": [],
                            "versions": []
                          }
                        ],
                        "tags": [
                          {
                            "id":"01H9HPT1C5ABN61S12D85J9DJ7",
                            "name": "tag"
                          }
                        ]
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: total template count
                        example: 1
                      limit:
                        type: integer
                        description: number of results per page
                        example: 10
                      offset:
                        type: integer
                        description: offset value passed in the request
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                          description: internal template_id
                        name:
                          type: string
                          description: template name given by user
                        slug:
                          type: string
                          description: unique template slug generated from name
                        description:
                          type: string
                          nullable: true
                          description: template description given by user
                        is_active:
                          type: boolean
                          description: "is true when atleast 1 template version is live for the channel"
                        default_language:
                          type: object
                          properties:
                            name:
                              type: string
                              example: "English"
                            slug:
                              type: string
                              example: "en"
                        created_at:
                          type: string
                          format: date-time
                          description: template creation time
                        updated_at:
                          type: string
                          format: date-time
                          description: latest template modification time
                        updated_by:
                          type: object
                          properties:
                            name:
                              type: string
                              description: team member name who last updated the template
                            email:
                              type: string
                              format: email
                              description: team member email who last updated the template
                        last_triggered_at:
                          type: string
                          format: date-time
                          description: time when the workflow was last triggered
                        is_auto_translate_enabled:
                          type: boolean
                          example: false
                        enabled_languages:
                          type: array
                          items:
                            type: string
                          examples:
                            english:
                              summary: "English language"
                              value: "en"
                            hindi:
                              summary: "Hindi language"
                              value: "hi"
                            kannada:
                              summary: "Kannada language"
                              value: "kn"
                        channels:
                          type: array
                          description: array of all template enabled channels along with their language and active status
                          items:
                            type: object
                        tags:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                                description: unique tag identifier
                                example: "01H9HPT1C5ABN61S12D85J9DJ7"
                              name:
                                type: string
                                description: tag name
                                example: "tag"
                          example: null
      deprecated: false
  /trigger/:
    post:
      summary: Trigger Workflow (single or bulk)
      security:
        - BearerAuth: []
      description: |
        API to trigger multi-step workflow to one or more users/objects by passing workflow slug, via `POST /trigger/`.

        Send a single JSON **object** to trigger one workflow, or an array of objects to trigger multiple workflows in one call.
      operationId: trigger-workflow-api
      x-codeSamples:
        - lang: cURL
          label: Trigger Workflow
          source: |
            curl --request POST \
              --url 'https://hub.suprsend.com/trigger/' \
              --header 'Authorization: Bearer __your_api_key__' \
              --header 'Content-Type: application/json' \
              --data '{
                "workflow": "demo_notification_workflow",
                "recipients": [
                  {
                    "distinct_id": "user123",
                    "$email": ["user@example.com"]
                  }
                ],
                "data": {
                  "user_name": "John Doe",
                  "welcome_message": "Welcome to our platform!"
                }
              }'
        - lang: cURL
          label: Bulk Trigger Workflows
          source: |
            curl --request POST \
              --url 'https://hub.suprsend.com/trigger/' \
              --header 'Authorization: Bearer __your_api_key__' \
              --header 'Content-Type: application/json' \
              --data '[
                {
                  "workflow": "demo_notification_workflow",
                  "recipients": [
                    {
                      "distinct_id": "user123",
                      "$email": ["user@example.com"]
                    }
                  ],
                  "data": {
                    "user_name": "John Doe",
                    "welcome_message": "Welcome to our platform!"
                  }
                },
                {
                  "workflow": "demo_notification_workflow",
                  "recipients": [
                    {
                      "distinct_id": "user123",
                      "$email": ["user@example.com"]
                    }
                  ],
                  "data": {
                    "user_name": "John Doe",
                    "welcome_message": "Welcome to our platform!"
                  }
                }
              ]'
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - title: "Single workflow trigger"
                  description: "Send a single workflow trigger object as the request body."
                  $ref: '#/components/schemas/WorkflowTriggerSingleBody'
                - title: "Bulk workflow trigger"
                  type: array
                  description: |
                    Send a JSON **array** of workflow trigger objects (instead of a single JSON **object**) to trigger multiple workflows in one request. Each array item uses the same payload structure as a single workflow trigger (see **Single workflow trigger**).

                    Each record is independent - `workflow` (workflow slug), `recipients`, `tenant_id`, and `data` (including `data.$attachments` for email attachments) can all differ per record.

                    **Limits:**
                    - Maximum **800 KB** total request body size.
                    - Maximum **100 records** per request. Behavior beyond these limits is undefined.

                    **Rate limits:** A bulk request counts as **N calls** (one per record), not one call, against your rate limit.

                    Returns **207 Multi-Status** with per-record outcomes. See the `207` response below.
                  maxItems: 100
                  items:
                    $ref: '#/components/schemas/WorkflowTriggerSingleBody'
      responses:
        '202':
          description: '202 - Accepted (returned for single workflow trigger requests).'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "message_id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
                    "status": "success"
                  }
              schema:
                type: object
                description: All workflow requests will be accepted as long as the API request is correct. To verify if the execution was successful, check the 'Requests' tab under the 'Logs' section on the SuprSend dashboard.
                properties:
                  message_id:
                    type: string
                    description: Unique identifier of the message generated by SuprSend.
                    example: "a1b2c3d4-e5f6-7890-abcd-ef0123456789"
                  status:
                    type: string
                    example: "success"
        '207':
          description: '207 - Multi-Status (returned for bulk workflow trigger requests). Inspect each record''s `status` and `error` for individual outcomes.'
          content:
            application/json:
              examples:
                Result:
                  value:
                    records:
                      - status: "success"
                        message_id: "a1b2c3d4-e5f6-7890-abcd-ef0123456789"
                        status_code: 202
                      - status: "error"
                        status_code: 404
                        error:
                          message: "workflow not found"
                          type: "not_found"
                    status: "success"
              schema:
                type: object
                description: Per-record outcomes for a bulk workflow trigger request. Each item in `records` corresponds to the workflow at the same index in the request array.
                properties:
                  records:
                    type: array
                    description: Per-record outcomes, in the same order as the request array.
                    items:
                      type: object
                      properties:
                        status:
                          type: string
                          enum:
                            - success
                            - error
                          description: Per-record status. `success` means the workflow was accepted; `error` means it was rejected.
                        status_code:
                          type: integer
                          description: Per-record HTTP-style status code (for example, `202` for accepted, `404` for workflow not found).
                        message_id:
                          type: string
                          description: Unique identifier of the message generated by SuprSend. Present only when `status` is `success`.
                        error:
                          type: object
                          description: Present only when `status` is `error`.
                          properties:
                            message:
                              type: string
                              description: Human-readable error message for the failed record.
                            type:
                              type: string
                              description: Machine-readable error type (for example, `not_found`).
                  status:
                    type: string
                    description: Top-level status returned by the API. Inspect each record's `status` and `error` to determine per-record outcomes.
                    example: "success"
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "status": "fail",
                    "message": "BAD REQUEST"
                  }
              schema:
                type: object
                description: This error would come if the API request format is incorrect.
                properties:
                  status:
                    type: string
                    example: "fail"
                  message:
                    type: string
                    example: "BAD REQUEST"
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "status": "fail",
                    "message": "workflow 'workflow_slug' not found"
                  }
              schema:
                type: object
                description: This error would come if the workflow slug is not found.
                properties:
                  status:
                    type: string
                    example: "fail"
                  message:
                    type: string
                    example: "workflow 'workflow_slug' not found"
      deprecated: false
  /v1/workflow_run/cancel/:
    post:
      summary: Cancel Workflow
      security:
        - BearerAuth: []
      description: |
        API to cancel a running workflow execution. You can cancel a workflow by passing any combination of filters in the request body. When multiple parameters are provided, they are **ANDed** together to narrow down the matching workflow runs.

        For example, passing both `workflow_slug` and `recipients` will cancel only the workflow runs that match both the given slug and recipients.
      operationId: cancel-workflow
      x-codeSamples:
        - lang: cURL
          label: Cancel by execution_id
          source: |
            curl --request POST \
              --url 'https://hub.suprsend.com/v1/workflow_run/cancel/' \
              --header 'Authorization: Bearer __your_api_key__' \
              --header 'Content-Type: application/json' \
              --data '{
                "execution_id": "dsl_xxxx-xxxx-xxxx-xxxx"
              }'
        - lang: cURL
          label: Cancel by multiple filters
          source: |
            curl --request POST \
              --url 'https://hub.suprsend.com/v1/workflow_run/cancel/' \
              --header 'Authorization: Bearer __your_api_key__' \
              --header 'Content-Type: application/json' \
              --data '{
                "recipients": ["user_123"],
                "workflow_slug": "order-confirmation"
              }'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: |
                Filter parameters to identify workflow runs to cancel. At least one parameter must be provided. When multiple parameters are passed, they are **ANDed** together.
              properties:
                execution_id:
                  type: string
                  description: Unique execution identifier of the workflow run to cancel. You can find this in the workflow logs on the SuprSend dashboard.
                  example: "dsl_xxxx-xxxx-xxxx-xxxx"
                recipients:
                  type: array
                  description: List of recipient identifiers (distinct_id or contact info) whose workflow runs should be cancelled.
                  items:
                    type: string
                  example: ["user_123", "user@example.com"]
                idempotency_key:
                  type: string
                  description: Idempotency key that was passed when triggering the workflow. Use this to cancel a specific workflow triggered with a known idempotency key.
                  example: "a1b2c3d4-xxxx-xxxx-xxxx-ef0123456789"
                workflow_slug:
                  type: string
                  description: Slug of the workflow whose runs should be cancelled.
                  example: "order-confirmation"
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Cancelled:
                  summary: Workflow runs cancelled
                  value:
                    execution_ids:
                      - "dsl_xxxx-xxxx-xxxx-xxxx"
                NoMatch:
                  summary: No matching workflow runs found
                  value:
                    execution_ids: []
              schema:
                type: object
                properties:
                  execution_ids:
                    type: array
                    description: List of workflow execution IDs that were successfully cancelled. Empty array if no matching workflow runs were found.
                    items:
                      type: string
                      description: Unique execution identifier of the cancelled workflow run.
                    example: ["dsl_xxxx-xxxx-xxxx-xxxx"]
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value:
                    code: 400
                    message: "at least one filter is required: execution_id, recipients, idempotency_key"
              schema:
                type: object
                description: Returned when the request body does not include at least one valid filter parameter.
                properties:
                  code:
                    type: integer
                    description: HTTP status code of the error.
                    example: 400
                  message:
                    type: string
                    description: Human-readable error message describing the issue.
                    example: "at least one filter is required: execution_id, recipients, idempotency_key"
      deprecated: false
  /v1/broadcast_run/cancel/:
    post:
      summary: Cancel Broadcast
      security:
        - BearerAuth: []
      description: |
        API to cancel a running broadcast execution. You can cancel a broadcast by passing any combination of filters in the request body. When multiple parameters are provided, they are **ANDed** together to narrow down the matching broadcast runs.

        For example, passing both `list_id` and `idempotency_key` will cancel only the broadcast runs that match both the given list and idempotency key.
      operationId: cancel-broadcast
      x-codeSamples:
        - lang: cURL
          label: Cancel by execution_id
          source: |
            curl --request POST \
              --url 'https://hub.suprsend.com/v1/broadcast_run/cancel/' \
              --header 'Authorization: Bearer __your_api_key__' \
              --header 'Content-Type: application/json' \
              --data '{
                "execution_id": "broadcast_xxxx-xxxx-xxxx-xxxx"
              }'
        - lang: cURL
          label: Cancel by multiple filters
          source: |
            curl --request POST \
              --url 'https://hub.suprsend.com/v1/broadcast_run/cancel/' \
              --header 'Authorization: Bearer __your_api_key__' \
              --header 'Content-Type: application/json' \
              --data '{
                "list_id": "my_user_list"
              }'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: |
                Filter parameters to identify broadcast runs to cancel. At least one parameter must be provided. When multiple parameters are passed, they are **ANDed** together.
              properties:
                execution_id:
                  type: string
                  description: Unique execution identifier of the broadcast run to cancel. You can find this in the broadcast logs on the SuprSend dashboard.
                  example: "broadcast_xxxx-xxxx-xxxx-xxxx"
                list_id:
                  type: string
                  description: Identifier of the user list whose broadcast runs should be cancelled.
                  pattern: "^[a-z0-9_-]+$"
                  example: "my_user_list"
                idempotency_key:
                  type: string
                  description: Idempotency key that was passed when triggering the broadcast. Use this to cancel a specific broadcast triggered with a known idempotency key.
                  example: "a1b2c3d4-xxxx-xxxx-xxxx-ef0123456789"
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Cancelled:
                  summary: Broadcast runs cancelled
                  value:
                    execution_ids:
                      - "broadcast_xxxx-xxxx-xxxx-xxxx"
                NoMatch:
                  summary: No matching broadcast runs found
                  value:
                    execution_ids: []
              schema:
                type: object
                properties:
                  execution_ids:
                    type: array
                    description: List of broadcast execution IDs that were successfully cancelled. Empty array if no matching broadcast runs were found.
                    items:
                      type: string
                      description: Unique execution identifier of the cancelled broadcast run.
                    example: ["broadcast_xxxx-xxxx-xxxx-xxxx"]
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value:
                    code: 400
                    message: "at least one filter is required: execution_id, list_id, idempotency_key"
              schema:
                type: object
                description: Returned when the request body does not include at least one valid filter parameter.
                properties:
                  code:
                    type: integer
                    description: HTTP status code of the error.
                    example: 400
                  message:
                    type: string
                    description: Human-readable error message describing the issue.
                    example: "at least one filter is required: execution_id, list_id, idempotency_key"
      deprecated: false
  /v1/bulk/user/preference/:
    patch:
      summary: Bulk Update
      security:
        - BearerAuth: []
      description: Bulk API to update channel and category-level notification preferences for multiple users in one request.
      operationId: bulk-update-user-preference
      parameters:
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - distinct_ids
              properties:
                distinct_ids:
                  type: array
                  description: distinct_id of users whose preference need to be updated
                  default:
                    - id1
                    - id2
                  items:
                    type: string
                channel_preferences:
                  type: array
                  description: Use this to update channel level user preferences. Set `is_restricted - true` if the channel is opted_out by the user. This will only send critical notifications to the user which can't be opted out
                  items:
                    properties:
                      channel:
                        type: string
                        description: Add channel as `email`, `inbox`, `sms`, `whatsapp`, `androidpush`, `slack`, `iospush`, `webpush`
                        default: email
                      is_restricted:
                        type: boolean
                        description: set `is_restricted = true` if user wants to receive notification in mandatory categories on this channel. Mandatory categories are `can't unsubscribe` categories and the above channel is added as `mandatory channel` in that category
                        default: false
                    type: object
                categories:
                  type: array
                  description: Use this to user preference across categories and channels inside a category.
                  items:
                    properties:
                      category:
                        type: string
                        description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
                        default: _category_slug_
                      preference:
                        type: string
                        description: 'choose one of the options: `opt_in` if the user has allowed notification in this category and `opt_out` if user wants to discontinue notification in this category'
                        default: opt_in
                      opt_out_channels:
                        type: array
                        description: Add array of channels if user wants to unsubscribe from particular channels in this category. Add channels as `email`, `sms`, `whatsapp`, `androidpush`, `inbox`, `iospush`, `slack`, `webpush`
                        default: []
                        items:
                          type: string
                      opt_in_channels:
                        type: array
                        description: You can either pass opt_out_channels when user opts out from a channel in the category or opt_in_channels when user opts in to a channel in the category. Add channels as `email`, `sms`, `whatsapp`, `androidpush`, `inbox`, `iospush`, `slack`, `webpush`
                        default: []
                        items:
                          type: string
                      digest_schedule:
                        type: object
                        nullable: true
                        description: >
                          Recipient's preferred digest schedule for this category. Set to `null` to fall back to the tenant or category default.
                        properties:
                          id:
                            type: string
                            description: ID of the selected digest schedule option.
                          time:
                            type: string
                            description: "Override time if the option's `time.edit_policy` is `editable`. Format: HH:MM."
                          dtstart:
                            type: string
                            format: date-time
                            description: Override start datetime if the option's `dtstart.edit_policy` is `editable`.
                          weekdays:
                            type: array
                            description: Override weekdays if the option's `weekdays.edit_policy` is `editable`.
                            items:
                              type: string
                              enum: ["mo", "tu", "we", "th", "fr", "sa", "su"]
                          monthdays:
                            type: array
                            description: Override monthdays if the option's `monthdays.edit_policy` is `editable`.
                            items:
                              type: object
                              properties:
                                pos:
                                  description: "Position in the month (1-31; use a negative value to count from the end)."
                                  type: integer
                                day:
                                  description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                  type: string
                      properties:
                        type: array
                        description: Override values for category condition properties. Only properties with `edit_policy` `editable` can be overridden, and the value's datatype must match the property's `value_type`.
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                              description: Property key identifier.
                            value:
                              description: Override value for the property.
                    type: object
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true
                  }
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant '_tenant_id_' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant '_tenant_id_' not found"        
      deprecated: false
  /v1/bulk/user/preference/reset/:
    patch:
      summary: Reset
      security:
        - BearerAuth: []
      description: API to reset user preference settings to default preference.
      operationId: reset-user-preferences
      parameters:
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - distinct_ids
              properties:
                distinct_ids:
                  type: array
                  description: distinct_id of users whose preference needs to be reset
                  default:
                    - id1
                    - id2
                  items:
                    type: string
                reset_channel_preferences:
                  type: boolean
                  description: setting this to true will set all channel preference to default setting.
                  default: true
                reset_categories:
                  type: boolean
                  description: setting this to true will set all category preferences to default tenant preference.
                  default: true
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "success": true
                  }
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant '_tenant_id_' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "tenant '_tenant_id_' not found"
      deprecated: false
  /v1/user/{distinct_id}/preference/:
    get:
      summary: Full Preference
      security:
        - BearerAuth: []
      description: API to fetch user preferences across all channels and categories.
      operationId: get-user-full-preference
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be fetched
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
        - name: show_opt_out_channels
          in: query
          description: set this flag to `true` if you want to fetch channel list for opt-out categories.
          schema:
            type: boolean
            default: false
        - name: tags
          in: query
          description: >
            Filter preference categories with tags assigned to them. Used to filter preference categories relevant to the user on UI based on their roles, department or teams.

            You can apply single tag filter like `tags=tag1` or build nested conditions using logical operators - `and`, `or`, `not`, `exists`.


            Example:

            ```

            tags=admin

            tags={"or":[{"and":["admin","sales"]},{"and":["admin","manager"]}]}

            tags={"not":"admin"}

            tags={"exists":true}

          schema:
            type: string
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file.
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "sections": [
                      {
                        "subcategories": [
                          {
                            "name": "Newsletter",
                            "category": "newsletter",
                            "description": "Send me updates on new product updates",
                            "preference": "opt_in",
                            "is_editable": true,
                            "channels": [
                              { "channel": "androidpush", "preference": "opt_in", "is_editable": true },
                              { "channel": "email", "preference": "opt_in", "is_editable": true }
                            ]
                          }
                        ]
                      }
                    ],
                    "channel_preferences": [
                      { "channel": "email", "is_restricted": false }
                    ]
                  }
              schema:
                type: object
                properties:
                  sections:
                    type: array
                    items:
                      type: object
                      properties:
                        subcategories:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                description: Display name of the notification category.
                                type: string
                                example: "Newsletter"
                              category:
                                description: Slug of the notification category.
                                type: string
                                example: "newsletter"
                              description:
                                description: Description of the notification category.
                                type: string
                                example: "Send me updates on new product updates"
                              preference:
                                type: string
                                enum: ["opt_in", "opt_out"]
                                example: "opt_in"
                              is_editable:
                                type: boolean
                                description: "false when category default preference is set to can't unsubscribe"
                              channels:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    channel:
                                      type: string
                                      example: "email"
                                    preference:
                                      type: string
                                      enum: ["opt_in", "opt_out"]
                                      example: "opt_in"
                                    is_editable:
                                      type: boolean
                                      description: "false when category default preference is set to can't unsubscribe"
                              digest_schedule_options:
                                type: object
                                nullable: true
                                description: All digest schedule options configured on the category, with the recipient's current selection. `null` if digest schedule is not enabled on the category.
                                properties:
                                  options:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          description: "Unique identifier of the digest schedule option."
                                          type: string
                                        label:
                                          type: string
                                          description: Display label shown to the recipient for this option.
                                        frequency:
                                          type: string
                                          description: Frequency of the digest schedule.
                                          enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                                        interval:
                                          description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                          type: integer
                                        time:
                                          type: object
                                          description: Time of day to send the digest, with its edit policy and the recipient's override.
                                          properties:
                                            edit_policy:
                                              type: string
                                              enum: ["locked", "editable"]
                                              description: "`editable` means the recipient can change this value; `locked` means it is fixed."
                                            default_value:
                                              type: string
                                              description: "Default time in HH:MM (24-hour) format."
                                            value:
                                              type: string
                                              nullable: true
                                              description: Recipient's overridden value, if any.
                                        weekdays:
                                          type: object
                                          description: Days of the week to send on (for `weekly` frequency), with edit policy and recipient override.
                                          properties:
                                            edit_policy:
                                              description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                              type: string
                                              enum: ["locked", "editable"]
                                            default_value:
                                              description: "Default value applied when not overridden."
                                              type: array
                                              items:
                                                type: string
                                            value:
                                              type: array
                                              nullable: true
                                              items:
                                                type: string
                                        monthdays:
                                          type: object
                                          description: Days of the month to send on (for `monthly` frequency), with edit policy and recipient override.
                                          properties:
                                            edit_policy:
                                              description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                              type: string
                                              enum: ["locked", "editable"]
                                            default_value:
                                              description: "Default value applied when not overridden."
                                              type: array
                                              items:
                                                type: object
                                                properties:
                                                  pos:
                                                    description: "Position in the month (1-31; use a negative value to count from the end)."
                                                    type: integer
                                                  day:
                                                    description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                                    type: string
                                            value:
                                              type: array
                                              nullable: true
                                              items:
                                                type: object
                                        dtstart:
                                          type: object
                                          description: Start datetime from which the recurring schedule is calculated, with edit policy and recipient override.
                                          properties:
                                            edit_policy:
                                              description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                              type: string
                                              enum: ["locked", "editable"]
                                            default_value:
                                              description: "Default value applied when not overridden."
                                              type: string
                                              format: date-time
                                            value:
                                              type: string
                                              nullable: true
                                        is_default:
                                          type: boolean
                                          description: Whether this option is the category default.
                                        is_user_selected:
                                          type: boolean
                                          description: Whether the recipient has selected this option.
                              digest_schedule:
                                type: object
                                nullable: true
                                description: The recipient's currently active digest schedule, resolved in order recipient selection -> tenant default -> category default. `null` if digest schedule is not enabled on the category.
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                    enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    type: string
                                    description: "Resolved time in HH:MM (24-hour) format."
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: array
                                    items:
                                      type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        pos:
                                          description: "Position in the month (1-31; use a negative value to count from the end)."
                                          type: integer
                                        day:
                                          description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                          type: string
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                                  is_user_selected:
                                    type: boolean
                              properties:
                                type: array
                                nullable: true
                                description: Category condition properties with the recipient's overrides. Referenced in workflows as `$category.properties.<key>`.
                                items:
                                  type: object
                                  properties:
                                    key:
                                      description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                      type: string
                                    label:
                                      type: string
                                      description: Display label for the property.
                                    value_type:
                                      description: "Data type of the property value."
                                      type: string
                                      enum: ["integer", "string", "string_choice", "list_choice", "string_dynamic", "list_dynamic"]
                                    default_value:
                                      nullable: true
                                      description: Default value applied when the recipient has not set a value.
                                    is_optional:
                                      description: "Whether this property is optional."
                                      type: boolean
                                    edit_policy:
                                      type: string
                                      enum: ["locked", "editable"]
                                      description: "`editable` means the recipient can override the value; `locked` means it is fixed."
                                    is_overridden:
                                      type: boolean
                                      description: Whether the recipient has overridden the default value.
                                    value:
                                      nullable: true
                                      description: Recipient-overridden value, if any.
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          description: channel name
                          example: "androidpush"
                        is_restricted:
                          type: boolean
                          description: "True means notification will be sent in categories where this channel is marked as mandatory channel. False means opt_in on channel."
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "user [distinct_id: 'user1'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "user [distinct_id: 'user1'] not found"
      deprecated: false
    patch:
      summary: Update User Full Preference
      security:
        - BearerAuth: []
      description: API to update user preferences across all channels and categories with translated names and descriptions in the response.
      operationId: update-user-full-preference
      parameters:
        - name: distinct_id
          in: path
          description: distinct_id of the user whose preferences should be updated
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to update user preferences for a particular tenant
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channel_preferences:
                  type: array
                  description: Use this to update channel level user preferences. Set `is_restricted - true` if the channel is opted_out by the user. This will only send critical notifications to the user which can't be opted out
                  items:
                    type: object
                    properties:
                      channel:
                        type: string
                        description: Add channel as `email`, `inbox`, `sms`, `whatsapp`, `androidpush`, `slack`, `iospush`, `webpush`
                      is_restricted:
                        type: boolean
                        description: set `is_restricted = true` if user wants to receive notification in mandatory categories on this channel. Mandatory categories are `can't unsubscribe` categories and the above channel is added as `mandatory channel` in that category
                categories:
                  type: array
                  description: Use this to update user preference across categories and channels inside a category.
                  items:
                    type: object
                    properties:
                      category:
                        type: string
                        description: notification category slug
                      preference:
                        type: string
                        enum: ["opt_in", "opt_out"]
                        description: set `opt_in` to turn on notifications on all or selected channels, `opt_out` to turn-off notifications
                      opt_out_channels:
                        type: array
                        description: List of channels to opt-out from this category. Only applicable when preference is `opt_in`
                        items:
                          type: string
                      opt_in_channels:
                        type: array
                        description: List of channels to opt-in for this category. Only applicable when preference is `opt_in`
                        items:
                          type: string
                      digest_schedule:
                        type: object
                        nullable: true
                        description: >
                          User's preferred digest schedule for this category. Set to `null` to fall back to tenant's default.
                        properties:
                          id:
                            type: string
                            description: ID of the selected digest schedule option
                          time:
                            type: string
                            description: "Override time if applicable and edit_policy is `editable`. Format: HH:MM"
                          dtstart:
                            type: string
                            format: date-time
                            description: Override start date if applicable and edit_policy is `editable`
                          weekdays:
                            type: array
                            description: Override weekdays if applicable and edit_policy is `editable`
                            items:
                              type: string
                              enum: ["mo", "tu", "we", "th", "fr", "sa", "su"]
                          monthdays:
                            type: array
                            description: Override monthdays if applicable and edit_policy is `editable`
                            items:
                              type: object
                              properties:
                                pos:
                                  type: integer
                                day:
                                  type: string
                      properties:
                        type: array
                        description: Override values for category condition properties. Only properties with edit_policy `editable` can be overridden.
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                              description: Property key identifier
                            value:
                              description: Override value for the property
            examples:
              Update Preferences:
                value: {
                  "channel_preferences": [
                    {
                      "channel": "email",
                      "is_restricted": false
                    }
                  ],
                  "categories": [
                    {
                      "category": "weekly-activity-digest",
                      "preference": "opt_in",
                      "opt_out_channels": [],
                      "opt_in_channels": [],
                      "digest_schedule": {
                        "id": "weekly-on-weekdays",
                        "time": "10:00"
                      },
                      "properties": [
                        {
                          "key": "threshold",
                          "value": "500"
                        }
                      ]
                    }
                  ]
                }
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "sections": [
                      {
                        "name": null,
                        "slug": null,
                        "subcategories": [
                          {
                            "name": "Weekly Activity Digest",
                            "category": "weekly-activity-digest",
                            "description": "Summary of recent activity in your workspace",
                            "original_preference": "opt_in",
                            "preference": "opt_in",
                            "is_editable": true,
                            "channels": [
                              {
                                "channel": "email",
                                "preference": "opt_in",
                                "is_editable": true
                              }
                            ],
                            "digest_schedule": {
                              "id": "weekly-on-weekdays",
                              "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                              "frequency": "weekly_mo2fr",
                              "interval": 1,
                              "time": "10:00",
                              "weekdays": ["mo", "tu", "we", "th", "fr"],
                              "is_default": false,
                              "is_user_selected": true
                            },
                            "properties": [
                              {
                                "key": "threshold",
                                "label": "Minimum activity count",
                                "value_type": "string",
                                "default_value": "100",
                                "is_optional": false,
                                "edit_policy": "editable",
                                "is_overridden": true,
                                "value": "500"
                              }
                            ]
                          }
                        ]
                      }
                    ],
                    "channel_preferences": [
                      {
                        "channel": "email",
                        "is_restricted": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  sections:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          nullable: true
                        slug:
                          type: string
                          nullable: true
                        description:
                          type: string
                          nullable: true
                        tags:
                          type: array
                          nullable: true
                          items:
                            type: string
                        subcategories:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              category:
                                type: string
                              description:
                                type: string
                                nullable: true
                              tags:
                                type: array
                                nullable: true
                                items:
                                  type: string
                              effective_tags:
                                type: array
                                nullable: true
                                items:
                                  type: string
                              original_preference:
                                type: string
                                nullable: true
                                enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                              preference:
                                type: string
                                enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                              is_editable:
                                type: boolean
                              channels:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    channel:
                                      type: string
                                    preference:
                                      type: string
                                      enum: ["opt_in", "opt_out"]
                                    is_editable:
                                      type: boolean
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                        is_restricted:
                          type: boolean
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "user [distinct_id: 'user1'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "user [distinct_id: 'user1'] not found"
      deprecated: false
  /v1/subscriber_list/{list_id}/subscriber/:
    get:
      summary: Get list subscribers
      security:
        - BearerAuth: []
      description: API to fetch a cursor-based paginated list of all users in the list.
      operationId: get-subscriber-list-users
      parameters:
        - name: list_id
          in: path
          description: The list_id of your subscriber list
          schema:
            type: string
            pattern: "^[a-z0-9_-]+$"
            default: list_id
          required: true
        - name: limit
          in: query
          schema:
            type: integer
            format: int32
            default: 20
        - name: before
          in: query
          description: the 'id' before which the results need to be fetched
          schema:
            type: string
        - name: after
          in: query
          description: the 'id' after which the results need to be fetched
          schema:
            type: string
        - name: sort
          in: query
          description: 'the sort order, ascending or descending, here it''s decided by ''id'': ascending and ''-id'': descending'
          schema:
            type: string
            default: '-id'
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value:
                    {
                        "meta": {
                            "limit": 2,
                            "count": 10,
                            "before": "01HAZ8CZ111111",
                            "after": "01H9S626C33222222",
                            "has_prev": true,
                            "has_next": true
                        },
                        "results": [
                            {
                                "id": "01HENBBNXXXXXXXXXX",
                                "distinct_id": "distinct_id_1",
                                "created_at": "2023-11-07T16:55:23.736016+00:00"
                            },
                            {
                                "id": "01HENBYYYYYYYYYY",
                                "distinct_id": "distinct_id2",
                                "created_at": "2023-11-07T16:55:23.751078+00:00"
                            }
                        ]
                    }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      limit:
                        type: integer
                        description: number of results to be returned in API response
                        default: 20
                      count:
                        type: integer
                        description: total number of users in the list
                      before:
                        type: string
                        description: cursor of the previous page.
                        example: 01HAZ8CZ111111
                      after:
                        type: string
                        description: cursor of the next page.
                        example: 01H9S626C33222222
                      has_prev:
                        type: boolean
                        description: Indicates if there is a previous page.
                      has_next:
                        type: boolean
                        description: Indicates if there is a next page.
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Indicates the subscription id
                        distinct_id:
                          type: string
                          description: unique identifier of the user
                          example: distinct_id_1
                        created_at:
                          type: string
                          description: timestamp when this subscription was added
                          example: '2023-11-07T16:55:23.736016+00:00'
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "error_code": "not_found",
                    "type": "NotFound",
                    "message": "list_id: fffd not found",
                    "detail": "list_id: fffd not found"
                  }
              schema:
                type: object
                description: error code and message detailing
      deprecated: false
      x-readme:
        code-samples:
          - language: text
            code: |-
              curl --location 'https://hub.suprsend.com/v1/subscriber_list/list_id/subscriber/?&sort=id&limit=2&before=01HENBBNPJ65KH3AZ8CZFGDYP4' \
              --header 'Authorization: Bearer __YOUR_API_KEY__'
        samples-languages:
          - text
  /v1/object/{object_type}/{id}/:
    post:
      summary: Create / Update Objects
      security:
        - BearerAuth: []
      description: API to upsert (create if not exists, update if exists) object by providing a unique object ID and type.
      operationId: create-update-objects
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            example:
              department: "Engineering"
              $email: ["devs@example.com"]
              $slack:
                - channel: "CXXXXXXXX"
                  access_token: "xoxb-XXXXXX"
            schema:
              properties:
                $email:
                  type: array
                  items:
                    type: string
                    format: email
                  description: List of email addresses.
                $sms:
                  type: array
                  items:
                    type: string
                  description: List of phone numbers for SMS
                $whatsapp:
                  type: array
                  items:
                    type: string
                  description: List of phone numbers for WhatsApp
                $inbox:
                  type: array
                  items:
                    type: string
                  description: List of inbox identifiers
                $androidpush:
                  type: array
                  items:
                    type: string
                  description: List of Android Push tokens
                $iospush:
                  type: array
                  items:
                    type: string
                  description: List of iOS Push tokens
                $slack:
                  type: array
                  description: Slack channel configuration
                  items:
                    oneOf:
                      - type: object
                        title: "Slack using email"
                        required: [email, access_token]
                        properties:
                          email:
                            type: string
                            format: email
                            description: User email address
                            example: "user@example.com"
                          access_token:
                            type: string
                            description: Slack bot access token
                            example: "xoxb-XXXXXXXX"
                      - type: object
                        title: "Slack using member ID"
                        required: [user_id, access_token]
                        properties:
                          user_id:
                            type: string
                            description: Slack user ID (U/WXXXXXXXX format)
                            example: "U/WXXXXXXXX"
                          access_token:
                            type: string
                            description: Slack bot access token
                            example: "xoxb-XXXXXX"
                      - type: object
                        title: "Slack using channel"
                        required: [channel, access_token]
                        properties:
                          channel:
                            type: string
                            description: Slack channel ID (CXXXXXXXX format)
                            example: "CXXXXXXXX"
                          access_token:
                            type: string
                            description: Slack bot access token
                            example: "xoxb-XXXXXX"
                      - type: object
                        title: "Slack using incoming webhook"
                        required: [incoming_webhook]
                        properties:
                          incoming_webhook:
                            type: object
                            required: [url]
                            properties:
                              url:
                                type: string
                                format: uri
                                description: Slack incoming webhook URL
                                example: "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"
                $ms_teams:
                  type: array
                  description: Microsoft Teams channel configuration
                  items:
                    oneOf:
                      - type: object
                        title: "MS Teams using conversation ID"
                        required: [tenant_id, service_url, conversation_id]
                        properties:
                          tenant_id:
                            type: string
                            description: Microsoft Teams tenant ID
                            example: "c1981ab2-9aaf-xxxx-xxxx"
                          service_url:
                            type: string
                            format: uri
                            description: Microsoft Teams service URL
                            example: "https://smba.trafficmanager.net/amer"
                          conversation_id:
                            type: string
                            description: Microsoft Teams conversation ID
                            example: "19:c1524d7c-a06f-456f-8abe-xxxx"
                      - type: object
                        title: "MS Teams using user ID"
                        required: [tenant_id, service_url, user_id]
                        properties:
                          tenant_id:
                            type: string
                            description: Microsoft Teams tenant ID
                            example: "c1981ab2-9aaf-xxxx-xxxx"
                          service_url:
                            type: string
                            format: uri
                            description: Microsoft Teams service URL
                            example: "https://smba.trafficmanager.net/amer"
                          user_id:
                            type: string
                            description: Microsoft Teams user ID
                            example: "29:1nsLcmJ2RKtYH6Cxxxx-xxxx"
                      - type: object
                        title: "MS Teams using incoming webhook"
                        required: [incoming_webhook]
                        properties:
                          incoming_webhook:
                            type: object
                            required: [url]
                            properties:
                              url:
                                type: string
                                format: uri
                                description: Microsoft Teams incoming webhook URL
                                example: "https://wnk1z.webhook.office.com/webhookb2/XXXXXXXXX"
                $timezone:
                  type: string
                  description: Object's timezone in [IANA format](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List)
                  example: America/New_York
                $locale:
                  type: string
                  description: Object's locale for [translating](https://suprsend.com/docs/translations) template content in SuprSend.
                  example: en_GB
      responses:
          '201':
            description: '201 - Created'
            content:
              application/json:
                examples:
                  Result:
                    value: {
                      "object_type": "departments",
                      "id": "engineering",
                      "subscriptions_count": 0,
                      "properties": {
                        "$locale": "en_GB",
                        "department": "Engineering"
                      },
                      "created_at": "2025-04-06T10:00:37.893892+00:00",
                      "updated_at": "2025-04-06T10:00:37.893892+00:00",
                      "$email": [
                        {
                          "value": "devs@example.com",
                          "status": "active",
                          "perma_status": "active"
                        }
                      ], 
                      "$slack": [
                        {
                          "value": {
                            "email_id": "user@example.com",
                            "access_token": "xoxb-..."
                          },
                          "status": "active",
                          "perma_status": "active"
                        }
                      ],
                      "$inbox": [
                        {
                          "value": "pO7w6x_HFZxCs30N4SHab05e3QIdB1e0xT2r4vQWjvM",
                          "id_provider": "suprsend",
                          "status": "active",
                          "perma_status": "active"
                        }
                      ]
                    }
                schema:
                  type: object
                  properties:
                    id:
                      type: string
                      description: unique identifier of the object
                      example: engineering
                    object_type:
                      type: string
                      description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
                      example: departments
                    subscriptions_count:
                      type: integer
                      description: number of users/child objects subscribed to the object
                      example: departments
                    properties:
                      type: object
                      description: all user properties in key-value pair. SuprSend reserved properties start with $
                    created_at:
                      type: string
                      format: date-time
                      description: Timestamp when the object was created.
                      example: 2025-04-04T09:55:12.397856+00:00
                    updated_at:
                      type: string
                      format: date-time
                      description: Timestamp when the object was last updated.
                      example: 2025-04-04T09:55:12.422388+00:00
                    $<channel>:
                      type: array
                      description: List of active communication channels for the object.
                      items:
                        type: object
                        properties:
                          value:
                            type: string
                            description: channel value
                          status:
                            type: string
                            description: Current status of the channel (active or inactive).
                            example: active
                          perma_status:
                            type: string
                            description: active/disabled. Perma_status is marked disabled in case of hard bounce on the channel.
          '400':
            description: '400 - Bad Request'
            content:
              application/json:
                examples:
                  Result:
                    value: {
                      "code": 400,
                      "message": "invalid_request_error"
                    }
                schema:
                  type: object
                  properties:
                    code:
                      type: integer
                      example: 400
                    message:
                      type: string
                      description: "Error message describing the missing resource."
      deprecated: false
    get:
      summary: Fetch Object by id
      security:
        - BearerAuth: []
      description: API to fetch Object details by passing object type and ID.
      operationId: get-object-by-id
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "object_type": "departments",
                    "id": "engineering",
                    "subscriptions_count": 0,
                    "properties": {
                      "$locale": "en_GB"
                    },
                    "created_at": "2025-04-06T10:00:37.893892+00:00",
                    "updated_at": "2025-04-06T10:00:37.893892+00:00",
                    "$inbox": [
                      {
                        "value": "pO7w6x_HFZxCs30N4SHab05e3QIdB1e0xT2r4vQWjvM",
                        "id_provider": "suprsend",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: unique identifier of the object
                    example: engineering
                  object_type:
                    type: string
                    description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
                    example: departments
                  subscriptions_count:
                    type: integer
                    description: number of users/child objects subscribed to the object
                    example: departments
                  properties:
                    type: object
                    description: all user properties in key-value pair. SuprSend reserved properties start with $
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the object was created.
                    example: 2025-04-04T09:55:12.397856+00:00
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the object was last updated.
                    example: 2025-04-04T09:55:12.422388+00:00
                  $<channel>:
                    type: array
                    description: List of active communication channels for the object.
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: channel value
                        status:
                          type: string
                          description: Current status of the channel (active or inactive).
                          example: active
                        perma_status:
                          type: string
                          description: active/disabled. Perma_status is marked disabled in case of hard bounce on the channel.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'obj_type/obj_id' not found"
                  }
              schema:
                  type: object
                  properties:
                    code:
                      type: integer
                      example: 404
                    message:
                      type: string
                      description: "Error message describing the missing resource."
      deprecated: false
    delete:
      summary: Delete an Object
      security:
        - BearerAuth: []
      description: API to permanently delete an object by passing `object_type` and `id`.
      operationId: delete-object
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
      responses:
        '204':
          description: '204 - No Content'
          content:
            application/json:
              examples:
                Result:
                  value: null
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'object_type/object_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    description: "Error message indicating object_id and type combination is not found"
      deprecated: false
    patch:
      summary: Edit Object Profile
      security:
        - BearerAuth: []
      description: API to edit (add/remove) properties and communication-channels for an object.
      operationId: edit-object-profile
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X PATCH "https://hub.suprsend.com/v1/object/{object_type}/{id}/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "operations": [
                  {
                    "$set": {
                      "name": "Engineering Department",
                      "$locale": "en_GB",
                      "$timezone": "America/New_York"
                    }
                  },
                  {
                    "$append": {
                      "$email": ["team@example.com"]
                    }
                  }
                ]
              }'
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          required: true
          schema:
            type: string
        - name: id
          in: path
          description: Unique identifier of the object in your system
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                operations:
                  type: array
                  description: |
                    You can use the following operations to edit user profile.
                    - `$set` to add/update a property
                    - `$unset` to delete property/channel
                    - `$append` to insert values in property/channel array
                    - `$remove` to remove values from property/channel array
                    - `$set_once` to remove immutable properties
                    - `$increment` to increase/decrease integer values on further update
                  items:
                    type: object
                    properties:
                      $set:
                        type: object
                        description: |
                          Use this to set user properties like name, location, locale, etc.
                          Example: `{"team":"Engineering","$locale":"en_GB","$timezone":"America/New_York"}`
                        additionalProperties:
                          type: string
                      $unset:
                        type: array
                        description: |
                          Use this to delete channels or properties from user profile.
                          Channels: `$email`, `$sms`, `$whatsapp`, `$androidpush`, `$iospush`, `$slack`, `$webpush`, `$ms_teams`
                          Example: `["$sms", "$whatsapp", "name"]`
                        items:
                          type: string
                      $append:
                        type: object
                        description: |
                          Use this to add communication channels or update array properties in user profile. Available channel keys: `$email`, `$sms`, `$whatsapp`, `$androidpush`, `$iospush`, `$slack`, `$webpush`, `$ms_teams`
                          Example: `{"$email":"team@example.com"}`
                        additionalProperties:
                          type: string
                      $remove:
                        type: object
                        description: |
                          Use this to remove communication channels or remove values from an array in user profile. Available channel keys: `$email`, `$sms`, `$whatsapp`, `$androidpush`, `$iospush`, `$slack`, `$webpush`, `$ms_teams`
                          Example: `{"$email":"team@example.com"}`
                        additionalProperties:
                          type: string
                      $set_once:
                        type: object
                        description: |
                          Use this to set properties which are not set once and not changed on further updates.
                          Example: `{"first_login_at":"2025-01-01T14:00:00Z"}`
                        additionalProperties:
                          type: string
                      $increment:
                        type: object
                        description: |
                          Use this to increase / decrease integer values on further updates
                          Example: `{"login_count":1}`
                        additionalProperties:
                          type: string
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "object_type": "departments",
                    "id": "engineering",
                    "subscriptions_count": 0,
                    "properties": {
                      "$locale": "en_GB"
                    },
                    "created_at": "2025-04-06T10:00:37.893892+00:00",
                    "updated_at": "2025-04-06T10:00:37.893892+00:00",
                    "$inbox": [
                      {
                        "value": "pO7w6x_HFZxCs30N4SHab05e3QIdB1e0xT2r4vQWjvM",
                        "id_provider": "suprsend",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: unique identifier of the object
                    example: engineering
                  object_type:
                    type: string
                    description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
                    example: departments
                  subscriptions_count:
                    type: integer
                    description: number of users/child objects subscribed to the object
                    example: departments
                  properties:
                    type: object
                    description: all user properties in key-value pair. SuprSend reserved properties start with $
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the object was created.
                    example: 2025-04-04T09:55:12.397856+00:00
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the object was last updated.
                    example: 2025-04-04T09:55:12.422388+00:00
                  $<channel>:
                    type: array
                    description: List of active communication channels for the object.
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: channel value
                        status:
                          type: string
                          description: Current status of the channel (active or inactive).
                          example: active
                        perma_status:
                          type: string
                          description: active/disabled. Perma_status is marked disabled in case of hard bounce on the channel.
        '400':
          description: '400 - Bad Request'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 400,
                    "message": "Request body must not be empty"
                  }
      deprecated: false
  /v1/object/{object_type}/{id}/subscription/:
    post:
      summary: Add Subscription
      security:
        - BearerAuth: []
      description: API to add subscribers (users/child objects) to a given object, to notify subscribers when workflow is triggered on the parent object.
      operationId: add-object-subscription
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST "https://hub.suprsend.com/v1/object/{object_type}/{id}/subscription/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "recipients": ["user123","user456"],
                "properties": {
                  "role": "developer"
                }
              }'
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                recipients:
                  type: array
                  description: List of recipients to be notified. You can either add recipient as array of distinct_ids or array of recipient objects. You can add up to 100 recipients in a single API.
                  items:
                    oneOf:
                      - type: object
                        title: "Add user"
                        description: "**Option 1: Add user subscription** - Add user subscription by passing user json. You can pass user distinct_ids in array as `[\"id1\",\"id2\"]` or as user object to identify recipient inline."
                        required: [distinct_id]
                        properties:
                          distinct_id:
                            type: string
                            description: unique identifier of the user
                            default: id1
                          $email:
                            type: array
                            description: List of email addresses.
                            items:
                              type: string
                          $sms:
                            type: array
                            description: List of SMS numbers.
                            items:
                              type: string
                          $whatsapp:
                            type: array
                            description: List of WhatsApp numbers.
                            items:
                              type: string
                          $inbox:
                            type: array
                            description: List of Inbox numbers.
                            items:
                              type: string
                          $androidpush:
                            type: array
                            description: List of Android Push tokens.
                            items:
                              type: string
                          $iospush:
                            type: array
                            description: List of iOS Push tokens.
                            items:
                              type: string
                          $slack:
                            type: array
                            description: Slack channel configuration
                            items:
                              oneOf:
                                - type: object
                                  title: "Slack using email"
                                  required: [email, access_token]
                                  properties:
                                    email:
                                      type: string
                                      format: email
                                      description: User email address
                                      example: "user@example.com"
                                    access_token:
                                      type: string
                                      description: Slack bot access token
                                      example: "xoxb-XXXXXXXX"
                                - type: object
                                  title: "Slack using member ID"
                                  required: [user_id, access_token]
                                  properties:
                                    user_id:
                                      type: string
                                      description: Slack user ID (U/WXXXXXXXX format)
                                      example: "U/WXXXXXXXX"
                                    access_token:
                                      type: string
                                      description: Slack bot access token
                                      example: "xoxb-XXXXXX"
                                - type: object
                                  title: "Slack using channel"
                                  required: [channel, access_token]
                                  properties:
                                    channel:
                                      type: string
                                      description: Slack channel ID (CXXXXXXXX format)
                                      example: "CXXXXXXXX"
                                    access_token:
                                      type: string
                                      description: Slack bot access token
                                      example: "xoxb-XXXXXX"
                                - type: object
                                  title: "Slack using incoming webhook"
                                  required: [incoming_webhook]
                                  properties:
                                    incoming_webhook:
                                      type: object
                                      required: [url]
                                      properties:
                                        url:
                                          type: string
                                          format: uri
                                          description: Slack incoming webhook URL
                                          example: "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"
                          $ms_teams:
                            type: array
                            description: Microsoft Teams channel configuration
                            items:
                              oneOf:
                                - type: object
                                  title: "MS Teams using conversation ID"
                                  required: [tenant_id, service_url, conversation_id]
                                  properties:
                                    tenant_id:
                                      type: string
                                      description: Microsoft Teams tenant ID
                                      example: "c1981ab2-9aaf-xxxx-xxxx"
                                    service_url:
                                      type: string
                                      format: uri
                                      description: Microsoft Teams service URL
                                      example: "https://smba.trafficmanager.net/amer"
                                    conversation_id:
                                      type: string
                                      description: Microsoft Teams conversation ID
                                      example: "19:c1524d7c-a06f-456f-8abe-xxxx"
                                - type: object
                                  title: "MS Teams using user ID"
                                  required: [tenant_id, service_url, user_id]
                                  properties:
                                    tenant_id:
                                      type: string
                                      description: Microsoft Teams tenant ID
                                      example: "c1981ab2-9aaf-xxxx-xxxx"
                                    service_url:
                                      type: string
                                      format: uri
                                      description: Microsoft Teams service URL
                                      example: "https://smba.trafficmanager.net/amer"
                                    user_id:
                                      type: string
                                      description: Microsoft Teams user ID
                                      example: "29:1nsLcmJ2RKtYH6Cxxxx-xxxx"
                                - type: object
                                  title: "MS Teams using incoming webhook"
                                  required: [incoming_webhook]
                                  properties:
                                    incoming_webhook:
                                      type: object
                                      required: [url]
                                      properties:
                                        url:
                                          type: string
                                          format: uri
                                          description: Microsoft Teams incoming webhook URL
                                          example: "https://wnk1z.webhook.office.com/webhookb2/XXXXXXXXX"
                          $locale:
                            type: string
                            description: User's locale for [translating](https://suprsend.com/docs/translations) template content in SuprSend.
                            example: en_GB
                          $timezone:
                            type: string
                            description: in IANA timezone format e.g. 'America/Los_Angeles'
                        additionalProperties:
                          type: string
                          description: You can pass other user properties to render dynamic template content in key-value pair as "user_prop1":"value1" . Extra properties will be set in subscriber profile (as subscriber properties) which can then be used in the template as $recipient.<property>.
                      - type: object
                        title: "Add child object"
                        description: "**Option 2: Add object subscription** - Add other object as child subscriber to the parent object"
                        required: [id,object_type]
                        properties:
                          id:
                            type: string
                            description: Unique identifier of the object
                            example: frontend
                          object_type:
                            type: string
                            description: Type of the child object to subscribe.
                        additionalProperties:
                          type: string
                          description: You can pass other user properties similar to recipient payload. It will be used when notification is sent to object channels as $recipient.<property>.
                properties:
                  type: object
                  description: properties defining the relation between object and its subscribers. Can be referenced as `recipient.subscription.<key>` in workflow and template.
                  example: {"role":"developer"}
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "results": [
                      {
                        "properties": {
                          "department":"frontend"
                        },
                        "user": {
                          "distinct_id": "_distinct_id_",
                          "updated_at": "2025-04-05T10:33:33.629736+00:00"
                        },
                        "object": {
                          "id": "_object_id_",
                          "object_type": "_object_type_",
                          "subscriptions_count": 10,
                          "updated_at": "2025-04-06T11:00:24.257046+00:00"
                        },
                        "created_at": "2025-04-06T10:59:07.726336+00:00",
                        "updated_at": "2025-04-06T10:59:07.726336+00:00"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  user:
                    type: object
                    properties:
                      distinct_id:
                        type: string
                        description: unique identifier of the user
                        example: _distinct_id_
                      updated_at:
                        type: string
                        format: date-time
                        description: time when user was subscribed to this list
                        example: 2025-04-04T09:55:12.422388+00:00
                  object:
                      type: object
                      properties:
                        id:
                          type: string
                          description: unique identifier of the object
                          example: frontend
                        object_type:
                          type: string
                          description: type of object like teams, organizations, and roles. Used to group similar objects together.
                          example: frontend
                        subscriptions_count:
                          type: integer
                          description: number of users/child objects subscribed to this object
                        updated_at:
                          type: string
                          format: date-time
                          description: timestamp when subscription was first created
                          example: 2025-04-04T09:55:12.422388+00:00
                  properties:
                    type: object
                    description: object subscription properties, referred as `$recipient.subscription.<key>` in template or workflow.
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the subscription was created.
                    example: 2025-04-04T09:55:12.397856+00:00
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the subscription was last updated.
                    example: 2025-04-04T09:55:12.422388+00:00
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'object_type/id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    description: "Error message indicating object_id and type combination is not found"
      deprecated: false
    get:
      summary: List Object Subscriptions
      security:
        - BearerAuth: []
      description: API to fetch a paginated list of users or child objects subscribed to a given object.
      operationId: list-object-subscriptions
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 3,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": null
                    },
                    "results": [
                      {
                        "properties": {},
                        "user": null,
                        "object": {
                          "id": "devs",
                          "object_type": "teams",
                          "subscriptions_count": 1,
                          "updated_at": "2025-04-06T11:00:24.257046+00:00"
                        },
                        "created_at": "2025-04-06T11:00:24.260496+00:00",
                        "updated_at": "2025-04-06T11:00:24.260496+00:00"
                      },
                      {
                        "properties": {
                          "role": "employee"
                        },
                        "user": {
                          "distinct_id": "user_456",
                          "updated_at": "2023-08-25T13:31:24.517819+00:00"
                        },
                        "object": null,
                        "created_at": "2024-11-10T21:40:02.169501+00:00",
                        "updated_at": "2024-11-10T21:40:02.169501+00:00"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 1
                        description: "Total number of results."
                      limit:
                        type: integer
                        example: 10
                        description: "Maximum number of results returned per request."
                      has_prev:
                        type: boolean
                        description: "Indicates if there are previous results."
                      before:
                        type: string
                        description: "Cursor for the previous page, if applicable."
                      has_next:
                        type: boolean
                        description: "Indicates if there are more results."
                      after:
                        type: string
                        description: "Cursor for the next page, if applicable."
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        user:
                          type: object
                          properties:
                            distinct_id:
                              type: string
                              description: unique identifier of the user
                              example: _distinct_id_
                            updated_at:
                              type: string
                              format: date-time
                              description: time when user was subscribed to this list
                              example: 2025-04-04T09:55:12.422388+00:00
                        object:
                            type: object
                            properties:
                              id:
                                type: string
                                description: unique identifier of the object
                                example: frontend
                              object_type:
                                type: string
                                description: type of object like teams, organizations, and roles. Used to group similar objects together.
                                example: frontend
                              subscriptions_count:
                                type: integer
                                description: number of users/child objects subscribed to this object
                              updated_at:
                                type: string
                                format: date-time
                                description: timestamp when subscription was first created
                                example: 2025-04-04T09:55:12.422388+00:00
                        properties:
                          type: object
                          description: object subscription properties, referred as `$recipient.subscription.<key>` in template or workflow.
                        created_at:
                          type: string
                          format: date-time
                          example: 2025-04-04T09:55:12.397856+00:00
                        updated_at:
                          type: string
                          format: date-time
                          example: 2025-04-04T09:55:12.422388+00:00
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'obj_type/obj_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: "HTTP status code indicating the error."
                  message:
                    type: string
                    description: "Error message indicating object_id and type combination is not found"
      deprecated: false
    delete:
      summary: Remove Object Subscriptions
      security:
        - BearerAuth: []
      description: API to remove object subscribers (users or child objects).
      operationId: delete-object-subscriptions
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: recipients
          in: query
          description: List of recipients to be notified. Provide recipient IDs as a comma-separated list (e.g., `id1,id2,id3`).
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                recipients:
                  type: array
                  description: List of recipients to be notified. You can either add recipient as array of distinct_ids or array of recipient objects. You can add up to 100 recipients in a single API.
                  items:
                    oneOf:
                      - type: string
                        description: Pass user distinct_ids in array as `["id1","id2"]`
                      - type: object
                        description: Pass object to be deleted in json
                        required: [id,object_type]
                        properties:
                          id:
                            type: string
                            description: Unique identifier of the object
                            example: frontend
                          object_type:
                            type: string
                            description: Type of the object to remove from subscriptions.
      responses:
        '204':
          description: '204 - No Content'
          content:
            application/json:
              examples:
                Result:
                  value: null
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'object_type/id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: "Error code indicating a bad request."
                  message:
                    type: string
                    description: "Detailed error message explaining the issue."
      deprecated: false

  /v1/object/{object_type}/:
    get:
      summary: List Objects by type
      security:
        - BearerAuth: []
      description: API to fetch paginated list of objects that belong to the specified `object_type`.
      operationId: list-objects-by-type
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 1,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": null
                    },
                    "results": [
                      {
                        "object_type": "teams",
                        "id": "devs",
                        "subscriptions_count": 1,
                        "properties": {},
                        "created_at": "2024-11-04T09:30:05.141405+00:00",
                        "updated_at": "2025-04-06T11:00:24.257046+00:00",
                        "$inbox": [
                          {
                            "value": "mwjNxXS-z5IvY6VwyXweG0mqc14WL-z9ctBlJ-4wx60",
                            "id_provider": "suprsend",
                            "status": "active",
                            "perma_status": "active"
                          }
                        ]
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 1
                        description: "Total number of results returned."
                      limit:
                        type: integer
                        example: 10
                        description: "Maximum number of results that can be returned."
                      has_prev:
                        type: boolean
                        example: false
                        description: "Indicates if there are previous results."
                      before:
                        type: string
                        nullable: true
                        example: null
                        description: "Cursor for paginating to previous results."
                      has_next:
                        type: boolean
                        example: false
                        description: "Indicates if there are more results."
                      after:
                        type: string
                        nullable: true
                        example: null
                        description: "Cursor for paginating to next results."
                  results:
                    type: array
                    description: List of objects belonging to given object type. Response JSON is similar to object upsert API.
                    items:
                      type: object
                      properties:
                        object_type:
                          type: string
                          description: Type of the object.
                          example: teams
                        id:
                          type: string
                          description: Unique identifier of the object.
                          example: devs
                        subscriptions_count:
                          type: integer
                          description: Number of users or child objects subscribed to this object.
                          example: 1
                        properties:
                          type: object
                          additionalProperties: true
                          description: additional object properties
                          example: {}
                        created_at:
                          type: string
                          format: date-time
                          description: Timestamp when the object was created.
                          example: "2024-11-04T09:30:05.141405+00:00"
                        updated_at:
                          type: string
                          format: date-time
                          description: Timestamp when the object was last updated.
                          example: "2025-04-06T11:00:24.257046+00:00"
                        $inbox:
                          type: array
                          items:
                            type: object
                            properties:
                              value:
                                type: string
                                example: mwjNxXS-z5IvY6VwyXweG0mqc14WL-z9ctBlJ-4wx60
                              id_provider:
                                type: string
                                example: suprsend
                              status:
                                type: string
                                example: active
                              perma_status:
                                type: string
                                example: active
      deprecated: false
  /v1/object/{object_type}/{id}/preference/category/{category_slug}/:
    patch:
      summary: Category and Channel within Category
      security:
        - BearerAuth: []
      description: API to update object preferences for a specific notification category.
      operationId: object-preference-category
      x-codeSamples:
        - lang: cURL
          label: Object Preference Category - Opt Out Channel
          source: |
            curl -X PATCH "https://hub.suprsend.com/v1/object/departments/engineering/preference/status-update-alert/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "preference": "opt_in",
                "opt_out_channels": ["email", "slack"]
              }'
      parameters:
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: category_slug
          in: path
          description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                preference:
                  type: string
                  description: 'choose one of the options: `opt_in` if the user has allowed notification in this category and `opt_out` if user wants to discontinue notification in this category'
                  default: opt_in
                opt_out_channels:
                  type: array
                  description: Add array of channels if user wants to unsubscribe from particular channels in this category. Add channels as `email`, `sms`, `whatsapp`, `androidpush`, `inbox`, `iospush`, `slack`, `webpush`
                  items:
                    type: string
                opt_in_channels:
                  type: array
                  description: You can either pass opt_out_channels when user opts out from a channel in the category or opt_in_channels when user opts in to a channel in the category. Add channels as `email`, `sms`, `whatsapp`, `androidpush`, `inbox`, `iospush`, `slack`, `webpush`
                  items:
                    type: string
                digest_schedule:
                  type: object
                  nullable: true
                  description: >
                    Object's preferred digest schedule for this category. Set to `null` to fall back to tenant's default.
                  properties:
                    id:
                      type: string
                      description: ID of the selected digest schedule option
                    time:
                      type: string
                      description: "Override time if applicable and edit_policy is `editable`. Format: HH:MM"
                    dtstart:
                      type: string
                      format: date-time
                      description: Override start date if applicable and edit_policy is `editable`
                    weekdays:
                      type: array
                      description: Override weekdays if applicable and edit_policy is `editable`
                      items:
                        type: string
                        enum: ["mo", "tu", "we", "th", "fr", "sa", "su"]
                    monthdays:
                      type: array
                      description: Override monthdays if applicable and edit_policy is `editable`
                      items:
                        type: object
                        properties:
                          pos:
                            description: "Position in the month (1-31; use a negative value to count from the end)."
                            type: integer
                          day:
                            description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                            type: string
                properties:
                  type: array
                  description: Override values for category condition properties. Only properties with edit_policy `editable` can be overridden. The datatype of value must match the property's `value_type`.
                  items:
                    type: object
                    properties:
                      key:
                        type: string
                        description: Property key identifier
                      value:
                        description: Override value for the property
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "name": "Weekly Activity Digest",
                    "category": "weekly-activity-digest",
                    "description": "Summary of recent activity in your workspace",
                    "tags": [
                      "digest",
                      "activity"
                    ],
                    "effective_tags": [
                      "digest",
                      "activity"
                    ],
                    "original_preference": "opt_in",
                    "preference": "opt_in",
                    "is_editable": true,
                    "channels": [
                      {
                        "channel": "email",
                        "preference": "opt_in",
                        "is_editable": true
                      }
                    ],
                    "digest_schedule_options": {
                      "options": [
                        {
                          "id": "instant",
                          "label": "Instant",
                          "frequency": "instantly",
                          "is_default": false,
                          "is_user_selected": false
                        },
                        {
                          "id": "daily-summary",
                          "label": "Daily summary at 9:00 AM",
                          "frequency": "daily",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "09:00",
                            "value": ""
                          },
                          "is_default": true,
                          "is_user_selected": false
                        },
                        {
                          "id": "weekly-on-weekdays",
                          "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                          "frequency": "weekly_mo2fr",
                          "interval": 1,
                          "time": {
                            "edit_policy": "editable",
                            "default_value": "09:00",
                            "value": "10:00"
                          },
                          "weekdays": {
                            "edit_policy": "locked",
                            "default_value": ["mo", "tu", "we", "th", "fr"],
                            "value": ["mo", "tu", "we", "th", "fr"]
                          },
                          "is_default": false,
                          "is_user_selected": true
                        }
                      ]
                    },
                    "digest_schedule": {
                      "id": "weekly-on-weekdays",
                      "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                      "frequency": "weekly_mo2fr",
                      "interval": 1,
                      "time": "10:00",
                      "weekdays": ["mo", "tu", "we", "th", "fr"],
                      "is_default": false,
                      "is_user_selected": true
                    },
                    "properties": [
                      {
                        "key": "threshold",
                        "label": "Minimum activity count",
                        "value_type": "string",
                        "default_value": "100",
                        "is_optional": false,
                        "edit_policy": "editable",
                        "is_overridden": true,
                        "value": "500"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  name:
                    type: string
                    description: preference category name
                    example: "Weekly Activity Digest"
                  category:
                    type: string
                    description: unique preference category slug
                    example: "weekly-activity-digest"
                  description:
                    description: Description of the notification category.
                    type: string
                    example: "Summary of recent activity in your workspace"
                  tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  effective_tags:
                    type: array
                    nullable: true
                    items:
                      type: string
                  original_preference:
                    type: string
                    enum: ["opt_in", "opt_out"]
                    description: default preference of the category
                    example: "opt_in"
                  preference:
                    type: string
                    enum: ["opt_in", "opt_out"]
                    description: final preference of the category
                    example: "opt_in"
                  is_editable:
                    type: boolean
                    description: "false for categories where default preference is set to can't unsubscribe"
                    example: true
                  channels:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          example: "email"
                        preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          example: "opt_in"
                        is_editable:
                          type: boolean
                  digest_schedule_options:
                    type: object
                    nullable: true
                    description: All available digest schedule options for this category
                    properties:
                      options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              description: "Time of day to send the digest, with its edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                value:
                                  type: string
                                  nullable: true
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: object
                            dtstart:
                              description: "Start datetime from which the recurring schedule is calculated, with edit policy and value."
                              type: object
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                value:
                                  type: string
                                  nullable: true
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                            is_user_selected:
                              type: boolean
                  digest_schedule:
                    type: object
                    nullable: true
                    description: The currently active digest schedule selection
                    properties:
                      id:
                        description: "Unique identifier of the digest schedule option."
                        type: string
                      label:
                        description: "Display label shown to the recipient."
                        type: string
                      frequency:
                        description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                        type: string
                      interval:
                        description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                        type: integer
                      time:
                        description: "Time of day to send the digest, with its edit policy and value."
                        type: string
                      weekdays:
                        description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                        type: array
                        items:
                          type: string
                      monthdays:
                        description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                        type: array
                        items:
                          type: object
                      is_default:
                        description: "Whether this option is the default selection."
                        type: boolean
                      is_user_selected:
                        type: boolean
                  properties:
                    type: array
                    nullable: true
                    description: Category condition properties with overrides
                    items:
                      type: object
                      properties:
                        key:
                          description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                          type: string
                        label:
                          description: "Display label shown to the recipient."
                          type: string
                        value_type:
                          description: "Data type of the property value."
                          type: string
                        default_value:
                          description: "Default value applied when not overridden."
                          type: string
                        is_optional:
                          description: "Whether this property is optional."
                          type: boolean
                        edit_policy:
                          description: "`editable` means the value can be overridden; `locked` means it is fixed."
                          type: string
                          enum: ["locked", "editable"]
                        is_overridden:
                          type: boolean
                        value:
                          description: Overridden value, if any
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "category '_category_slug_' not found"
                  }
              schema:
                type: object
                description: error code and message detailing the error
      deprecated: false
    get:
      summary: Single Category
      security:
        - BearerAuth: []
      description: API to fetch object preferences for a given category.
      operationId: fetch-object-preference-single-category
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch object preferences for a particular tenant
          schema:
            type: string
        - name: show_opt_out_channels
          in: query
          description: set this flag to `true` if you want to fetch channel list for opt-out categories.
          schema:
            type: boolean
            default: false
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: category_slug
          in: path
          description: notification category slug. You can get this from Notification Categories page on SuprSend dashboard -> Settings page
          schema:
            type: string
          required: true
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file.

            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "name": "Newsletter",
                    "category": "newsletter",
                    "description": "Send me updates on new product updates",
                    "original_preference": null,
                    "preference": "opt_in",
                    "is_editable": false,
                    "channels": [
                      {
                        "channel": "email",
                        "preference": "opt_in",
                        "is_editable": false
                      },
                      {
                        "channel": "ms_teams",
                        "preference": "opt_in",
                        "is_editable": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  name:
                    description: Display name of the notification category.
                    type: string
                    example: Newsletter
                  category:
                    description: Slug of the notification category.
                    type: string
                    example: newsletter
                  description:
                    description: Description of the notification category.
                    type: string
                    example: Send me updates on new product updates
                  original_preference:
                    description: Category default preference, before the recipient's override is applied.
                    type: string
                    enum: ["opt_in", "opt_out"]
                    nullable: true
                    example: null
                  preference:
                    type: string
                    enum: ["opt_in", "opt_out"]
                    example: opt_in
                  is_editable:
                    type: boolean
                    example: false
                  channels:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          description: channel name
                          example: email
                        preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          description: user preference for this channel (opt_in, opt_out)
                          example: opt_in
                        is_editable:
                          type: boolean
                          description: whether the user can edit this channel preference
                          example: false
                  digest_schedule_options:
                    type: object
                    nullable: true
                    description: All digest schedule options configured on the category, with the recipient's current selection. `null` if digest schedule is not enabled on the category.
                    properties:
                      options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              type: string
                              description: Display label shown to the recipient for this option.
                            frequency:
                              type: string
                              description: Frequency of the digest schedule.
                              enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              type: object
                              description: Time of day to send the digest, with its edit policy and the recipient's override.
                              properties:
                                edit_policy:
                                  type: string
                                  enum: ["locked", "editable"]
                                  description: "`editable` means the recipient can change this value; `locked` means it is fixed."
                                default_value:
                                  type: string
                                  description: "Default time in HH:MM (24-hour) format."
                                value:
                                  type: string
                                  nullable: true
                                  description: Recipient's overridden value, if any.
                            weekdays:
                              type: object
                              description: Days of the week to send on (for `weekly` frequency), with edit policy and recipient override.
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: string
                            monthdays:
                              type: object
                              description: Days of the month to send on (for `monthly` frequency), with edit policy and recipient override.
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      pos:
                                        description: "Position in the month (1-31; use a negative value to count from the end)."
                                        type: integer
                                      day:
                                        description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                        type: string
                                value:
                                  type: array
                                  nullable: true
                                  items:
                                    type: object
                            dtstart:
                              type: object
                              description: Start datetime from which the recurring schedule is calculated, with edit policy and recipient override.
                              properties:
                                edit_policy:
                                  description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                  type: string
                                  enum: ["locked", "editable"]
                                default_value:
                                  description: "Default value applied when not overridden."
                                  type: string
                                  format: date-time
                                value:
                                  type: string
                                  nullable: true
                            is_default:
                              type: boolean
                              description: Whether this option is the category default.
                            is_user_selected:
                              type: boolean
                              description: Whether the recipient has selected this option.
                  digest_schedule:
                    type: object
                    nullable: true
                    description: The recipient's currently active digest schedule, resolved in order recipient selection -> tenant default -> category default. `null` if digest schedule is not enabled on the category.
                    properties:
                      id:
                        description: "Unique identifier of the digest schedule option."
                        type: string
                      label:
                        description: "Display label shown to the recipient."
                        type: string
                      frequency:
                        description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                        type: string
                        enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                      interval:
                        description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                        type: integer
                      time:
                        type: string
                        description: "Resolved time in HH:MM (24-hour) format."
                      weekdays:
                        description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                        type: array
                        items:
                          type: string
                      monthdays:
                        description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                        type: array
                        items:
                          type: object
                          properties:
                            pos:
                              description: "Position in the month (1-31; use a negative value to count from the end)."
                              type: integer
                            day:
                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                              type: string
                      is_default:
                        description: "Whether this option is the default selection."
                        type: boolean
                      is_user_selected:
                        type: boolean
                  properties:
                    type: array
                    nullable: true
                    description: Category condition properties with the recipient's overrides. Referenced in workflows as `$category.properties.<key>`.
                    items:
                      type: object
                      properties:
                        key:
                          description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                          type: string
                        label:
                          type: string
                          description: Display label for the property.
                        value_type:
                          description: "Data type of the property value."
                          type: string
                          enum: ["integer", "string", "string_choice", "list_choice", "string_dynamic", "list_dynamic"]
                        default_value:
                          nullable: true
                          description: Default value applied when the recipient has not set a value.
                        is_optional:
                          description: "Whether this property is optional."
                          type: boolean
                        edit_policy:
                          type: string
                          enum: ["locked", "editable"]
                          description: "`editable` means the recipient can override the value; `locked` means it is fixed."
                        is_overridden:
                          type: boolean
                          description: Whether the recipient has overridden the default value.
                        value:
                          nullable: true
                          description: Recipient-overridden value, if any.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "category 'category_slug' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "category 'category_slug' not found"
      deprecated: false
  /v1/object/{object_type}/{id}/preference/channel_preference/:
    patch:
      summary: Overall Channel level
      security:
        - BearerAuth: []
      description: API to update object preferences across all channels.
      operationId: object-preference-channel
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch user preferences for a particular tenant
          schema:
            type: string
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channel_preferences:
                  type: array
                  description: Use this to update channel level user preferences. Set `is_restricted - true` if the channel is opted_out by the user. This will only send critical notifications to the user which can't be opted out
                  items:
                    properties:
                      channel:
                        type: string
                        description: Add channel as `email`, `inbox`, `sms`, `whatsapp`, `androidpush`, `slack`, `iospush`, `webpush`
                        default: email
                      is_restricted:
                        type: boolean
                        description: set `is_restricted = true` if user wants to receive notification in mandatory categories on this channel. Mandatory categories are `can't unsubscribe` categories and the above channel is added as `mandatory channel` in that category
                        default: false
                    type: object
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "channel_preferences": [
                      {
                        "channel": "email",
                        "is_restricted": true
                      },
                      {
                        "channel": "inbox",
                        "is_restricted": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          example: "email"
                        is_restricted:
                          type: boolean
                          example: "true"
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'obj_type/obj_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "object 'obj_type/obj_id' not found"
      deprecated: false
    get:
      summary: All Channels
      security:
        - BearerAuth: []
      description: API to retrieve all channel preferences for a given object.
      operationId: fetch-object-preference-all-channels
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch object preferences for a particular tenant
          schema:
            type: string
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "channel_preferences": [
                      {
                        "channel": "androidpush",
                        "is_restricted": false
                      },
                      {
                        "channel": "email",
                        "is_restricted": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          description: channel name
                          example: "androidpush"
                        is_restricted:
                          type: boolean
                          description: True means notification will be sent in categories where this channel is marked as mandatory channel. False means opt_in on channel.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'obj_type/obj_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "object 'obj_type/obj_id' not found"
      deprecated: false
  /v1/object/{object_type}/{id}/preference/:
    get:
      summary: Full Preference
      security:
        - BearerAuth: []
      description: API to fetch object preferences across all channels and categories.
      operationId: fetch-object-full-preference
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch object preferences for a particular tenant
          schema:
            type: string
        - name: show_opt_out_channels
          in: query
          description: set this flag to `true` if you want to fetch channel list for opt-out categories.
          schema:
            type: boolean
            default: false
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: tags
          in: query
          description: >
            Filter preference categories with tags assigned to them. Used to filter preference categories relevant to the user on UI based on their roles, department or teams.

            You can apply single tag filter like `tags=tag1` or build nested conditions using logical operators - `and`, `or`, `not`, `exists`.


            Example:

            ```

            tags=admin

            tags={"or":[{"and":["admin","sales"]},{"and":["admin","manager"]}]}

            tags={"not":"admin"}

            tags={"exists":true}
          schema:
            type: string
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file.
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "sections": [
                      {
                        "subcategories": [
                          {
                            "name": "Newsletter",
                            "category": "newsletter",
                            "description": "Send me updates on new product updates",
                            "preference": "opt_in",
                            "is_editable": true,
                            "channels": [
                              { "channel": "androidpush", "preference": "opt_in", "is_editable": true },
                              { "channel": "email", "preference": "opt_in", "is_editable": true }
                            ]
                          }
                        ]
                      }
                    ],
                    "channel_preferences": [
                      { "channel": "email", "is_restricted": false }
                    ]
                  }
              schema:
                type: object
                properties:
                  sections:
                    type: array
                    items:
                      type: object
                      properties:
                        subcategories:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                description: Display name of the notification category.
                                type: string
                                example: "Newsletter"
                              category:
                                description: Slug of the notification category.
                                type: string
                                example: "newsletter"
                              description:
                                description: Description of the notification category.
                                type: string
                                example: "Send me updates on new product updates"
                              preference:
                                type: string
                                enum: ["opt_in", "opt_out"]
                                example: "opt_in"
                              is_editable:
                                type: boolean
                                description: "false when category default preference is set to can't unsubscribe"
                              channels:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    channel:
                                      type: string
                                      example: "email"
                                    preference:
                                      type: string
                                      enum: ["opt_in", "opt_out"]
                                      example: "opt_in"
                                    is_editable:
                                      type: boolean
                                      description: "false when category default preference is set to can't unsubscribe"
                              digest_schedule_options:
                                type: object
                                nullable: true
                                description: All digest schedule options configured on the category, with the recipient's current selection. `null` if digest schedule is not enabled on the category.
                                properties:
                                  options:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          description: "Unique identifier of the digest schedule option."
                                          type: string
                                        label:
                                          type: string
                                          description: Display label shown to the recipient for this option.
                                        frequency:
                                          type: string
                                          description: Frequency of the digest schedule.
                                          enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                                        interval:
                                          description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                          type: integer
                                        time:
                                          type: object
                                          description: Time of day to send the digest, with its edit policy and the recipient's override.
                                          properties:
                                            edit_policy:
                                              type: string
                                              enum: ["locked", "editable"]
                                              description: "`editable` means the recipient can change this value; `locked` means it is fixed."
                                            default_value:
                                              type: string
                                              description: "Default time in HH:MM (24-hour) format."
                                            value:
                                              type: string
                                              nullable: true
                                              description: Recipient's overridden value, if any.
                                        weekdays:
                                          type: object
                                          description: Days of the week to send on (for `weekly` frequency), with edit policy and recipient override.
                                          properties:
                                            edit_policy:
                                              description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                              type: string
                                              enum: ["locked", "editable"]
                                            default_value:
                                              description: "Default value applied when not overridden."
                                              type: array
                                              items:
                                                type: string
                                            value:
                                              type: array
                                              nullable: true
                                              items:
                                                type: string
                                        monthdays:
                                          type: object
                                          description: Days of the month to send on (for `monthly` frequency), with edit policy and recipient override.
                                          properties:
                                            edit_policy:
                                              description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                              type: string
                                              enum: ["locked", "editable"]
                                            default_value:
                                              description: "Default value applied when not overridden."
                                              type: array
                                              items:
                                                type: object
                                                properties:
                                                  pos:
                                                    description: "Position in the month (1-31; use a negative value to count from the end)."
                                                    type: integer
                                                  day:
                                                    description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                                    type: string
                                            value:
                                              type: array
                                              nullable: true
                                              items:
                                                type: object
                                        dtstart:
                                          type: object
                                          description: Start datetime from which the recurring schedule is calculated, with edit policy and recipient override.
                                          properties:
                                            edit_policy:
                                              description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                              type: string
                                              enum: ["locked", "editable"]
                                            default_value:
                                              description: "Default value applied when not overridden."
                                              type: string
                                              format: date-time
                                            value:
                                              type: string
                                              nullable: true
                                        is_default:
                                          type: boolean
                                          description: Whether this option is the category default.
                                        is_user_selected:
                                          type: boolean
                                          description: Whether the recipient has selected this option.
                              digest_schedule:
                                type: object
                                nullable: true
                                description: The recipient's currently active digest schedule, resolved in order recipient selection -> tenant default -> category default. `null` if digest schedule is not enabled on the category.
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                    enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    type: string
                                    description: "Resolved time in HH:MM (24-hour) format."
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: array
                                    items:
                                      type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        pos:
                                          description: "Position in the month (1-31; use a negative value to count from the end)."
                                          type: integer
                                        day:
                                          description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                          type: string
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                                  is_user_selected:
                                    type: boolean
                              properties:
                                type: array
                                nullable: true
                                description: Category condition properties with the recipient's overrides. Referenced in workflows as `$category.properties.<key>`.
                                items:
                                  type: object
                                  properties:
                                    key:
                                      description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                      type: string
                                    label:
                                      type: string
                                      description: Display label for the property.
                                    value_type:
                                      description: "Data type of the property value."
                                      type: string
                                      enum: ["integer", "string", "string_choice", "list_choice", "string_dynamic", "list_dynamic"]
                                    default_value:
                                      nullable: true
                                      description: Default value applied when the recipient has not set a value.
                                    is_optional:
                                      description: "Whether this property is optional."
                                      type: boolean
                                    edit_policy:
                                      type: string
                                      enum: ["locked", "editable"]
                                      description: "`editable` means the recipient can override the value; `locked` means it is fixed."
                                    is_overridden:
                                      type: boolean
                                      description: Whether the recipient has overridden the default value.
                                    value:
                                      nullable: true
                                      description: Recipient-overridden value, if any.
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                          description: channel name
                          example: "androidpush"
                        is_restricted:
                          type: boolean
                          description: "True means notification will be sent in categories where this channel is marked as mandatory channel. False means opt_in on channel."
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'object_type/id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "object 'object_type/id' not found"
      deprecated: false
    patch:
      summary: Update Object Full Preference
      security:
        - BearerAuth: []
      description: API to update object preferences across all channels and categories with translated names and descriptions in the response.
      operationId: update-object-full-preference
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to update object preferences for a particular tenant
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channel_preferences:
                  type: array
                  description: Use this to update channel level object preferences. Set `is_restricted - true` if the channel is opted_out. This will only send critical notifications which can't be opted out
                  items:
                    type: object
                    properties:
                      channel:
                        type: string
                        description: Add channel as `email`, `inbox`, `sms`, `whatsapp`, `androidpush`, `slack`, `iospush`, `webpush`
                      is_restricted:
                        type: boolean
                        description: set `is_restricted = true` if object wants to receive notification in mandatory categories on this channel. Mandatory categories are `can't unsubscribe` categories and the above channel is added as `mandatory channel` in that category
                categories:
                  type: array
                  description: Use this to update object preference across categories and channels inside a category.
                  items:
                    type: object
                    properties:
                      category:
                        type: string
                        description: notification category slug
                      preference:
                        type: string
                        enum: ["opt_in", "opt_out"]
                        description: set `opt_in` to turn on notifications on all or selected channels, `opt_out` to turn-off notifications
                      opt_out_channels:
                        type: array
                        description: List of channels to opt-out from this category
                        items:
                          type: string
                      opt_in_channels:
                        type: array
                        description: List of channels to opt-in for this category
                        items:
                          type: string
                      digest_schedule:
                        type: object
                        nullable: true
                        description: >
                          Object's preferred digest schedule for this category. Set to `null` to fall back to tenant's default.
                        properties:
                          id:
                            type: string
                            description: ID of the selected digest schedule option
                          time:
                            type: string
                            description: "Override time if applicable and edit_policy is `editable`. Format: HH:MM"
                          dtstart:
                            type: string
                            format: date-time
                            description: Override start date if applicable and edit_policy is `editable`
                          weekdays:
                            type: array
                            description: Override weekdays if applicable and edit_policy is `editable`
                            items:
                              type: string
                              enum: ["mo", "tu", "we", "th", "fr", "sa", "su"]
                          monthdays:
                            type: array
                            description: Override monthdays if applicable and edit_policy is `editable`
                            items:
                              type: object
                              properties:
                                pos:
                                  description: "Position in the month (1-31; use a negative value to count from the end)."
                                  type: integer
                                day:
                                  description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                  type: string
                      properties:
                        type: array
                        description: Override values for category condition properties. Only properties with edit_policy `editable` can be overridden.
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                              description: Property key identifier
                            value:
                              description: Override value for the property
            examples:
              Update Preferences:
                value: {
                  "channel_preferences": [
                    {
                      "channel": "email",
                      "is_restricted": false
                    }
                  ],
                  "categories": [
                    {
                      "category": "weekly-activity-digest",
                      "preference": "opt_in",
                      "digest_schedule": {
                        "id": "weekly-on-weekdays",
                        "time": "10:00"
                      },
                      "properties": [
                        {
                          "key": "threshold",
                          "value": "500"
                        }
                      ]
                    }
                  ]
                }
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "sections": [
                      {
                        "name": null,
                        "slug": null,
                        "subcategories": [
                          {
                            "name": "Weekly Activity Digest",
                            "category": "weekly-activity-digest",
                            "description": "Summary of recent activity in your workspace",
                            "original_preference": "opt_in",
                            "preference": "opt_in",
                            "is_editable": true,
                            "channels": [
                              {
                                "channel": "email",
                                "preference": "opt_in",
                                "is_editable": true
                              }
                            ],
                            "digest_schedule": {
                              "id": "weekly-on-weekdays",
                              "label": "Every week on Mon\u2013Fri \u00b7 time set by recipient (default: 9:00 AM)",
                              "frequency": "weekly_mo2fr",
                              "interval": 1,
                              "time": "10:00",
                              "weekdays": ["mo", "tu", "we", "th", "fr"],
                              "is_default": false,
                              "is_user_selected": true
                            },
                            "properties": [
                              {
                                "key": "threshold",
                                "label": "Minimum activity count",
                                "value_type": "string",
                                "default_value": "100",
                                "is_optional": false,
                                "edit_policy": "editable",
                                "is_overridden": true,
                                "value": "500"
                              }
                            ]
                          }
                        ]
                      }
                    ],
                    "channel_preferences": [
                      {
                        "channel": "email",
                        "is_restricted": false
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  sections:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          description: Display name of the notification category.
                          type: string
                          nullable: true
                        slug:
                          type: string
                          nullable: true
                        description:
                          description: Description of the notification category.
                          type: string
                          nullable: true
                        tags:
                          type: array
                          nullable: true
                          items:
                            type: string
                        subcategories:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                description: Display name of the notification category.
                                type: string
                              category:
                                description: Slug of the notification category.
                                type: string
                              description:
                                description: Description of the notification category.
                                type: string
                                nullable: true
                              tags:
                                type: array
                                nullable: true
                                items:
                                  type: string
                              effective_tags:
                                type: array
                                nullable: true
                                items:
                                  type: string
                              original_preference:
                                description: Category default preference, before the recipient's override is applied.
                                type: string
                                nullable: true
                                enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                              preference:
                                type: string
                                enum: ["opt_in", "opt_out", "cant_unsubscribe"]
                              is_editable:
                                type: boolean
                              channels:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    channel:
                                      type: string
                                    preference:
                                      type: string
                                      enum: ["opt_in", "opt_out"]
                                    is_editable:
                                      type: boolean
                              digest_schedule:
                                type: object
                                nullable: true
                                description: The currently active digest schedule selection
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    description: "Display label shown to the recipient."
                                    type: string
                                  frequency:
                                    description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                                    type: string
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    description: "Time of day to send the digest, with its edit policy and value."
                                    type: string
                                  weekdays:
                                    description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                                    type: array
                                    items:
                                      type: string
                                  monthdays:
                                    description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                                    type: array
                                    items:
                                      type: object
                                  is_default:
                                    description: "Whether this option is the default selection."
                                    type: boolean
                                  is_user_selected:
                                    type: boolean
                              properties:
                                type: array
                                nullable: true
                                description: Category condition properties with overrides
                                items:
                                  type: object
                                  properties:
                                    key:
                                      description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                      type: string
                                    label:
                                      description: "Display label shown to the recipient."
                                      type: string
                                    value_type:
                                      description: "Data type of the property value."
                                      type: string
                                    default_value:
                                      description: "Default value applied when not overridden."
                                      type: string
                                    is_optional:
                                      description: "Whether this property is optional."
                                      type: boolean
                                    edit_policy:
                                      description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                      type: string
                                      enum: ["locked", "editable"]
                                    is_overridden:
                                      type: boolean
                                    value:
                                      description: Overridden value, if any
                  channel_preferences:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: string
                        is_restricted:
                          type: boolean
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'object_type/id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "object 'object_type/id' not found"
      deprecated: false
  /v1/object/{object_type}/{id}/preference/category/:
    get:
      summary: All Categories
      security:
        - BearerAuth: []
      description: API to fetch user preferences across all categories.
      operationId: fetch-object-preference-all-categories
      parameters:
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: query
          description: to fetch object preferences for a particular tenant
          schema:
            type: string
        - name: show_opt_out_channels
          in: query
          description: set this flag to `true` if you want to fetch channel list for opt-out categories.
          schema:
            type: boolean
            default: false
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: tags
          in: query
          description: >
            Filter preference categories with tags assigned to them. Used to filter preference categories relevant to the user on UI based on their roles, department or teams.

            You can apply single tag filter like `tags=tag1` or build nested conditions using logical operators - `and`, `or`, `not`, `exists`.


            Example:

            ```

            tags=admin

            tags={"or":[{"and":["admin","sales"]},{"and":["admin","manager"]}]}

            tags={"not":"admin"}

            tags={"exists":true}
          schema:
            type: string
        - name: locale
          in: query
          description: >
            Locale code (e.g., `es`, `fr`, `de`, `ja`, `es-AR`) to fetch preference translations in user's locale.
            When provided, the API looks for category and section names and descriptions in the respective locale file. 
            
            If a translation is missing for the requested locale, the system automatically falls back in this order: `locale-region` (e.g., `es-AR`) → `locale` (e.g., `es`) → `en` (English - always available).
          schema:
            type: string
          example: "es"
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 12,
                      "limit": 10,
                      "offset": 0
                    },
                    "results": [
                      {
                        "name": "Newsletter",
                        "category": "newsletter",
                        "description": "Send me updates on new product updates",
                        "original_preference": null,
                        "preference": "opt_in",
                        "is_editable": false,
                        "channels": [
                          {
                            "channel": "email",
                            "preference": "opt_in",
                            "is_editable": false
                          },
                          {
                            "channel": "ms_teams",
                            "preference": "opt_in",
                            "is_editable": false
                          }
                        ]
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 12
                      limit:
                        type: integer
                        example: 10
                      offset:
                        type: integer
                        example: 0
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          description: Display name of the notification category.
                          type: string
                          example: Newsletter
                        category:
                          description: Slug of the notification category.
                          type: string
                          example: newsletter
                        description:
                          description: Description of the notification category.
                          type: string
                          example: Send me updates on new product updates
                        original_preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          description: "default preference of the category"
                          nullable: true
                          example: null
                        preference:
                          type: string
                          enum: ["opt_in", "opt_out"]
                          example: opt_in
                        is_editable:
                          type: boolean
                          description: "false when category default preference is set to `can't unsubscribe`"
                          example: false
                        channels:
                          type: array
                          description: "channel level preference in the category"
                          items:
                            type: object
                            properties:
                              channel:
                                type: string
                                description: channel name
                                example: email
                              preference:
                                type: string
                                enum: ["opt_in", "opt_out"]
                                description: user preference for this channel (opt_in, opt_out)
                                example: opt_in
                              is_editable:
                                type: boolean
                                description: whether the user can edit this channel preference
                                example: false
                        digest_schedule_options:
                          type: object
                          nullable: true
                          description: All digest schedule options configured on the category, with the recipient's current selection. `null` if digest schedule is not enabled on the category.
                          properties:
                            options:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    description: "Unique identifier of the digest schedule option."
                                    type: string
                                  label:
                                    type: string
                                    description: Display label shown to the recipient for this option.
                                  frequency:
                                    type: string
                                    description: Frequency of the digest schedule.
                                    enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                                  interval:
                                    description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                                    type: integer
                                  time:
                                    type: object
                                    description: Time of day to send the digest, with its edit policy and the recipient's override.
                                    properties:
                                      edit_policy:
                                        type: string
                                        enum: ["locked", "editable"]
                                        description: "`editable` means the recipient can change this value; `locked` means it is fixed."
                                      default_value:
                                        type: string
                                        description: "Default time in HH:MM (24-hour) format."
                                      value:
                                        type: string
                                        nullable: true
                                        description: Recipient's overridden value, if any.
                                  weekdays:
                                    type: object
                                    description: Days of the week to send on (for `weekly` frequency), with edit policy and recipient override.
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: string
                                      value:
                                        type: array
                                        nullable: true
                                        items:
                                          type: string
                                  monthdays:
                                    type: object
                                    description: Days of the month to send on (for `monthly` frequency), with edit policy and recipient override.
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            pos:
                                              description: "Position in the month (1-31; use a negative value to count from the end)."
                                              type: integer
                                            day:
                                              description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                              type: string
                                      value:
                                        type: array
                                        nullable: true
                                        items:
                                          type: object
                                  dtstart:
                                    type: object
                                    description: Start datetime from which the recurring schedule is calculated, with edit policy and recipient override.
                                    properties:
                                      edit_policy:
                                        description: "`editable` means the value can be overridden; `locked` means it is fixed."
                                        type: string
                                        enum: ["locked", "editable"]
                                      default_value:
                                        description: "Default value applied when not overridden."
                                        type: string
                                        format: date-time
                                      value:
                                        type: string
                                        nullable: true
                                  is_default:
                                    type: boolean
                                    description: Whether this option is the category default.
                                  is_user_selected:
                                    type: boolean
                                    description: Whether the recipient has selected this option.
                        digest_schedule:
                          type: object
                          nullable: true
                          description: The recipient's currently active digest schedule, resolved in order recipient selection -> tenant default -> category default. `null` if digest schedule is not enabled on the category.
                          properties:
                            id:
                              description: "Unique identifier of the digest schedule option."
                              type: string
                            label:
                              description: "Display label shown to the recipient."
                              type: string
                            frequency:
                              description: "Frequency of the digest schedule (instantly, hourly, daily, weekly, weekly_mo2fr, monthly)."
                              type: string
                              enum: ["instantly", "minutely", "hourly", "daily", "weekly", "weekly_mo2fr", "monthly"]
                            interval:
                              description: "Recurrence multiplier for the frequency (for example, every 2 weeks)."
                              type: integer
                            time:
                              type: string
                              description: "Resolved time in HH:MM (24-hour) format."
                            weekdays:
                              description: "Days of the week to send on (for weekly frequency), with edit policy and value."
                              type: array
                              items:
                                type: string
                            monthdays:
                              description: "Days of the month to send on (for monthly frequency), with edit policy and value."
                              type: array
                              items:
                                type: object
                                properties:
                                  pos:
                                    description: "Position in the month (1-31; use a negative value to count from the end)."
                                    type: integer
                                  day:
                                    description: "Optional day of the week (su, mo, tu, we, th, fr, sa)."
                                    type: string
                            is_default:
                              description: "Whether this option is the default selection."
                              type: boolean
                            is_user_selected:
                              type: boolean
                        properties:
                          type: array
                          nullable: true
                          description: Category condition properties with the recipient's overrides. Referenced in workflows as `$category.properties.<key>`.
                          items:
                            type: object
                            properties:
                              key:
                                description: "Property key identifier, referenced in workflows as `$category.properties.<key>`."
                                type: string
                              label:
                                type: string
                                description: Display label for the property.
                              value_type:
                                description: "Data type of the property value."
                                type: string
                                enum: ["integer", "string", "string_choice", "list_choice", "string_dynamic", "list_dynamic"]
                              default_value:
                                nullable: true
                                description: Default value applied when the recipient has not set a value.
                              is_optional:
                                description: "Whether this property is optional."
                                type: boolean
                              edit_policy:
                                type: string
                                enum: ["locked", "editable"]
                                description: "`editable` means the recipient can override the value; `locked` means it is fixed."
                              is_overridden:
                                type: boolean
                                description: Whether the recipient has overridden the default value.
                              value:
                                nullable: true
                                description: Recipient-overridden value, if any.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'object_type/id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "object 'object_type/id' not found"
      deprecated: false
  /v1/user/{distinct_id}/:
    post:
      summary: Create / Update Users
      security:
        - BearerAuth: []
      description: API to upsert (create if not exists, update if exists) user profile using a `distinct_id`.
      operationId: create-update-users
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST "https://hub.suprsend.com/v1/user/user123/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "$email": ["user@example.com"],
                "$sms": ["+1234567890"],
                "$slack": [{
                  "email_id": "user@example.com",
                  "access_token": "xoxb-..."
                }],
                "$ms_teams": [{
                  "user_id": "teams_user_id_12345",
                  "tenant_id": "tenant_12345",
                  "service_url": "https://smba.trafficmanager.net/amer"
                }]
              }'
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            example:
              $email: ["jsmith@example.com"]
              $sms: ["+1234567890"]
              $whatsapp: ["+1234567890"]
              $inbox: ["4nlPk4XXLcDxxxHQ70xx2Cx24"]
              $webpush: 
                - token: "webpush_token_abc123"
                  endpoint: "https://fcm.googleapis.com/fcm/send/abc123"
                  keys:
                    p256dh: "BNJxwH..."
                    auth: "tBH..."
              $androidpush: ["android_push_token_xyz987"]
              $iospush: ["ios_push_token_lmn456"]
              $slack:
                - user_id: "U01ABCDE2F3"
                  team_id: "T1234567890"
                  access_token: "xoxb-..."
              $ms_teams:
                - user_id: "teams_user_id_12345"
                  tenant_id: "tenant_12345"
                  conversation_id: "conversation_12345"
              $timezone: America/New_York
              $locale: en_GB
              custom_key: custom_value
            schema:
              type: object
              properties:
                $email:
                  type: array
                  items:
                    type: string
                    format: email
                  description: List of email addresses. You can add other channels in the same format by replacing `$email` with the respective channel keys. Supported keys- `$email`, `$sms`, `$whatsapp`, `$inbox`, `$webpush`, `$androidpush`, `$iospush`, `$slack`, `$ms_teams`.
                $sms:
                  type: array
                  items:
                    type: string
                  description: List of phone numbers for SMS
                $whatsapp:
                  type: array
                  items:
                    type: string
                  description: List of phone numbers for WhatsApp
                $inbox:
                  type: array
                  items:
                    type: string
                  description: List of inbox identifiers
                $androidpush:
                  type: array
                  items:
                    type: string
                  description: List of Android Push tokens
                $iospush:
                  type: array
                  items:
                    type: string
                  description: List of iOS Push tokens
                $slack:
                  type: array
                  description: Slack channel configuration
                  items:
                    oneOf:
                      - type: object
                        title: "Slack using email"
                        required: [email, access_token]
                        properties:
                          email:
                            type: string
                            format: email
                            description: User email address
                            example: "user@example.com"
                          access_token:
                            type: string
                            description: Slack bot access token
                            example: "xoxb-XXXXXXXX"
                      - type: object
                        title: "Slack using member ID"
                        required: [user_id, access_token]
                        properties:
                          user_id:
                            type: string
                            description: Slack user ID (U/WXXXXXXXX format)
                            example: "U/WXXXXXXXX"
                          access_token:
                            type: string
                            description: Slack bot access token
                            example: "xoxb-XXXXXX"
                      - type: object
                        title: "Slack using channel"
                        required: [channel, access_token]
                        properties:
                          channel:
                            type: string
                            description: Slack channel ID (CXXXXXXXX format)
                            example: "CXXXXXXXX"
                          access_token:
                            type: string
                            description: Slack bot access token
                            example: "xoxb-XXXXXX"
                      - type: object
                        title: "Slack using incoming webhook"
                        required: [incoming_webhook]
                        properties:
                          incoming_webhook:
                            type: object
                            required: [url]
                            properties:
                              url:
                                type: string
                                format: uri
                                description: Slack incoming webhook URL
                                example: "https://hooks.slack.com/services/TXXXX/BXXXX/XXXXXXX"
                $ms_teams:
                  type: array
                  description: Microsoft Teams channel configuration
                  items:
                    oneOf:
                      - type: object
                        title: "MS Teams using conversation ID"
                        required: [tenant_id, service_url, conversation_id]
                        properties:
                          tenant_id:
                            type: string
                            description: Microsoft Teams tenant ID
                            example: "c1981ab2-9aaf-xxxx-xxxx"
                          service_url:
                            type: string
                            format: uri
                            description: Microsoft Teams service URL
                            example: "https://smba.trafficmanager.net/amer"
                          conversation_id:
                            type: string
                            description: Microsoft Teams conversation ID
                            example: "19:c1524d7c-a06f-456f-8abe-xxxx"
                      - type: object
                        title: "MS Teams using user ID"
                        required: [tenant_id, service_url, user_id]
                        properties:
                          tenant_id:
                            type: string
                            description: Microsoft Teams tenant ID
                            example: "c1981ab2-9aaf-xxxx-xxxx"
                          service_url:
                            type: string
                            format: uri
                            description: Microsoft Teams service URL
                            example: "https://smba.trafficmanager.net/amer"
                          user_id:
                            type: string
                            description: Microsoft Teams user ID
                            example: "29:1nsLcmJ2RKtYH6Cxxxx-xxxx"
                      - type: object
                        title: "MS Teams using incoming webhook"
                        required: [incoming_webhook]
                        properties:
                          incoming_webhook:
                            type: object
                            required: [url]
                            properties:
                              url:
                                type: string
                                format: uri
                                description: Microsoft Teams incoming webhook URL
                                example: "https://wnk1z.webhook.office.com/webhookb2/XXXXXXXXX"
                $timezone:
                  type: string
                  description: User's timezone in [IANA format](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List)
                  example: America/New_York
                $locale:
                  type: string
                  description: User's locale for [translating](https://suprsend.com/docs/translations) template content in SuprSend.
                  example: en_GB
              additionalProperties:
                type: string
                description: Add any additional property in key-value pair
                example: val
      responses:
        '201':
          description: '201'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "distinct_id": "_distinct_id_",
                    "properties": {
                      "$locale": "en_GB",
                      "$timezone": "America/New_York"
                    },
                    "created_at": "2025-04-04T21:37:36.712496+00:00",
                    "updated_at": "2025-04-04T21:37:36.743167+00:00",
                    "$email": [
                      {
                        "value": "john@example.com",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ],
                    "$inbox": [
                      {
                        "value": "4nlPk4t4kurG5kChOELB8Q1LcDI9DHzHQ70st2E2C24",
                        "id_provider": "suprsend",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ],
                    "$sms": [
                      {
                        "value": "+1234567890",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ],
                    "$slack": [
                      {
                        "value": {
                          "email_id": "user@example.com",
                          "access_token": "xoxb-..."
                        },
                        "status": "active",
                        "perma_status": "active"
                      }
                    ],
                    "$ms_teams": [
                      {
                        "value": {
                          "user_id": "teams_user_id_12345",
                          "tenant_id": "tenant_12345",
                          "service_url": "https://smba.trafficmanager.net/amer"
                        },
                        "status": "active",
                        "perma_status": "active"
                      }
                    ]
                    }
              schema:
                type: object
                properties:
                  distinct_id:
                    type: string
                    description: Unique identifier of the user.
                    example: _distinct_id_
                  properties:
                    type: object
                    description: all user properties in key-value pair. SuprSend reserved properties start with $
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was created.
                    example: 2025-04-04T09:55:12.397856+00:00
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was last updated.
                    example: 2025-04-04T09:55:12.422388+00:00
                  $<channel>:
                    type: array
                    description: List of active communication channels for the user.
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: channel value
                        status:
                          type: string
                          description: Current status of the channel (active or inactive).
                          example: active
                        perma_status:
                          type: string
                          description: active/disabled. Perma_status is marked disabled in case of hard bounce on the channel.
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 400,
                    "message": "invalid_request_error"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code indicating the error.
                  message:
                    type: string
                    description: Description of the error type.
      deprecated: false
    get:
      summary: Fetch User by id
      security:
        - BearerAuth: []
      description: API to fetch user object by passing it's unique `distinct_id`.
      operationId: fetch-user-profile
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "distinct_id": "_distinct_id_",
                    "properties": {
                      "$locale": "en_GB",
                      "$timezone": "America/New_York"
                    },
                    "created_at": "2025-04-04T21:37:36.712496+00:00",
                    "updated_at": "2025-04-04T21:37:36.743167+00:00",
                    "$email": [
                      {
                        "value": "john@example.com",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ],
                    "$inbox": [
                      {
                        "value": "4nlPk4t4kurG5kChOELB8Q1LcDI9DHzHQ70st2E2C24",
                        "id_provider": "suprsend",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ]
                    }
              schema:
                type: object
                properties:
                  distinct_id:
                    type: string
                    description: Unique identifier of the user.
                    example: _distinct_id_
                  properties:
                    type: object
                    description: all user properties in key-value pair. SuprSend reserved properties start with $
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was created.
                    example: 2025-04-04T09:55:12.397856+00:00
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was last updated.
                    example: 2025-04-04T09:55:12.422388+00:00
                  $<channel>:
                    type: array
                    description: List of active communication channels for the user.
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: channel value
                        status:
                          type: string
                          description: Current status of the channel (active or inactive).
                          example: active
                        perma_status:
                          type: string
                          description: active/disabled. Perma_status is marked disabled in case of hard bounce on the channel.
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 400,
                    "message": "invalid_request_error"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code indicating the error.
                  message:
                    type: string
                    description: Description of the error type.
      deprecated: false
    delete:
      summary: Delete user
      security:
        - BearerAuth: []
      description: API to permanently delete a user from SuprSend by passing `distinct_id`.
      operationId: delete-user
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system
          schema:
            type: string
          required: true
      responses:
        '204':
          description: '204 - No Content'
        '404':
          description: '404'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "user [distinct_id: 'user1'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code indicating the error.
                    example: 404
                  message:
                    type: string
                    description: Description of the error.
                    example: "user [distinct_id: 'user1'] not found"
      deprecated: false
    patch:
      summary: Edit User Profile
      security:
        - BearerAuth: []
      description: API to edit (add/remove) properties and communication-channels for a user.
      operationId: edit-user-profile
      x-codeSamples:
        - lang: cURL
          label: Edit User Profile
          source: |
            curl -X PATCH "https://hub.suprsend.com/v1/user/user123/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "operations": [
                  {
                    "$set": {
                      "name": "John Doe",
                      "$locale": "en_GB",
                      "$timezone": "America/New_York"
                    }
                  },
                  {
                    "$append": {
                      "$email": "john@example.com"
                    }
                  }
                ]
              }'
      parameters:
        - name: distinct_id
          in: path
          description: unique identifier of the user
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                operations:
                  type: array
                  description: |
                    You can use the following operations to edit user profile.
                    - `$set` to add/update a property
                    - `$unset` to delete property/channel
                    - `$append` to insert values in property/channel array
                    - `$remove` to remove values from property/channel array
                    - `$set_once` to remove immutable properties
                    - `$increment` to increase/decrease integer values on further update
                  items:
                    type: object
                    properties:
                      $set:
                        type: object
                        description: |
                          Use this to set user properties like name, location, locale, etc.
                          Example: `{"name":"Marge Simpson","$locale":"en_GB","$timezone":"America/New_York"}`
                        additionalProperties:
                          type: string
                      $unset:
                        type: array
                        description: |
                          Use this to delete channels or properties from user profile.
                          Channels: `$email`, `$sms`, `$whatsapp`, `$androidpush`, `$iospush`, `$slack`, `$webpush`, `$ms_teams`
                          Example: `["$sms", "$whatsapp", "name"]`
                        items:
                          type: string
                      $append:
                        type: object
                        description: |
                          Use this to add communication channels or update array properties in user profile. Available channel keys: `$email`, `$sms`, `$whatsapp`, `$androidpush`, `$iospush`, `$slack`, `$webpush`, `$ms_teams`
                          Example: `{"$email":"user@example.com"}`
                        additionalProperties:
                          type: string
                      $remove:
                        type: object
                        description: |
                          Use this to remove communication channels or remove values from an array in user profile. Available channel keys: `$email`, `$sms`, `$whatsapp`, `$androidpush`, `$iospush`, `$slack`, `$webpush`, `$ms_teams`
                          Example: `{"$email":"user@example.com"}`
                        additionalProperties:
                          type: string
                      $set_once:
                        type: object
                        description: |
                          Use this to set properties which are not set once and not changed on further updates.
                          Example: `{"first_login_at":"2025-01-01T14:00:00Z"}`
                        additionalProperties:
                          type: string
                      $increment:
                        type: object
                        description: |
                          Use this to increase / decrease integer values on further updates
                          Example: `{"login_count":1}`
                        additionalProperties:
                          type: string
      responses:
        '202':
          description: '202'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "distinct_id": "_distinct_id_",
                    "properties": {
                      "name":"Marge Simpson",
                      "$locale": "en_GB",
                      "$timezone": "America/New_York"
                    },
                    "created_at": "2025-04-04T21:37:36.712496+00:00",
                    "updated_at": "2025-04-04T21:37:36.743167+00:00",
                    "$email": [
                      {
                        "value": "john@example.com",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ],
                    "$inbox": [
                      {
                        "value": "4nlPk4t4kurG5kChOELB8Q1LcDI9DHzHQ70st2E2C24",
                        "id_provider": "suprsend",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ]
                    }
              schema:
                type: object
                properties:
                  distinct_id:
                    type: string
                    description: Unique identifier of the user.
                    example: _distinct_id_
                  properties:
                    type: object
                    description: all user properties in key-value pair. SuprSend reserved properties start with $
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was created.
                    example: 2025-04-04T09:55:12.397856+00:00
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was last updated.
                    example: 2025-04-04T09:55:12.422388+00:00
                  $<channel>:
                    type: array
                    description: list of all active channels.
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                          description: channel value
                        status:
                          type: string
                          description: Current status of the channel (active or inactive).
                          example: active
                        perma_status:
                          type: string
                          description: active/disabled. Perma_status is marked disabled in case of hard bounce on the channel.
      deprecated: false
  /v1/user/:
    get:
      summary: List Users
      security:
        - BearerAuth: []
      description: |
        API to list cursor-based paginated list of users in your workspace.

        Pass the optional `tenant_id` query parameter to list only users associated with that tenant. When the filter is applied, each user object in the response also carries a `tenant` block containing the tenant-scoped property and channel overrides for that user.
      operationId: list-users
      parameters:
        - name: tenant_id
          in: query
          required: false
          schema:
            type: string
          description: Filter users associated with the given tenant. When set, each result includes the tenant-scoped `properties` and channel overrides applied for this user under that tenant.
          example: acme-corp
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 1201709,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": true,
                      "after": "01JXXXX99APxxxxxx8Wxxxx1B"
                    },
                    "results": [
                      {
                        "distinct_id": "_distinct_id_",
                        "properties": {
                          "name":"Marge Simpson"
                        },
                        "created_at": "2025-04-04T21:37:36.712496+00:00",
                        "updated_at": "2025-04-04T21:37:36.743167+00:00"
                      }
                    ]
                  }
                Filtered by tenant:
                  value: {
                    "meta": {
                      "count": 1,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": null
                    },
                    "results": [
                      {
                        "distinct_id": "user@example.com",
                        "properties": {
                          "name": "Marge Simpson",
                          "role": "admin"
                        },
                        "created_at": "2025-04-04T21:37:36.712496+00:00",
                        "updated_at": "2026-07-21T09:49:36.383794+00:00",
                        "$email": [
                          {
                            "value": "marge@example.com",
                            "status": "active",
                            "perma_status": "active"
                          }
                        ],
                        "$androidpush": [
                          {
                            "value": "fcm_token_global_abc",
                            "id_provider": "fcm",
                            "status": "active",
                            "perma_status": "active"
                          }
                        ],
                        "tenant": {
                          "tenant_id": "acme-corp",
                          "properties": {
                            "role": "viewer"
                          },
                          "$email": [
                            {
                              "value": "marge@acme.com",
                              "status": "active",
                              "perma_status": "active"
                            }
                          ]
                        }
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    description: Metadata related to pagination.
                    properties:
                      count:
                        type: integer
                        description: Total number of records available.
                        example: 1201709
                      limit:
                        type: integer
                        description: Maximum number of records per page.
                        example: 10
                      has_prev:
                        type: boolean
                        description: Indicates if there is a previous page.
                        example: false
                      before:
                        type: string
                        nullable: true
                        description: Cursor for the previous page.
                        example: null
                      has_next:
                        type: boolean
                        description: Indicates if there is a next page.
                        example: true
                      after:
                        type: string
                        description: Cursor for the next page.
                        example: "01JXXXX99APxxxxxx8Wxxxx1B"
                  results:
                    type: array
                    description: List of users objects
                    items:
                      type: object
                      properties:
                        distinct_id:
                          type: string
                          description: Unique identifier of the user.
                          example: _distinct_id_
                        properties:
                          type: object
                          description: User properties (simplified)
                        created_at:
                          type: string
                          format: date-time
                          description: Timestamp when the user was created.
                          example: "2025-04-04T21:37:36.712496+00:00"
                        updated_at:
                          type: string
                          format: date-time
                          description: Timestamp when the user was last updated.
                          example: "2025-04-04T21:37:36.743167+00:00"
      deprecated: false
  /v1/user/{distinct_id}/merge/:
    post:
      summary: Merge User Profiles
      security:
        - BearerAuth: []
      description: API to merge two user profiles to resolve duplicate user records.
      operationId: merge-users
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of primary user
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                from_user_id:
                  type: string
                  description: Unique identifier of secondary user whose profile needs to be merged into primary user.
      responses:
        '201':
          description: '201 - Created'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "distinct_id": "_distinct_id_",
                    "properties": {},
                    "created_at": "2025-04-04T21:37:36.712496+00:00",
                    "updated_at": "2025-04-04T21:37:36.743167+00:00",
                    "$inbox": [
                      {
                        "value": "4nlPk4t4kurG5kChOELB8Q1LcDI9DHzHQ70st2E2C24",
                        "id_provider": "suprsend",
                        "status": "active",
                        "perma_status": "active"
                      }
                    ]
                    }
              schema:
                type: object
                description: user object of the primary user after the merge.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "from_user_id: [distinct_id: 'secondary_user'] not found / user [distinct_id: 'primary_user'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code indicating the error.
                    example: 404
                  message:
                    type: string
                    description: Description of the error.
                    example: "user [distinct_id: 'user1'] not found"
      deprecated: false
  /v1/user/{distinct_id}/subscribed_to/object/:
    get:
      summary: Fetch User object subscriptions
      security:
        - BearerAuth: []
      description: API to fetch all objects that a given user is subscribed to.
      operationId: fetch-user-object-subscriptions
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system
          schema:
            type: string
          required: true
        - name: limit
          in: query
          description: number of results to be returned in API response
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 4,
                      "limit": 1,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": null
                    },
                    "results": [
                      {
                        "properties": {
                          "role": "manager"
                        },
                        "object": {
                          "id": "frontend",
                          "object_type": "department",
                          "properties": {},
                          "subscriptions_count": 10,
                          "updated_at": "2025-01-28T16:49:23.695448+00:00"
                        },
                        "created_at": "2025-01-23T16:34:56.093683+00:00",
                        "updated_at": "2025-01-23T16:34:56.093683+00:00"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    description: Metadata related to pagination.
                    properties:
                      count:
                        type: integer
                        description: Total number of results.
                        example: 4
                      limit:
                        type: integer
                        description: The maximum number of results per request.
                        example: 10
                      has_prev:
                        type: boolean
                        description: Indicates if there are previous results.
                        example: false
                      before:
                        type: string
                        nullable: true
                        description: Cursor for fetching previous results.
                        example: "01JXXXX99APxxxxxx8Wxxxx1B"
                      has_next:
                        type: boolean
                        description: Indicates if there are more results available.
                        example: false
                      after:
                        type: string
                        nullable: true
                        description: Cursor for fetching next results.
                        example: "02KXXXX99APxxxxxx0Wxxxx1A"
                  results:
                    type: array
                    description: List of retrieved results.
                    items:
                      type: object
                      properties:
                        properties:
                          type: object
                          description: Object subscription property referred as `$recipient.subscription.<prop>` in templates or workflows.
                        object:
                          type: object
                          description: Details of the subscribed object.
                          properties:
                            id:
                              type: string
                              description: Unique identifier for the object.
                              example: frontend
                            object_type:
                              type: string
                              description: Type of object.
                              example: department
                            properties:
                              type: object
                              description: Additional properties related to the object.
                            subscriptions_count:
                              type: integer
                              description: Number of active subscriptions associated with the object.
                              example: 1
                            updated_at:
                              type: string
                              format: date-time
                              description: Timestamp when the object was last updated.
                              example: "2025-01-28T16:49:23.695448+00:00"
                        created_at:
                          type: string
                          format: date-time
                          description: Timestamp when the result was created.
                          example: "2025-01-23T16:34:56.093683+00:00"
                        updated_at:
                          type: string
                          format: date-time
                          description: Timestamp when the result was last updated.
                          example: "2025-01-23T16:34:56.093683+00:00"
        '404':
                  description: '404 - Not Found'
                  content:
                    application/json:
                      examples:
                        Result:
                          value: {
                            "code": 404,
                            "message": "User [distinct_id: 'user1'] not found"
                          }
                      schema:
                        type: object
                        properties:
                          code:
                            type: integer
                            description: HTTP status code indicating the error type.
                            example: 404
                          message:
                            type: string
                            description: Error message providing details about the issue.
                            example: "User [distinct_id: 'user1'] not found"
      deprecated: false
  /v1/user/{distinct_id}/subscribed_to/list/:
    get:
      summary: Fetch User list subscriptions
      security:
        - BearerAuth: []
      description: API to retrieve all lists that a user is part of.
      operationId: fetch-user-list-subscriptions
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system
          schema:
            type: string
          required: true
        - name: limit
          in: query
          description: number of results to be returned in API response
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 8,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": "01HPMFF5V2CFCF5882QX9FQXYB"
                    },
                    "results": [
                      {
                        "list": {
                          "list_description": "List of users to send newsletter to (Qualified leads + Product Users)",
                          "list_id": "product_update",
                          "list_name": "",
                          "list_type": "static_list",
                          "source": "csv_upload",
                          "subscribers_count": 2,
                          "updated_at": "2024-09-26T10:20:33.636698+00:00"
                        },
                        "created_at": "2024-08-04T13:16:12.825+00:00"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    description: Metadata related to pagination.
                    properties:
                      count:
                        type: integer
                        description: Total number of records returned.
                        example: 8
                      limit:
                        type: integer
                        description: Maximum number of records per page.
                        example: 10
                      has_prev:
                        type: boolean
                        description: Indicates if there is a previous page.
                        example: false
                      before:
                        type: string
                        nullable: true
                        description: Cursor for the previous page.
                        example: "01HPMFF5V2CFCF5882QX9FQXYB"
                      has_next:
                        type: boolean
                        description: Indicates if there is a next page.
                        example: false
                      after:
                        type: string
                        nullable: true
                        description: Cursor for the next page.
                        example: "01HPMFF5V2CFCFti5882QX9FQXYB"
                  results:
                    type: array
                    description: List of user lists.
                    items:
                      type: object
                      properties:
                        list:
                          type: object
                          properties:
                            list_id:
                              type: string
                              description: Unique identifier for the list.
                              example: "product_update"
                            list_name:
                              type: string
                              description: Name of the list.
                              example: "Newsletter subscriber users"
                            description:
                              type: string
                              description: Brief description of the list.
                              example: "List of users to send newsletter to"
                            list_type:
                              type: string
                              description: Type of list (static_list, query_based)
                              example: "static_list"
                            source:
                              type: string
                              nullable: true
                              description: Source from which the list was created (csv_upload, database_sync, mixpanel)
                              example: "csv_upload"
                            subscribers_count:
                              type: integer
                              description: Number of subscribers in the list.
                              example: 2
                            updated_at:
                              type: string
                              format: date-time
                              description: Timestamp when the list was last updated.
                              example: "2024-09-26T10:20:33.636698+00:00"
                        created_at:
                          type: string
                          format: date-time
                          description: Timestamp when the user was added to the list.
                          example: "2024-09-26T10:20:33.636698+00:00"
        '404':
                  description: '404 - Not Found'
                  content:
                    application/json:
                      examples:
                        Result:
                          value: {
                            "code": 404,
                            "message": "user [distinct_id: 'user1'] not found"
                          }
                      schema:
                        type: object
                        properties:
                          code:
                            type: integer
                            description: HTTP error status code.
                            example: 404
                          message:
                            type: string
                            description: Error message describing the issue.
                            example: "user [distinct_id: 'user1'] not found"
      deprecated: false
  /v1/user/{distinct_id}/tenant/{tenant_id}/:
    post:
      summary: Upsert User Tenant Profile
      security:
        - BearerAuth: []
      description: "Adds or updates the per-tenant profile for a user. Fields you set here override the user's global profile when the workflow is triggered with `tenant_id`. Body accepts the same shape as [Create / Update Users](/reference/create-update-users)."
      operationId: upsert-user-tenant-profile
      x-codeSamples:
        - lang: cURL
          label: Upsert user tenant profile
          source: |
            curl -X POST "https://hub.suprsend.com/v1/user/user@example.com/tenant/acme-corp/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__' \
              --header 'Content-Type: application/json' \
              --data '{
                "$email": ["user@acme-corp.com"],
                "$slack": [{ "email": "user@acme-corp.com", "access_token": "xoxb-XXXXXXXX" }],
                "$timezone": "America/New_York",
                "$preferred_language": "en",
                "role": "admin"
              }'
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system. The user's global profile must exist before you upsert a per-tenant profile.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: path
          description: Tenant to scope the profile update to. Tenant must exist in the workspace.
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            example:
              $email: ["user@acme-corp.com"]
              $sms: ["+1234567890"]
              $whatsapp: ["+1234567890"]
              $inbox: ["4nlPk4XXLcDxxxHQ70xx2Cx24"]
              $webpush:
                - token: "webpush_token_abc123"
                  endpoint: "https://fcm.googleapis.com/fcm/send/abc123"
                  keys:
                    p256dh: "BNJxwH..."
                    auth: "tBH..."
              $androidpush: ["android_push_token_xyz987"]
              $iospush: ["ios_push_token_lmn456"]
              $slack:
                - email: "user@acme-corp.com"
                  access_token: "xoxb-XXXXXXXX"
              $timezone: "America/New_York"
              $preferred_language: "en"
              role: "admin"
            schema:
              type: object
              description: "Per-tenant profile payload. Same channel and property keys as [Create / Update Users](/reference/create-update-users). Any key set here becomes the per-tenant override; keys omitted here fall through to the global profile at send time."
              properties:
                $email:
                  type: array
                  items:
                    type: string
                    format: email
                  description: List of email addresses to set on the per-tenant profile.
                $sms:
                  type: array
                  items:
                    type: string
                  description: List of phone numbers for SMS on the per-tenant profile.
                $whatsapp:
                  type: array
                  items:
                    type: string
                  description: List of phone numbers for WhatsApp on the per-tenant profile.
                $inbox:
                  type: array
                  items:
                    type: string
                  description: List of inbox identifiers on the per-tenant profile.
                $androidpush:
                  type: array
                  items:
                    type: string
                  description: Android push tokens on the per-tenant profile. Use this to isolate device tokens per tenant / app install.
                $iospush:
                  type: array
                  items:
                    type: string
                  description: iOS push tokens on the per-tenant profile.
                $webpush:
                  type: array
                  description: Web push subscription objects on the per-tenant profile.
                  items:
                    type: object
                $slack:
                  type: array
                  description: Slack channel configuration on the per-tenant profile. Same shape as the global profile — email + access_token, user_id + access_token, channel + access_token, or incoming_webhook.
                  items:
                    type: object
                $ms_teams:
                  type: array
                  description: Microsoft Teams channel configuration on the per-tenant profile. Same shape as the global profile.
                  items:
                    type: object
                $timezone:
                  type: string
                  description: IANA timezone for the per-tenant profile.
                  example: "America/New_York"
                $preferred_language:
                  type: string
                  description: Preferred language code for the per-tenant profile.
                  example: "en"
                $locale:
                  type: string
                  description: Locale for the per-tenant profile.
                  example: "en_GB"
              additionalProperties:
                description: Any custom property to set on the per-tenant profile. Overrides the same key on the global profile at send time.
      responses:
        '201':
          description: "201 - Created. The response is the full user object with the merged (effective) profile at the top level and the per-tenant override under `tenant`."
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "distinct_id": "user@example.com",
                    "properties": {
                      "$timezone": "America/New_York",
                      "$preferred_language": "en",
                      "role": "admin"
                    },
                    "created_at": "2022-02-13T12:47:00.388999+00:00",
                    "updated_at": "2026-07-21T09:49:36.383794+00:00",
                    "$email": [
                      { "value": "user@acme-corp.com", "status": "active", "perma_status": "active" }
                    ],
                    "$slack": [
                      { "value_json": { "email": "user@acme-corp.com", "access_token": "xoxb-XXXXXXXX" }, "status": "active", "perma_status": "active" }
                    ],
                    "tenant": {
                      "tenant_id": "acme-corp",
                      "properties": {
                        "$timezone": "America/New_York",
                        "$preferred_language": "en",
                        "role": "admin"
                      },
                      "$email": [
                        { "value": "user@acme-corp.com", "status": "active", "perma_status": "active" }
                      ],
                      "$slack": [
                        { "value_json": { "email": "user@acme-corp.com", "access_token": "xoxb-XXXXXXXX" }, "status": "active", "perma_status": "active" }
                      ]
                    }
                  }
              schema:
                type: object
                properties:
                  distinct_id:
                    type: string
                    description: The user identifier the operation applied to.
                    example: "user@example.com"
                  properties:
                    type: object
                    description: Merged (effective) properties — global properties layered with per-tenant overrides.
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was originally created.
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was last updated (global or per-tenant).
                  tenant:
                    type: object
                    description: The per-tenant override block for the tenant the request targeted. Contains only the fields explicitly set at the tenant level, not the merged view.
                    properties:
                      tenant_id:
                        type: string
                        description: Tenant this override belongs to.
                        example: "acme-corp"
                      properties:
                        type: object
                        description: Properties explicitly set on the per-tenant profile.
        '400':
          description: "400 - Bad Request. Returned when `user_tenancy_mode` is `exclusive` and the user is already associated with a different tenant."
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 400,
                    "message": "user is already associated with a different tenant; workspace is in exclusive mode"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 400
                  message:
                    type: string
                    description: Human-readable error description.
                    example: "user is already associated with a different tenant; workspace is in exclusive mode"
        '404':
          description: "404 - Not Found. Returned when the tenant does not exist."
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'acme-corp' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  message:
                    type: string
                    description: Human-readable error description.
                    example: "tenant 'acme-corp' not found"
      deprecated: false
    get:
      summary: Fetch User Tenant Profile
      security:
        - BearerAuth: []
      description: "Returns the user profile evaluated for a specific tenant. The top-level fields are the **merged** effective profile (global layered with per-tenant overrides). The `tenant` block returns only the fields explicitly set on the per-tenant profile."
      operationId: fetch-user-tenant-profile
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: path
          description: Tenant to evaluate the profile against.
          schema:
            type: string
          required: true
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "distinct_id": "user@example.com",
                    "properties": {
                      "$timezone": "America/New_York",
                      "role": "admin",
                      "plan": "enterprise"
                    },
                    "created_at": "2022-02-13T12:47:00.388999+00:00",
                    "updated_at": "2026-07-21T09:49:36.383794+00:00",
                    "$email": [
                      { "value": "user@acme-corp.com", "status": "active", "perma_status": "active" }
                    ],
                    "$slack": [
                      { "value_json": { "email": "user@acme-corp.com", "access_token": "xoxb-XXXXXXXX" }, "status": "active", "perma_status": "active" }
                    ],
                    "tenant": {
                      "tenant_id": "acme-corp",
                      "properties": {
                        "role": "admin"
                      },
                      "$email": [
                        { "value": "user@acme-corp.com", "status": "active", "perma_status": "active" }
                      ]
                    }
                  }
              schema:
                type: object
                properties:
                  distinct_id:
                    type: string
                    description: The user identifier.
                  properties:
                    type: object
                    description: Merged (effective) properties — global properties layered with per-tenant overrides.
                  created_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was originally created.
                  updated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the user was last updated.
                  tenant:
                    type: object
                    description: Per-tenant override block. Contains only the fields explicitly set on the per-tenant profile.
                    properties:
                      tenant_id:
                        type: string
                        description: Tenant the override belongs to.
                      properties:
                        type: object
                        description: Properties explicitly set on the per-tenant profile.
        '404':
          description: '404 - Not Found. Returned when the tenant does not exist for the workspace.'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "tenant 'acme-corp' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  message:
                    type: string
                    description: Human-readable error description.
                    example: "tenant 'acme-corp' not found"
      deprecated: false
    delete:
      summary: Delete User Tenant Mapping
      security:
        - BearerAuth: []
      description: "Removes the per-tenant profile for a user. The global profile is untouched and the user remains in the workspace."
      operationId: delete-user-tenant-mapping
      x-codeSamples:
        - lang: cURL
          label: Delete user tenant mapping
          source: |
            curl -X DELETE "https://hub.suprsend.com/v1/user/user@example.com/tenant/acme-corp/" \
              --header 'Authorization: Bearer __YOUR_API_KEY__'
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system.
          schema:
            type: string
          required: true
        - name: tenant_id
          in: path
          description: Tenant to disassociate the user from. Only the per-tenant profile is removed.
          schema:
            type: string
          required: true
      responses:
        '204':
          description: '204 - No Content. The per-tenant profile was removed.'
        '404':
          description: '404 - Not Found. Returned when the mapping does not exist.'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "no per-tenant profile for user in tenant 'acme-corp'"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  message:
                    type: string
                    description: Human-readable error description.
                    example: "no per-tenant profile for user in tenant 'acme-corp'"
      deprecated: false
  /v1/user/{distinct_id}/tenant/:
    get:
      summary: List User Tenant Profiles
      security:
        - BearerAuth: []
      description: "Returns every tenant profile the user has, one entry per mapping. Each entry contains the merged effective profile evaluated for that tenant, with the per-tenant override under the `tenant` key."
      operationId: list-user-tenant-profiles
      parameters:
        - name: distinct_id
          in: path
          description: Unique identifier of the user in your system.
          schema:
            type: string
          required: true
        - name: limit
          in: query
          description: Number of results per page (1–100). Defaults to 10.
          required: false
          schema:
            type: integer
            format: int32
            default: 10
        - name: after
          in: query
          description: Pagination cursor returned by a previous call. Pass to fetch the next page.
          required: false
          schema:
            type: string
      responses:
        '200':
          description: '200 - OK'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 2,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": null
                    },
                    "results": [
                      {
                        "distinct_id": "user@example.com",
                        "properties": { "role": "admin" },
                        "$email": [
                          { "value": "user@acme-corp.com", "status": "active", "perma_status": "active" }
                        ],
                        "tenant": {
                          "tenant_id": "acme-corp",
                          "properties": { "role": "admin" },
                          "$email": [
                            { "value": "user@acme-corp.com", "status": "active", "perma_status": "active" }
                          ]
                        }
                      },
                      {
                        "distinct_id": "user@example.com",
                        "properties": { "role": "viewer" },
                        "$email": [
                          { "value": "user@globex.io", "status": "active", "perma_status": "active" }
                        ],
                        "tenant": {
                          "tenant_id": "globex",
                          "properties": { "role": "viewer" },
                          "$email": [
                            { "value": "user@globex.io", "status": "active", "perma_status": "active" }
                          ]
                        }
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    description: Pagination metadata.
                    properties:
                      count:
                        type: integer
                        description: Number of results in this response.
                      limit:
                        type: integer
                        description: Maximum number of results requested for this page.
                      has_prev:
                        type: boolean
                        description: Whether a previous page exists.
                      before:
                        type: string
                        nullable: true
                        description: Cursor for the previous page. `null` on the first page.
                      has_next:
                        type: boolean
                        description: Whether a next page exists.
                      after:
                        type: string
                        nullable: true
                        description: Cursor to pass to fetch the next page.
                  results:
                    type: array
                    description: List of tenant profiles for the user. One entry per associated tenant.
                    items:
                      type: object
                      properties:
                        distinct_id:
                          type: string
                          description: The user identifier this entry belongs to.
                        properties:
                          type: object
                          description: Merged effective properties for this tenant (global layered with per-tenant overrides).
                        tenant:
                          type: object
                          description: Per-tenant override block for this entry.
                          properties:
                            tenant_id:
                              type: string
                              description: Tenant the override belongs to.
                            properties:
                              type: object
                              description: Properties explicitly set on the per-tenant profile.
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "User [distinct_id: 'user@example.com'] not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code.
                    example: 404
                  message:
                    type: string
                    description: Human-readable error description.
                    example: "User [distinct_id: 'user@example.com'] not found"
      deprecated: false
  /v1/object/{object_type}/{id}/subscribed_to/object/:
    get:
      summary: Fetch Object subscriptions
      security:
        - BearerAuth: []
      description: API to fetch a paginated list of all parent objects that the given child object is subscribed to.
      operationId: fetch-object-subscriptions
      parameters:
        - name: id
          in: path
          description: Unique identifier of the object in your system
          schema:
            type: string
          required: true
        - name: object_type
          in: path
          description: Used to group similar objects together. Give plural namespace like teams, organizations, and roles.
          schema:
            type: string
          required: true
        - name: limit
          in: query
          description: number of results to be returned in API response
          required: true
          schema:
            type: integer
            format: int32
        - name: after
          in: query
          required: true
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: '200'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "meta": {
                      "count": 1,
                      "limit": 10,
                      "has_prev": false,
                      "before": null,
                      "has_next": false,
                      "after": null
                    },
                    "results": [
                      {
                        "properties": {},
                        "object": {
                          "id": "frontend",
                          "object_type": "developer",
                          "properties": {
                            "name": "frontend",
                            "technology": "react"
                          },
                          "subscriptions_count": 3,
                          "updated_at": "2024-11-10T21:41:02.673661+00:00"
                        },
                        "created_at": "2025-04-06T11:00:24.260496+00:00",
                        "updated_at": "2025-04-06T11:00:24.260496+00:00"
                      }
                    ]
                  }
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 1
                        description: "Total number of results."
                      limit:
                        type: integer
                        example: 10
                        description: "Maximum number of results returned per request."
                      has_prev:
                        type: boolean
                        description: "Indicates if there are previous results."
                      before:
                        type: string
                        description: "Cursor for the previous page, if applicable."
                      has_next:
                        type: boolean
                        description: "Indicates if there are more results."
                      after:
                        type: string
                        description: "Cursor for the next page, if applicable."
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        properties:
                          type: object
                          description: Subscription Properties
                        object:
                          type: object
                          description: payload of the parent object
                        created_at:
                          type: string
                          format: date-time
                          example: "2024-11-10T21:40:02.169501+00:00"
                          description: "Timestamp when the record was created."
                        updated_at:
                          type: string
                          format: date-time
                          example: "2024-11-10T21:40:02.169501+00:00"
                          description: "Timestamp when the record was last updated."
        '404':
          description: '404 - Not Found'
          content:
            application/json:
              examples:
                Result:
                  value: {
                    "code": 404,
                    "message": "object 'obj_type/obj_id' not found"
                  }
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: "HTTP status code indicating the error."
                  message:
                    type: string
                    description: "Error message indicating object_id and type combination is not found"
      deprecated: false

  /v1/message/:
    get:
      summary: List Messages
      description: |
        Retrieve a paginated list of messages in a workspace order by created_at desc. Can be used to fetch and show message logs on the platform.
      operationId: list-messages
      security:
        - BearerAuth: []
      parameters:
        # Pagination
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 1000
          description: Maximum number of messages to return per page. Defaults to `10`, maximum is `1000`.
        - name: after
          in: query
          schema:
            type: string
          description: |
            Cursor for forward pagination - pass the `meta.after` value from a previous response to fetch the next page of older messages. Treat this value as an opaque cursor - do not parse, validate, or assume any format for it. **Takes precedence over `before` when both are set** (`before` is silently ignored).
        - name: before
          in: query
          schema:
            type: string
          description: |
            Cursor for backward pagination - pass the `meta.before` value from a previous response to fetch the previous page of newer messages. Treat this value as an opaque cursor - do not parse, validate, or assume any format for it. Ignored when `after` is also set.

        # Filters
        - name: status[]
          in: query
          schema:
            type: array
            items:
              type: string
              enum:
                - triggered (status AnyOf('triggered','trigger_blocked','sent_by_vendor','to_be_triggered','not_to_be_triggered'))
                - delivery_failed (status AnyOf('trigger_failed','failure_by_vendor')
                - delivered
                - seen
                - clicked
                - dismissed
                - read (is_read = true)
                - unread (is_read = false)
                - archived (is_archived = true)
          style: form
          explode: true
          description: |
            Filter by one or more derived statuses. Multiple values are OR-ed. Repeat the param for each value, e.g. `?status[]=delivered&status[]=seen`.
        - name: channel
          in: query
          schema:
            type: string
            enum:
              - sms
              - email
              - androidpush
              - iospush
              - webpush
              - inbox
              - whatsapp
              - slack
              - ms_teams
          description: Filter by delivery channel.
        - name: recipient_id[]
          in: query
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Filter by one or more recipient `distinct_id`s (OR-ed). Repeat the param for each value, e.g. `?recipient_id[]=user_123&recipient_id[]=user_456`.
        - name: category[]
          in: query
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Filter by one or more notification categories (OR-ed). Repeat the param for each value, e.g. `?category[]=transactional&category[]=promotional`.
        - name: created_at_gte
          in: query
          schema:
            type: string
            format: date-time
          description: |
            RFC3339 timestamp lower bound (inclusive). Compared against the `created_at` column which has **second precision** - sub-second components in the filter value are effectively truncated. Example: `2026-04-26T21:34:33Z`.
        - name: created_at_lte
          in: query
          schema:
            type: string
            format: date-time
          description: |
            RFC3339 timestamp upper bound (inclusive). Same second-precision caveat as `created_at_gte`. Must be `>= created_at_gte` when both are set.
        - name: workflow_slug
          in: query
          schema:
            type: string
          description: Filter messages triggered from a specific workflow.
        - name: execution_id
          in: query
          schema:
            type: string
          description: Matches `wf_exec_id` or `broadcast_id`.
        - name: idempotency_key
          in: query
          schema:
            type: string
          description: Filter by the idempotency key associated with the message at trigger time.
        - name: message_id
          in: query
          schema:
            type: string
          description: Exact match on message ID.
        - name: tenant_id
          in: query
          schema:
            type: string
          description: Filter messages belonging to a specific tenant.
        - name: is_campaign
          in: query
          schema:
            type: boolean
          description: Set `true` to return only messages sent as part of a broadcast/campaign.
        - name: object_id
          in: query
          schema:
            type: string
          description: Must be provided together with `object_type` to filter messages sent to an object. Will filter all message logs which were sent to recipients after object fanout.
        - name: object_type
          in: query
          schema:
            type: string
          description: Must be provided together with `object_id` to filter messages sent to an object. Will filter all message logs which were sent to recipients after object fanout.
        - name: include_content
          in: query
          schema:
            type: boolean
            default: false
          description: Set `true` to include the rendered message content in each result object. When `false` (default), the `content` key is omitted from the response to keep payloads lightweight.
      responses:
        '200':
          description: Returns the paginated list of messages order by created_at desc.
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    $ref: '#/components/schemas/CursorPagination'
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/MessageResponse'
              example:
                meta:
                  count: 3506
                  limit: 10
                  has_prev: false
                  before: null
                  has_next: true
                  after: "01HVXXXXXXXXXXXXXXXXXXXX10"
                results:
                  - message_id: "01HVXXXXXXXXXXXXXXXXXXXX01"
                    created_at: "2026-04-01T17:18:06.000Z"
                    updated_at: "2026-04-01T17:20:11.000Z"
                    triggered_at: "2026-04-01T17:18:06.000Z"
                    delivered_at: "2026-04-01T17:18:08.000Z"
                    seen_at: "2026-04-01T17:19:25.000Z"
                    clicked_at: null
                    dismissed_at: null
                    read_at: null
                    unread_at: null
                    archived_at: null
                    unarchived_at: null
                    is_read: false
                    is_archived: false
                    status: "seen"
                    channel: "inbox"
                    idempotency_key: "order-5678"
                    failure_reason: null
                    recipient:
                      $type: "user"
                      distinct_id: "user_123"
                      object_type: null
                      id: null
                    parent_entity_id: null
                    parent_entity_type: null
                    vendor:
                      name: "suprsend_inbox"
                      nickname: "Inbox"
                    execution_id: "exec_01HV..."
                    parent_execution_id: null
                    is_campaign: false
                    tenant_id: "acme"
                    workflow:
                      slug: "order-confirmation"
                      version_id: "wf_ver_01HV..."
                      name: "Order Confirmation"
                      node_ref: "send_inbox_1"
                    template:
                      name: "Order Confirmation"
                      slug: "order-confirmation"
                      version_no: 4
                      variant_id: "default"
                    content:
                      header: "Your order #5678 is confirmed"
                      body: "Hi Alex, we've received your order #5678. We'll notify you once it ships."
                      schema_version: "1.0"
                      templating_language: "handlebars"
                    channel_identity:
                      inbox: "user_123"
                    category: "transactional"
                  - message_id: "01HVXXXXXXXXXXXXXXXXXXXX02"
                    created_at: "2026-04-01T17:30:01.000Z"
                    updated_at: "2026-04-01T17:30:15.000Z"
                    triggered_at: "2026-04-01T17:30:01.000Z"
                    delivered_at: null
                    seen_at: null
                    clicked_at: null
                    dismissed_at: null
                    read_at: null
                    unread_at: null
                    archived_at: null
                    unarchived_at: null
                    is_read: false
                    is_archived: false
                    status: "delivery_failure"
                    channel: "sms"
                    idempotency_key: null
                    failure_reason: "invalid_recipient_number"
                    recipient:
                      $type: "user"
                      distinct_id: "user_456"
                      object_type: null
                      id: null
                    parent_entity_id: null
                    parent_entity_type: null
                    vendor:
                      name: "gupshup"
                      nickname: "Gupshup WhatsApp"
                    execution_id: "exec_01HV..."
                    parent_execution_id: null
                    is_campaign: false
                    tenant_id: "acme"
                    workflow:
                      slug: "password-reset"
                      version_id: "wf_ver_01HV..."
                      name: "Password Reset"
                      node_ref: "multichannel_1"
                    template:
                      name: "Password Reset"
                      slug: "password-reset"
                      version_no: 2
                      variant_id: "default"
                    content:
                      body: "Your password reset code is 482913. It expires in 10 minutes."
                      schema_version: "1.0"
                      templating_language: "handlebars"
                    channel_identity:
                      sms: "+15555550100"
                    category: "transactional"
      deprecated: false

  /v1/message/{message_id}/content/:
    get:
      summary: Get Message Content
      description: |
        Retrieve the rendered content of a specific message. Returns the channel and the content object containing the rendered template output.
      operationId: get-message-content
      security:
        - BearerAuth: []
      parameters:
        - name: message_id
          in: path
          required: true
          schema:
            type: string
          description: ID of the message whose content you want to retrieve.
      responses:
        '200':
          description: Returns the channel and rendered content of the message.
          content:
            application/json:
              schema:
                type: object
                properties:
                  channel:
                    type: string
                    description: Channel through which the message was sent.
                    enum:
                      - sms
                      - email
                      - whatsapp
                      - inbox
                      - androidpush
                      - iospush
                      - webpush
                      - slack
                      - ms_teams
                  content:
                    type: object
                    additionalProperties: true
                    description: Rendered message content. The keys vary by channel and template configuration.
              example:
                channel: "email"
                content:
                  header: "Your invoice for March is ready"
                  body: "Hi Alex, your invoice #INV-2026-0042 for $1,200.00 is now available. You can view and download it from your billing dashboard."
                  importance: "high"
                  notification_category: "transactional"
                  schema_version: "1.0"
                  templating_language: "handlebars"
        '404':
          description: Message not found.
      deprecated: false

  /v1/bulk/message/:
    patch:
      summary: Bulk Update Message Status
      description: Change the status of messages by passing their id and notification action.
      operationId: bulk-update-messages
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - messages
              properties:
                messages:
                  type: array
                  minItems: 1
                  maxItems: 1000
                  description: List of messages to update. No duplicate `message_id`s allowed.
                  items:
                    type: object
                    required:
                      - message_id
                      - action
                    properties:
                      message_id:
                        type: string
                        description: Message-id to update.
                      action:
                        type: string
                        enum:
                          - seen
                          - clicked
                          - dismissed
                          - read
                          - unread
                          - archived
                          - unarchived
                        description: |
                          Action to apply to the message. Each action sets the corresponding status or flag.

                          - `seen` - Mark the message as seen by the recipient. 
                          - `clicked` - Mark the message as clicked or interacted with. 
                          - `dismissed` - Mark the message as dismissed (cleared without taking action).
                          - `read` - Mark the inbox message as read. Applicable for Inbox channel only. Also sets flag is_read = true.
                          - `unread` - Revert a previously read inbox message back to unread. Applicable for Inbox channel only. Sets flag is_read = false.
                          - `archived` - Archive the inbox message (sets the `is_archived` flag to true; status is preserved). Applicable for Inbox channel only.
                          - `unarchived` - Unarchive a previously archived inbox message. (sets the `is_archived` flag to false; status is preserved). Applicable for Inbox channel only.

                          **Status progression (one-way):** `triggered` → `sent_by_vendor` → `delivered` → `seen` → `read` -> `clicked` / `dismissed`. Once a message reaches a later status, it cannot be moved back to an earlier one - for example, marking a `clicked` message as `seen` will not change the status to `seen`.

                          **Toggles (reversible):** `read` ↔ `unread` and `archived` ↔ `unarchived` flip independent flags and can be applied in either direction any number of times.
            examples:
              mark-as-seen:
                summary: Mark messages as seen
                value:
                  messages:
                    - message_id: "01HVXXXXXXXXXXXXXXXXXXXX01"
                      action: "seen"
                    - message_id: "01HVXXXXXXXXXXXXXXXXXXXX02"
                      action: "seen"
              mixed-actions:
                summary: Apply different actions in one call
                value:
                  messages:
                    - message_id: "01HVXXXXXXXXXXXXXXXXXXXX01"
                      action: "read"
                    - message_id: "01HVXXXXXXXXXXXXXXXXXXXX02"
                      action: "archived"
      responses:
        '202':
          description: Bulk update accepted. Inspect each record's `status_code` and `error` for individual outcomes - a `null` `error` means success.
          content:
            application/json:
              schema:
                type: object
                properties:
                  records:
                    type: array
                    description: Per-message results, in the same order as the request.
                    items:
                      $ref: '#/components/schemas/BulkPatchItemResult'
              example:
                records:
                  - message_id: "01HVXXXXXXXXXXXXXXXXXXXX01"
                    status_code: 202
                    error: null
                  - message_id: "01HVXXXXXXXXXXXXXXXXXXXX02"
                    status_code: 404
                    error:
                      type: "not_found"
                      message: "not found"
      deprecated: false

  /v1/workspace/:
    get:
      summary: List Workspaces
      description: List all workspaces available in your account.
      operationId: list-workspaces
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Workspaces
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/workspace/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      responses:
        '200':
          description: Successfully retrieved workspaces.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceListResponse'
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - uid: "wksp_exampleUid01"
                    slug: "staging"
                    data_center: {}
                    is_expired: false
                    has_limit_reached: false
                    name: "Staging"
                    description: "Development environment to test iterations internally"
                    mode: "sandbox"
                  - uid: "wksp_exampleUid02"
                    slug: "production"
                    data_center: {}
                    is_expired: false
                    has_limit_reached: false
                    name: "Production"
                    description: "Final environment to send notifications to live users"
                    mode: "production"
        '401':
          $ref: '#/components/responses/AuthenticationError'
    post:
      summary: Create Workspace
      description: Create a new workspace in your account.
      operationId: create-workspace
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Create Workspace
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/workspace/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json' \
              --data '{"name":"my-workspace","description":"Testing workspace API"}'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkspaceCreateRequest'
            example:
              name: "my-workspace"
              description: "Testing workspace API"
      responses:
        '200':
          description: Workspace created. Response returns the updated paginated list of workspaces in the account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceListResponse'
              example:
                meta:
                  count: 3
                  limit: 10
                  offset: 0
                results:
                  - uid: "wksp_exampleUid01"
                    slug: "staging"
                    data_center: {}
                    is_expired: false
                    has_limit_reached: false
                    name: "Staging"
                    description: "Development environment to test iterations internally"
                    mode: "sandbox"
                  - uid: "wksp_exampleUid02"
                    slug: "production"
                    data_center: {}
                    is_expired: false
                    has_limit_reached: false
                    name: "Production"
                    description: "Final environment to send notifications to live users"
                    mode: "production"
                  - uid: "wksp_exampleUid03"
                    slug: "my-workspace"
                    data_center: {}
                    is_expired: false
                    has_limit_reached: false
                    name: "my-workspace"
                    description: "Testing workspace API"
                    mode: "sandbox"
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /v1/workspace/{workspace_slug}/config/:
    get:
      summary: Get Workspace Config
      description: |
        Retrieve workspace-level configuration flags — the settings that govern behavior for every user, tenant, and workflow inside this workspace.

        Fields returned:
        - `user_inbox_preference_enabled` — if you are using the Inbox channel, enable this to show the Inbox channel in the preference centre.
        - `sms_vendor_type` — SMS delivery mode used for this workspace (`basic` for standard sends, `dlt` for India DLT-compliant sends).
        - `user_tenancy_mode` — how a user's association to tenants is constrained. `shared` allows a user to belong to any number of tenants; `exclusive` restricts each user to at most one tenant. See [User-tenant mapping](/docs/user-tenant-mapping) for the trade-offs.
        - `user_tenancy_channel_fallback_mode` and `user_tenancy_channel_fallback` — govern which channels on a tenant-scoped profile are allowed to fall back to the user's global profile. Use `allowlist` mode with an explicit list to prevent identities like `$androidpush` or `$slack` from leaking across tenants.
        - `user_tenancy_channel_fallback_applies_to_default_tenant` — whether the fallback rule above also applies to the default-tenant path (sends without a `tenant_id`).
      operationId: get-workspace-config
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Workspace Config
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/workspace/{workspace_slug}/config/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace_slug
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      responses:
        '200':
          description: Workspace config retrieved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkspaceConfig'
              example:
                user_inbox_preference_enabled: true
                sms_vendor_type: "basic"
                user_tenancy_mode: "exclusive"
                user_tenancy_channel_fallback_mode: "allowlist"
                user_tenancy_channel_fallback: ["$email", "$sms", "$whatsapp"]
                user_tenancy_channel_fallback_applies_to_default_tenant: false
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    patch:
      summary: Update Workspace Config
      description: |
        Update one or more workspace-level configuration flags. Any field returned by `GET /v1/workspace/{workspace_slug}/config/` can be sent in the PATCH body — only fields you include are changed.
      operationId: update-workspace-config
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Update Workspace Config
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/workspace/{workspace_slug}/config/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json' \
              --data '{"user_tenancy_mode":"shared"}'
      parameters:
        - in: path
          name: workspace_slug
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkspaceConfigUpdateRequest'
            example:
              user_tenancy_mode: "shared"
      responses:
        '200':
          description: Workspace config updated. The full updated config is returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkspaceConfig'
              example:
                user_inbox_preference_enabled: true
                sms_vendor_type: "basic"
                user_tenancy_mode: "shared"
                user_tenancy_channel_fallback_mode: "allowlist"
                user_tenancy_channel_fallback: ["$email", "$sms", "$whatsapp"]
                user_tenancy_channel_fallback_applies_to_default_tenant: false
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_api_key/:
    get:
      summary: List Workspace API Keys
      description: List API keys scoped to a workspace. Secret values are never returned on list; only a masked preview is shown.
      operationId: list-workspace-api-keys
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Workspace API Keys
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/ws_api_key/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      responses:
        '200':
          description: Successfully retrieved API keys.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceApiKeyListResponse'
              example:
                meta:
                  count: 1
                  limit: 10
                  offset: 0
                results:
                  - id: "ws_apik_exampleId01"
                    masked_api_key: "SS.XXXXXXX*****"
                    is_deleted: false
                    name: "backend-prod"
                    allowed_domains: []
                    created_at: "2026-04-21T12:19:00.148846Z"
                    created_by:
                      name: "System User"
                      email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                    deleted_at: null
                    deleted_by: null
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    post:
      summary: Create Workspace API Key
      description: |
        Create a new API key scoped to this workspace.

        The full `api_key` secret is returned **only once** in the create response. Store it securely - it cannot be retrieved later.
      operationId: create-workspace-api-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Create API Key
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/ws_api_key/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json' \
              --data '{"name":"backend-prod","description":"Primary backend key"}'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkspaceApiKeyCreateRequest'
            example:
              name: "backend-prod"
              description: "Primary backend key"
      responses:
        '201':
          description: API key created. `api_key` is returned only once - store it securely.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceApiKeyCreateResponse'
              example:
                id: "ws_apik_exampleId01"
                masked_api_key: "SS.XXXXXXX*****"
                is_deleted: false
                name: "backend-prod"
                allowed_domains: []
                created_at: "2026-04-21T12:19:00.148846Z"
                created_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                deleted_at: null
                deleted_by: null
                api_key: "SS.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_api_key/{api_key_id}/:
    delete:
      summary: Delete API Key
      description: Delete an API key by its `id` (e.g. `ws_apik_...`). Once disabled, the key can no longer authenticate requests.
      operationId: disable-workspace-api-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delete API Key
          source: |
            curl -X DELETE "https://management-api.suprsend.com/v1/{workspace}/ws_api_key/{api_key_id}/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
        - in: path
          name: api_key_id
          required: true
          schema:
            type: string
          description: API key identifier (e.g. `ws_apik_...`).
      responses:
        '204':
          description: API key disabled - no response body.
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_public_key/:
    get:
      summary: List Workspace Public Keys
      description: List public keys for this workspace. Public keys are used by client-side SDKs.
      operationId: list-workspace-public-keys
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Workspace Public Keys
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/ws_public_key/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      responses:
        '200':
          description: Successfully retrieved public keys.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspacePublicKeyListResponse'
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - id: "ws_pubk_exampleId01"
                    api_key: "SS.PUBK.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                    name: "web-app"
                    allowed_domains: null
                    is_secure_mode_enabled: false
                    is_deleted: false
                    is_default: false
                    created_at: "2026-04-21T11:12:23.557360Z"
                    created_by:
                      name: "System User"
                      email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                    rotated_at: null
                    rotated_by: null
                    updated_at: "2026-04-21T11:12:23.557406Z"
                    updated_by: null
                  - id: "ws_pubk_exampleId02"
                    api_key: "SS.PUBK.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
                    name: "default"
                    allowed_domains: null
                    is_secure_mode_enabled: false
                    is_deleted: false
                    is_default: true
                    created_at: "2024-08-27T10:54:03.512045Z"
                    created_by: null
                    rotated_at: "2026-04-15T17:59:45.634355Z"
                    rotated_by:
                      name: "System User"
                      email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                    updated_at: "2026-04-15T17:59:45.634452Z"
                    updated_by:
                      name: "System User"
                      email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    post:
      summary: Create Workspace Public Key
      description: Create a new public key for this workspace. Public keys can be safely distributed to client SDKs.
      operationId: create-workspace-public-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Create Workspace Public Key
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/ws_public_key/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json' \
              --data '{"name":"web-app","description":"Browser integration"}'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkspacePublicKeyCreateRequest'
            example:
              name: "web-app"
              description: "Browser integration"
      responses:
        '201':
          description: Public key created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspacePublicKey'
              example:
                id: "ws_pubk_exampleId01"
                api_key: "SS.PUBK.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                name: "web-app"
                allowed_domains: null
                is_secure_mode_enabled: false
                is_deleted: false
                is_default: false
                created_at: "2026-04-21T12:31:18.943398Z"
                created_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                rotated_at: null
                rotated_by: null
                updated_at: "2026-04-21T12:31:18.943443Z"
                updated_by: null
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_public_key/{public_key_id}/:
    patch:
      summary: Enable/Disable Secure Mode on Public Key
      description: Enable or disable secure mode on an existing public key (e.g. `ws_pubk_...`).
      operationId: patch-workspace-public-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Patch Workspace Public Key
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/ws_public_key/{public_key_id}/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json' \
              --data '{"is_secure_mode_enabled":true}'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
        - in: path
          name: public_key_id
          required: true
          schema:
            type: string
          description: Public key identifier (e.g. `ws_pubk_...`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkspacePublicKeyPatchRequest'
            example:
              is_secure_mode_enabled: true
      responses:
        '202':
          description: Secure mode update accepted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspacePublicKey'
              example:
                id: "ws_pubk_exampleId01"
                api_key: "SS.PUBK.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                name: "web-app"
                allowed_domains: null
                is_secure_mode_enabled: true
                is_deleted: false
                is_default: false
                created_at: "2026-04-21T13:08:29.144658Z"
                created_by:
                  name: "Example User"
                  email: "user@example.com"
                rotated_at: "2026-04-21T13:08:59.983999Z"
                rotated_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                updated_at: "2026-04-21T13:08:59.984183Z"
                updated_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    delete:
      summary: Delete Workspace Public Key
      description: Delete a public key by its `id`.
      operationId: delete-workspace-public-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delete Workspace Public Key
          source: |
            curl -X DELETE "https://management-api.suprsend.com/v1/{workspace}/ws_public_key/{public_key_id}/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
        - in: path
          name: public_key_id
          required: true
          schema:
            type: string
          description: Public key identifier (e.g. `ws_pubk_...`).
      responses:
        '204':
          description: Public key deleted - no response body.
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_public_key/{public_key_id}/rotate/:
    patch:
      summary: Rotate Workspace Public Key
      description: Rotate public key material while keeping the same logical key record. Clients using the old material must switch to the new value.
      operationId: rotate-workspace-public-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Rotate Workspace Public Key
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/ws_public_key/{public_key_id}/rotate/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
        - in: path
          name: public_key_id
          required: true
          schema:
            type: string
          description: Public key identifier (e.g. `ws_pubk_...`).
      responses:
        '202':
          description: Public key rotation accepted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspacePublicKey'
              example:
                id: "ws_pubk_exampleId01"
                api_key: "SS.PUBK.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
                name: "web-app"
                allowed_domains: null
                is_secure_mode_enabled: false
                is_deleted: false
                is_default: false
                created_at: "2026-04-21T13:08:29.144658Z"
                created_by:
                  name: "Example User"
                  email: "user@example.com"
                rotated_at: "2026-04-21T13:08:59.983999Z"
                rotated_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                updated_at: "2026-04-21T13:08:59.984183Z"
                updated_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_signing_key/:
    get:
      summary: List Workspace Signing Keys
      description: List signing keys for this workspace. Signing keys are used to verify signed payloads.
      operationId: list-workspace-signing-keys
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Workspace Signing Keys
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/ws_signing_key/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      responses:
        '200':
          description: Successfully retrieved signing keys.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceSigningKeyListResponse'
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - id: "ws_signk_exampleId01"
                    uid: "signing_key_exampleUid01"
                    status: "active"
                    allowed_domains: null
                    expiry_at: null
                    created_at: "2026-04-02T19:35:06.513406Z"
                    created_by:
                      name: "Example User"
                      email: "user@example.com"
                    rolled_at: null
                    rolled_by: null
                    deleted_at: null
                    deleted_by: null
                  - id: "ws_signk_exampleId02"
                    uid: "signing_key_exampleUid02"
                    status: "rolled"
                    allowed_domains: null
                    expiry_at: null
                    created_at: "2024-09-08T16:27:46.700367Z"
                    created_by:
                      name: "Example User"
                      email: "user@example.com"
                    rolled_at: "2026-04-02T19:35:06.503029Z"
                    rolled_by:
                      name: "Example User"
                      email: "user@example.com"
                    deleted_at: null
                    deleted_by: null
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    post:
      summary: Create Workspace Signing Key
      description: |
        Create a signing key for this workspace.

        The `private_key_pem` and `private_key_base64` fields are returned **only once** at creation. Store them securely - they cannot be retrieved later.

        Only **one active** signing key is allowed per workspace. To replace an existing active key, use the [Roll Workspace Signing Key](#operation/roll-workspace-signing-key) endpoint instead.
      operationId: create-workspace-signing-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Create Workspace Signing Key
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/ws_signing_key/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
      responses:
        '201':
          description: Signing key created. Private key material is returned once in this response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceSigningKeyCreateResponse'
              example:
                id: "ws_signk_exampleId01"
                uid: "signing_key_exampleUid01"
                status: "active"
                allowed_domains: null
                expiry_at: null
                private_key_pem: "-----BEGIN PRIVATE KEY-----\n...redacted...\n-----END PRIVATE KEY-----\n"
                private_key_base64: "LS0tLS1CRUdJTi...redacted..."
                created_at: "2026-04-21T12:35:24.117631Z"
                created_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                rolled_at: null
                rolled_by: null
                deleted_at: null
                deleted_by: null
        '400':
          description: Validation error - for example, an active signing key already exists.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "[\"only 1 active signing key is allowed\"]"
                detail:
                  - "only 1 active signing key is allowed"
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_signing_key/{signing_key_uid}/:
    delete:
      summary: Delete Workspace Signing Key
      description: Delete a signing key by its `uid` (e.g. `signing_key_20260421T123746`).
      operationId: delete-workspace-signing-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delete Workspace Signing Key
          source: |
            curl -X DELETE "https://management-api.suprsend.com/v1/{workspace}/ws_signing_key/{signing_key_uid}/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
        - in: path
          name: signing_key_uid
          required: true
          schema:
            type: string
          description: Signing key `uid` (e.g. `signing_key_...`).
      responses:
        '204':
          description: Signing key deleted - no response body.
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/ws_signing_key/{signing_key_uid}/roll/:
    post:
      summary: Roll Workspace Signing Key
      description: |
        Roll a signing key. Generates a new signing key that replaces the existing active key. The previous key is marked `rolled`.

        The new `private_key_pem` and `private_key_base64` are returned **only once** in this response - store them securely.
      operationId: roll-workspace-signing-key
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Roll Workspace Signing Key
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/ws_signing_key/{signing_key_uid}/roll/" \
              --header 'Authorization: ServiceToken <SERVICE_TOKEN>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g. `staging`, `production`).
        - in: path
          name: signing_key_uid
          required: true
          schema:
            type: string
          description: Signing key `uid` to roll (e.g. `signing_key_...`).
      responses:
        '201':
          description: Signing key rolled. A new signing key is created and its private key material is returned once.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ManagementWorkspaceSigningKeyCreateResponse'
              example:
                id: "ws_signk_exampleId02"
                uid: "signing_key_exampleUid02"
                status: "active"
                allowed_domains: null
                expiry_at: null
                private_key_pem: "-----BEGIN PRIVATE KEY-----\n...redacted...\n-----END PRIVATE KEY-----\n"
                private_key_base64: "LS0tLS1CRUdJTi...redacted..."
                created_at: "2026-04-21T12:37:46.216734Z"
                created_by:
                  name: "System User"
                  email: "org_XXXXXXXXXXXXXXXXXXXXXX@systemuser.suprsend.com"
                rolled_at: null
                rolled_by: null
                deleted_at: null
                deleted_by: null
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v1/{workspace}/workflow/:
    get:
      summary: List Workflows
      description: Retrieve a list of workflows in a workspace.
      operationId: list-workflows
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Workflows
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/workflow/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Mode to filter workflows (draft or live). By default, draft workflows are returned.
        - in: query
          name: slugs
          schema:
            type: string
          description: Comma-separated list of workflow slugs to filter. This can be used to filter workflows by slug.
      responses:
        '200':
          description: Successfully retrieved list of workflows
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of workflows matching the query
                        example: 92
                      limit:
                        type: integer
                        description: Number of results returned per page
                        example: 10
                      offset:
                        type: integer
                        description: Offset value passed in the request
                        example: 0
                    description: Metadata related to pagination information
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/Workflow'
                    description: Array of workflows along with their node tree.
              example:
                meta:
                  count: 92
                  limit: 10
                  offset: 0
                results:
                  - $schema: "https://schema.suprsend.com/workflow/v1/schema.json"
                    slug: "survey-reminder"
                    is_enabled: true
                    created_at: "2025-06-27T03:26:48.793551Z"
                    last_executed_at: "2025-06-27T04:48:20.653366Z"
                    name: "Survey Reminder"
                    description: null
                    updated_at: "2025-06-27T03:36:05.623939Z"
                    commit_message: "Survey completed"
                    hash: "ed3e630c1526170564c962db00dbfcfef997e995f62f67c068a8c9c1d5efbc13"
                    status: "active"
                    category: "transactional"
                    tags: ["reminder"]
                    ratelimit: null
                    conditions: []
                    trigger_type: "api"
                    trigger_events: []
                    override_recipients_type: null
                    override_recipients_user_expr: null
                    override_recipients_single_object_fields_expr: null
                    override_actor_user_expr: null
                    override_tenant_expr: null
                    active_at: "2025-06-27T03:36:05.623845Z"
                    updated_by:
                      name: "Jane Doe"
                      email: "user@example.com"
                    tree:
                      nodes:
                        - name: "Multi-Channel"
                          node_type: "send_multi_channel"
                          properties:
                            template: "11-performance-review-session"
                            channels: []
                            channels_expr: null
                            success: "seen"
                            success_is_event: false
                          description: ""
                          schema_version: "1"
                    validation_result:
                      is_valid: true
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workflow not found
   
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed

  /v1/{workspace}/workflow/{slug}/:
    get:
      summary: Get Workflow Details
      description: Fetch workflow corresponding to the given slug in a workspace.
      operationId: get-workflow
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Workflow
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/workflow/{slug}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: Unique identifier of the workflow. You can get it from workflow settings.
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Which workflow version to fetch (draft or live). By default, draft version is returned.
      responses:
        '200':
          description: Successfully retrieved workflow
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
              example:
                $schema: "https://schema.suprsend.com/workflow/v1/schema.json"
                slug: "survey-reminder"
                is_enabled: true
                created_at: "2025-06-27T03:26:48.793551Z"
                last_executed_at: "2025-06-27T04:48:20.653366Z"
                name: "Survey Reminder"
                description: null
                updated_at: "2025-06-27T03:36:05.623939Z"
                commit_message: "Survey completed"
                hash: "ed3e630c1526170564c962db00dbfcfef997e995f62f67c068a8c9c1d5efbc13"
                status: "active"
                category: "transactional"
                tags: ["reminder"]
                ratelimit: null
                conditions: []
                trigger_type: "api"
                trigger_events: []
                override_recipients_type: null
                override_recipients_user_expr: null
                override_recipients_single_object_fields_expr: null
                override_actor_user_expr: null
                override_tenant_expr: null
                active_at: "2025-06-27T03:36:05.623845Z"
                updated_by:
                  name: "Jane Doe"
                  email: "user@example.com"
                tree:
                  nodes:
                    - name: "Multi-Channel"
                      node_type: "send_multi_channel"
                      properties:
                        template: "11-performance-review-session"
                        channels: []
                        channels_expr: null
                        success: "seen"
                        success_is_event: false
                      description: ""
                      schema_version: "1"
                validation_result:
                  is_valid: true
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workflow not found

        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

    post:
      summary: Create or Update Workflow
      description: Create a new workflow or update the draft version of an existing one
      operationId: upsert-workflow
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/workflow/{slug}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "name": "Welcome Email",
                "description": "Sends welcome email to new users",
                "category": "transactional",
                "tags": ["welcome", "onboarding"],
                "tree": {
                  "nodes": [
                    {
                      "name": "Send Email",
                      "node_type": "send_email",
                      "properties": {
                        "template": "welcome-email-template",
                        "subject": "Welcome to our platform!"
                      },
                      "description": "Send welcome email to new users"
                    }
                  ]
                }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace where the workflow should be created (staging, production, etc.)
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: Unique identifier of the workflow. You can get it from workflow settings for existing workflows.
        - in: query
          name: commit
          schema:
            type: boolean
            default: false
          description: Whether to commit the workflow immediately. Workflow will be successfully committed only if validation_result.is_valid is true.
        - in: query
          name: commit_message
          schema:
            type: string
          description: Commit message describing the changes (required if commit=true)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkflowCreateUpdate'
            examples:
              workflow_example:
                summary: Example workflow creation
                description: Example of creating a simple email workflow
                value:
                  name: "Welcome Email"
                  description: "Sends welcome email to new users"
                  category: "transactional"
                  tags: ["welcome", "onboarding"]
                  tree:
                    nodes:
                      - name: "Send Email"
                        node_type: "send_email"
                        properties:
                          template: "welcome-email-template"
                          subject: "Welcome to our platform!"
                        description: "Send welcome email to new users"
      responses:
        '201':
          description: The response includes the same workflow object as input along with a validation_result field that indicates whether the workflow configuration is valid.
          content:
            application/json:
              examples:
                workflow_example:
                  summary: Example workflow creation
                  description: Example of creating a simple email workflow
                  value:
                    name: "Welcome Email"
                    description: "Sends welcome email to new users"
                    category: "transactional"
                    tags: ["welcome", "onboarding"]
                    tree:
                      nodes:
                        - name: "Send Email"
                          node_type: "send_email"
                          properties:
                            template: "welcome-email-template"
                            subject: "Welcome to our platform!"
                          description: "Send welcome email to new users"
                    validation_result:
                      is_valid: true
                      errors: []
              schema:
                type: object
                properties:
                  validation_result:
                    type: object
                    properties:
                      is_valid:
                        type: boolean
                        description: Whether the workflow configuration is valid and can be committed
                      errors:
                        type: array
                        description: List of validation errors if the workflow is invalid and `is_valid` is false.
                        items:
                          type: string
        '404':
          $ref: '#/components/responses/NotFoundError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

    delete:
      summary: Delete Workflow
      description: Permanently deletes a workflow by providing it's slug.
      operationId: delete-workflow
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delete Workflow
          source: |
            curl -X DELETE "https://management-api.suprsend.com/v1/{workspace}/workflow/{slug}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Which workspace workflow belongs to (staging, production, etc.)
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: Unique identifier of the workflow. You can get it from workflow settings.
      responses:
        '204':
          description: No Content
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workflow not found

        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.


  /v1/{workspace}/workflow/{slug}/commit/:
    patch:
      summary: Commit Workflow
      description: Commit a workflow to make the draft version live.
      operationId: commit-workflow
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/workflow/{slug}/commit/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace to which the workflow belongs (staging, production, etc.)
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: Unique identifier of the workflow. You can get it from workflow settings.
        - in: query
          name: commit_message
          required: false
          schema:
            type: string
          description: Commit message describing the changes
      responses:
        '202':
          description: Workflow committed successfully. The response will be the latest draft version after the commit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workflow not found
          
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/workflow/{slug}/enable/:
    patch:
      summary: Enable/Disable Workflow
      description: Enable or disable a workflow. Disabled workflows will not be executed when triggered. By default, workflows are enabled unless you explicitly disable them.
      operationId: toggle-workflow
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Toggle Workflow
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/workflow/{slug}/enable/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "is_enabled": true
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace to which the workflow belongs (staging, production, etc.)
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: Unique identifier of the workflow. You can get it from workflow settings.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - is_enabled
              properties:
                is_enabled:
                  type: boolean
                  description: Set to true to enable the workflow, false to disable it.
              example:
                is_enabled: true
      responses:
        '202':
          description: Workflow status updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Workflow'
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workflow not found
          
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/schema/:
    get:
      summary: List Schemas
      description: Retrieve a list of schemas in a workspace.
      operationId: list-schemas
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Schemas
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/schema/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Specify if you want to fetch draft or live schema.
      responses:
        '200':
          description: Successfully retrieved list of schemas
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of schemas matching the query
                        example: 5
                      limit:
                        type: integer
                        description: Number of results returned per page
                        example: 10
                      offset:
                        type: integer
                        description: Offset value passed in the request
                        example: 0
                    description: Metadata related to pagination information
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        slug:
                          type: string
                          description: Unique identifier for the schema
                          example: "new-order-placed"
                        name:
                          type: string
                          description: Human-readable name of the schema
                          example: "Order Placed Event"
                        description:
                          type: string
                          nullable: true
                          description: Description of the schema
                          example: "Schema for order placement action"
                        status:
                          type: string
                          enum: ["draft", "live"]
                          description: Status of returned schema. By default, draft version is returned. You can set `mode=live` to fetch the live schema.
                          example: "draft"
                        hash:
                          type: string
                          description: Git-like hash for version tracking
                          example: "382b707d4b1f8999a1xxxxxxxx"
                        json_schema:
                          type: object
                          nullable: true
                          description: Structure of the workflow or event payload. Follows standard [json schema specification](https://json-schema.org/draft/2020-12/schema). You can link this schema to a workflow or event to validate their input payload in API response. Same schema can be linked to multiple workflows and events.
                          example:
                            type: "object"
                            $schema: "https://json-schema.org/draft/2020-12/schema"
                            required: ["order_id", "amount"]
                            properties:
                              order_id:
                                type: "string"
                              amount:
                                type: "string"
                            additionalProperties: true
                        created_at:
                          type: string
                          format: date-time
                          description: When the schema was created
                          example: "2025-08-27T09:30:57.945326Z"
                        updated_at:
                          type: string
                          format: date-time
                          description: When the schema was last updated
                          example: "2025-08-29T15:37:37.650177Z"
                        committed_at:
                          type: string
                          format: date-time
                          nullable: true
                          description: When the schema was last committed. Only available for live schema.
                          example: null
                        commit_message:
                          type: string
                          nullable: true
                          description: Last commit message. Only available for live schema.
                          example: null
                    description: Array of schemas
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 404
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "not_found"
                  type:
                    type: string
                    description: Error type
                    example: "NotFound"
                  message:
                    type: string
                    description: Error message
                    example: "workspace 'demo' not found"
                  detail:
                    type: string
                    description: Detailed error information
                    example: "workspace 'demo' not found"
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "workspace 'demo' not found"
                detail: "workspace 'demo' not found"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/schema/{schema_slug}/:
    get:
      summary: Get Schema
      description: Fetch the JSON schema corresponding to a slug.
      operationId: get-schema
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Schema
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/schema/{schema_slug}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: schema_slug
          required: true
          schema:
            type: string
          description: Unique identifier of the schema
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Mode to fetch schema (draft or live). By default, draft schema is returned.
      responses:
        '200':
          description: Successfully retrieved schema object
          content:
            application/json:
              schema:
                type: object
                properties:
                  slug:
                    type: string
                    description: Unique identifier for the schema
                    example: "new-order-placed"
                  name:
                    type: string
                    description: Human-readable name of the schema
                    example: "Order Placed Event"
                  description:
                    type: string
                    nullable: true
                    description: Description of the schema
                    example: "Schema for order placement action"
                  status:
                    type: string
                    enum: ["draft", "live"]
                    description: Status of returned schema. By default, draft version is returned. You can set `mode=live` to fetch the live schema.
                    example: "draft"
                  hash:
                    type: string
                    description: Git-like hash for version tracking
                    example: "382b707d4b1f8999a1xxxxxxxx"
                  json_schema:
                    type: object
                    nullable: true
                    description: Structure of the workflow or event payload. Follows standard [json schema specification](https://json-schema.org/draft/2020-12/schema). You can link this schema to a workflow or event to validate their input payload in API response. Same schema can be linked to multiple workflows and events.
                    example:
                      type: "object"
                      $schema: "https://json-schema.org/draft/2020-12/schema"
                      required: ["order_id", "amount"]
                      properties:
                        order_id:
                          type: "string"
                        amount:
                          type: "string"
                      additionalProperties: true
                  created_at:
                    type: string
                    format: date-time
                    description: When the schema was created
                    example: "2025-08-27T09:30:57.945326Z"
                  updated_at:
                    type: string
                    format: date-time
                    description: When the schema was last updated
                    example: "2025-08-29T15:37:37.650177Z"
                  committed_at:
                    type: string
                    format: date-time
                    nullable: true
                    description: When the schema was last committed. Only available for live schema.
                    example: null
                  commit_message:
                    type: string
                    nullable: true
                    description: Last commit message. Only available for live schema.
                    example: null
                example:
                  slug: "new-order-placed"
                  name: "Order Placed Event"
                  description: "Schema for order placement action"
                  status: "draft"
                  hash: "382b707d4b1f8999a1xxxxxxxx"
                  json_schema:
                    type: "object"
                    $schema: "https://json-schema.org/draft/2020-12/schema"
                    required: ["order_id", "amount"]
                    properties:
                      order_id:
                        type: "string"
                      amount:
                        type: "string"
                    additionalProperties: true
                  created_at: "2025-08-27T09:30:57.945326Z"
                  updated_at: "2025-08-29T15:37:37.650177Z"
                  committed_at: null
                  commit_message: null
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 404
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "not_found"
                  type:
                    type: string
                    description: Error type
                    example: "NotFound"
                  message:
                    type: string
                    description: Error message
                    example: "workspace 'staging4' not found"
                  detail:
                    type: string
                    description: Detailed error information
                    example: "workspace 'staging4' not found"
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "workspace 'staging4' not found"
                detail: "workspace 'staging4' not found"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

    post:
      summary: Create/Update Schema
      description: Upset draft version of a JSON schema. Creates a new schema if it doesn't exist.
      operationId: upsert-schema
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Upsert Schema
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/schema/{schema_slug}/?commit=true&commit_message=Initial%20schema%20creation" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "name": "Order Placed Event",
                "description": "Schema for order placement action",
                "json_schema": {
                  "type": "object",
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "required": ["order_id", "amount"],
                  "properties": {
                    "order_id": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: schema_slug
          required: true
          schema:
            type: string
          description: Unique identifier of the schema
        - in: query
          name: commit
          required: false
          schema:
            type: boolean
            default: false
          description: Set to true to commit the schema immediately after creation/update
        - in: query
          name: commit_message
          required: false
          schema:
            type: string
          description: Commit message describing the changes (required when commit=true)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - json_schema
              properties:
                name:
                  type: string
                  description: Human-readable name of the schema
                  example: "Order Placed Event"
                description:
                  type: string
                  nullable: true
                  description: Description of the schema. Can be used to describe which action this schema is linked to.
                  example: "Schema for order placement action"
                json_schema:
                  type: object
                  description: Structure of the workflow or event payload. Follows standard [json schema specification](https://json-schema.org/draft/2020-12/schema). You can link this schema to a workflow or event to validate their input payload in API response. Same schema can be linked to multiple workflows and events.
                  example:
                    type: "object"
                    $schema: "https://json-schema.org/draft/2020-12/schema"
                    required: ["order_id", "amount"]
                    properties:
                      order_id:
                        type: "string"
                      amount:
                        type: "string"
                    additionalProperties: true
              example:
                name: "Order Placed Event"
                description: "Schema for order placement action"
                json_schema:
                  type: "object"
                  $schema: "https://json-schema.org/draft/2020-12/schema"
                  required: ["order_id", "amount"]
                  properties:
                    order_id:
                      type: "string"
                    amount:
                      type: "string"
                  additionalProperties: true
      responses:
        '200':
          description: Successfully retrieved schema object
          content:
            application/json:
              schema:
                type: object
                properties:
                  slug:
                    type: string
                    description: Unique identifier for the schema
                    example: "new-order-placed"
                  name:
                    type: string
                    description: Human-readable name of the schema
                    example: "Order Placed Event"
                  description:
                    type: string
                    nullable: true
                    description: Description of the schema
                    example: "Schema for order placement action"
                  status:
                    type: string
                    enum: ["draft", "live"]
                    description: Status of returned schema. By default, draft version is returned. You can set `mode=live` to fetch the live schema.
                    example: "draft"
                  hash:
                    type: string
                    description: Git-like hash for version tracking
                    example: "382b707d4b1f8999a1xxxxxxxx"
                  json_schema:
                    type: object
                    nullable: true
                    description: JSON schema passed in the request body.
                  created_at:
                    type: string
                    format: date-time
                    description: When the schema was created
                    example: "2025-08-27T09:30:57.945326Z"
                  updated_at:
                     type: string
                     format: date-time
                     description: When the schema was last updated
                     example: "2025-08-29T15:37:37.650177Z"
                  commit_result:
                    type: object
                    nullable: true
                    description: Commit result when commit=true is passed in query parameter
                    properties:
                      is_committed:
                        type: boolean
                        description: Whether the schema was successfully committed
                        example: false
                      errors:
                        type: array
                        items:
                          type: string
                        description: List of errors if commit failed
                        example: "hash: no uncommitted changes found"
                    example:
                      is_committed: false
                      errors: ["hash: no uncommitted changes found"]
                example:
                  slug: "new-order-placed"
                  name: "Order Placed Event"
                  description: "Schema for order placement action"
                  status: "draft"
                  hash: "382b707d4b1f8999a1xxxxxxxx"
                  json_schema:
                    type: "object"
                    $schema: "https://json-schema.org/draft/2020-12/schema"
                    required: ["order_id", "amount"]
                    properties:
                      order_id:
                        type: "string"
                      amount:
                        type: "string"
                    additionalProperties: true
                  created_at: "2025-08-27T09:30:57.945326Z"
                  updated_at: "2025-08-29T15:37:37.650177Z"
                  commit_result:
                    is_committed: false
                    errors: ["hash: no uncommitted changes found"]
        '400':
          description: Invalid schema format
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 400
                  error_code:
                    type: string
                    description: Error code identifier.
                    example: "error"
                  type:
                    type: string
                    description: Error type
                    example: "ValidationError"
                  message:
                    type: string
                    description: Error message
                    example: "{\"json_schema\": [\"Schema looks like JSON data, not a JSON Schema. Include keywords like '$schema', 'type', 'properties', or '$defs'.\"]}"
                  detail:
                    type: object
                    description: Detailed error information
                    example:
                      json_schema:
                        - "Schema looks like JSON data, not a JSON Schema. Include keywords like '$schema', 'type', 'properties', or '$defs'."
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "{\"json_schema\": [\"Schema looks like JSON data, not a JSON Schema. Include keywords like '$schema', 'type', 'properties', or '$defs'.\"]}"
                detail:
                  json_schema:
                    - "Schema looks like JSON data, not a JSON Schema. Include keywords like '$schema', 'type', 'properties', or '$defs'."
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 404
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "not_found"
                  type:
                    type: string
                    description: Error type
                    example: "NotFound"
                  message:
                    type: string
                    description: Error message
                    example: "workspace 'staging4' not found"
                  detail:
                    type: string
                    description: Detailed error information
                    example: "workspace 'staging4' not found"
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "workspace 'staging4' not found"
                detail: "workspace 'staging4' not found"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/schema/{schema_slug}/commit/:
    patch:
      summary: Commit Schema
      description: Commit a draft schema to make it live. Changes will start to take effect as soon as it's live.
      operationId: commit-schema
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Commit Schema
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/schema/{schema_slug}/commit/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: schema_slug
          required: true
          schema:
            type: string
          description: Unique identifier of the schema
        - in: query
          name: commit_message
          required: false
          schema:
            type: string
          description: Commit message describing the changes
      responses:
        '200':
          description: Successfully retrieved schema object
          content:
            application/json:
              schema:
                type: object
                properties:
                  slug:
                    type: string
                    description: Unique identifier for the schema
                    example: "new-order-placed"
                  name:
                    type: string
                    description: Human-readable name of the schema
                    example: "Order Placed Event"
                  description:
                    type: string
                    nullable: true
                    description: Description of the schema. Can be used to describe which action this schema is linked to.
                    example: "Schema for order placement action"
                  status:
                    type: string
                    enum: ["draft", "live"]
                    description: Status of returned schema. By default, draft version is returned. You can set `mode=live` to fetch the live schema.
                    example: "live"
                  hash:
                    type: string
                    description: Git-like hash for version tracking
                    example: "382b707d4b1f8999a1xxxxxxxx"
                  json_schema:
                    type: object
                    nullable: true
                    description: updated json schema
                  created_at:
                    type: string
                    format: date-time
                    description: When the schema was created
                    example: "2025-08-27T09:30:57.945326Z"
                  updated_at:
                    type: string
                    format: date-time
                    description: When the schema was last updated
                    example: "2025-08-29T15:37:37.650177Z"
                  committed_at:
                    type: string
                    format: date-time
                    description: When the schema was last committed
                    example: "2025-09-01T18:35:00.270698Z"
                  commit_message:
                    type: string
                    description: Last commit message
                    example: "required fields updated"
                example:
                  slug: "new-order-placed"
                  name: "Order Placed Event"
                  description: "Schema for order placement action"
                  status: "live"
                  hash: "382b707d4b1f8999a1xxxxxxxx"
                  json_schema:
                    type: "object"
                    $schema: "https://json-schema.org/draft/2020-12/schema"
                    required: ["order_id", "amount"]
                    properties:
                      order_id:
                        type: "string"
                      amount:
                        type: "string"
                    additionalProperties: true
                  created_at: "2025-08-27T09:30:57.945326Z"
                  updated_at: "2025-08-29T15:37:37.650177Z"
                  committed_at: "2025-09-01T18:35:00.270698Z"
                  commit_message: "required fields updated"
        '404':
          description: Schema not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 404
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "not_found"
                  type:
                    type: string
                    description: Error type
                    example: "NotFound"
                  message:
                    type: string
                    description: Error message
                    example: "workspace 'staging4' not found"
                  detail:
                    type: string
                    description: Detailed error information
                    example: "workspace 'staging4' not found"
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "workspace 'staging4' not found"
                detail: "workspace 'staging4' not found"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/event/:
    get:
      summary: List Events
      description: Retrieve a list of events in a workspace.
      operationId: list-events
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Events
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/event/?limit=10&offset=0" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: limit
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 10
          description: Number of events to return per page (max 100)
        - in: query
          name: offset
          required: false
          schema:
            type: integer
            minimum: 0
            default: 0
          description: Number of events to skip for pagination
      responses:
        '200':
          description: Successfully retrieved list of events
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of events matching the query
                        example: 15
                      limit:
                        type: integer
                        description: Number of results returned per page
                        example: 10
                      offset:
                        type: integer
                        description: Offset value passed in the request
                        example: 0
                    description: Metadata related to pagination information
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: Event name
                          example: "user_signup"
                        description:
                          type: string
                          description: Description of the event
                          example: "Triggered whenever a new user successfully signs up on the platform"
                        payload_schema:
                          type: object
                          properties:
                            schema:
                              type: string
                              description: Linked schema identifier
                              example: "user_signup_v1"
                            version_no:
                              type: integer
                              description: Schema version number
                              example: 1
                        created_at:
                          type: string
                          format: date-time
                          description: When the event was created
                          example: "2025-08-27T09:30:57.945326Z"
                        $schema:
                          type: string
                          description: JSON Schema reference for how the event API call should be structured
                          example: "https://schema.suprsend.com/event/v1/schema.json"
                    description: Array of events
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

    post:
      summary: Create Event
      description: Add events and their linked schemas in SuprSend
      operationId: create-event
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Create Event
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/event/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "name": "User Signup Event",
                "description": "Triggered whenever a new user successfully signs up on the platform",
                "payload_schema": {
                  "schema": "user_signup_v1"
                }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: Unique Identifier of the Event.
                  example: "User Signup Event"
                description:
                  type: string
                  description: Description of the event. Can be used to describe which action this event is linked to.
                  example: "Triggered whenever a new user successfully signs up on the platform"
                payload_schema:
                  type: object
                  required:
                    - schema
                  properties:
                    schema:
                      type: string
                      description: Linked schema slug to validate event properties structure. You can create a schema via [Create Schema](/reference/create-schema) endpoint and then link it here.
                      example: "user_signup_v1"
                    version_no:
                      type: integer
                      description: Schema version number to link. By default, live version is always picked for validation.
                      example: 1
              example:
                name: "User Signup Event"
                description: "Triggered whenever a new user successfully signs up on the platform"
                payload_schema:
                  schema: "user_signup_v1"
                  version_no: 1
      responses:
        '200':
          description: Updated event details
          content:
            application/json:
              schema:
                type: object
              example:
                name: "user_signup"
                description: "Triggered whenever a new user successfully signs up on the platform"
                payload_schema:
                  schema: "user_signup_v1"
                  version_no: 1
                created_at: "2025-08-27T09:30:57.945326Z"
                $schema: "https://schema.suprsend.com/event/v1/schema.json"
        '400':
          description: Invalid event format
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 400
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "error"
                  type:
                    type: string
                    description: Error type
                    example: "ValidationError"
                  message:
                    type: string
                    description: Error message
                    example: "{\"name\": [\"This field is required.\"]}"
                  detail:
                    type: object
                    description: Detailed error information
                    example:
                      name: ["This field is required."]
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "{\"name\": [\"This field is required.\"]}"
                detail:
                  name: ["This field is required."]
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/event/{url_encoded_event_name}/:
    get:
      summary: Get Event Details
      description: Fetch event details and its linked schema.
      operationId: get-event
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/event/{url_encoded_event_name}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: url_encoded_event_name
          required: true
          schema:
            type: string
          description: URL encoded event name. Example - `SHIPMENT%20ARRIVED`
      responses:
        '200':
          description: Successfully retrieved event
          content:
            application/json:
              schema:
                type: object
                properties:
                  name:
                    type: string
                    description: Event name
                    example: "user_signup"
                  description:
                    type: string
                    description: Description of the event
                    example: "Triggered whenever a new user successfully signs up on the platform"
                  payload_schema:
                    type: object
                    properties:
                      schema:
                        type: string
                        description: Linked schema slug
                        example: "user_signup_v1"
                      version_no:
                        type: integer
                        description: Linked schema version number. if `null`, live version will be picked for validation.
                        example: 1
                  created_at:
                    type: string
                    format: date-time
                    description: When the event was created
                    example: "2025-08-27T09:30:57.945326Z"
                  $schema:
                    type: string
                    description: JSON Schema reference for how the event API call should be structured.
                    example: "https://schema.suprsend.com/event/v1/schema.json"
                example:
                  name: "user_signup"
                  description: "Triggered whenever a new user successfully signs up on the platform"
                  payload_schema:
                    schema: "user_signup_v1"
                    version_no: 1
                  created_at: "2025-08-27T09:30:57.945326Z"
                  $schema: "https://schema.suprsend.com/event/v1/schema.json"
        '400':
          description: Invalid event format
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 400
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "error"
                  type:
                    type: string
                    description: Error type
                    example: "ValidationError"
                  message:
                    type: string
                    description: Error message
                    example: "{\"name\": [\"This field is required.\"]}"
                  detail:
                    type: object
                    description: Detailed error information
                    example:
                      name: ["This field is required."]
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "{\"name\": [\"This field is required.\"]}"
                detail:
                  name: ["This field is required."]
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

    patch:
      summary: Update Event
      description: Update event description and its linked schema.
      operationId: update-event
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Update Event
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/event/{url_encoded_event_name}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "description": "Triggered whenever a new user successfully signs up on the platform",
                "payload_schema": {
                  "schema": "user_signup_v1"
                }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: url_encoded_event_name
          required: true
          schema:
            type: string
          description: URL encoded event name
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                description:
                  type: string
                  description: Description of the event. Can be used to describe which action this event is linked to.
                  example: "Triggered whenever a new user successfully signs up on the platform"
                payload_schema:
                  type: object
                  required:
                    - schema
                  properties:
                    schema:
                      type: string
                      description: Linked schema slug to validate event properties structure. You can create a schema via [Create Schema](/reference/create-schema) endpoint and then link it here.
                      example: "user_signup_v1"
                    version_no:
                      type: integer
                      description: Schema version number to link. By default, live version is always picked for validation.
                      example: null
              example:
                description: "Triggered whenever a new user successfully signs up on the platform"
                payload_schema:
                  schema: "user_signup_v1"
      responses:
        '200':
          description: Updated event details
          content:
            application/json:
              schema:
                type: object
              example:
                name: "user_signup"
                description: "Triggered whenever a new user successfully signs up on the platform"
                payload_schema:
                  schema: "user_signup_v1"
                  version_no: 1
                created_at: "2025-08-27T09:30:57.945326Z"
                $schema: "https://schema.suprsend.com/event/v1/schema.json"
        '400':
          description: Invalid event format
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 400
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "error"
                  type:
                    type: string
                    description: Error type
                    example: "ValidationError"
                  message:
                    type: string
                    description: Error message
                    example: "{\"payload_schema\": [\"Schema is required\"]}"
                  detail:
                    type: object
                    description: Detailed error information
                    example:
                      payload_schema: ["Schema is required"]
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "{\"payload_schema\": [\"Schema is required\"]}"
                detail:
                  payload_schema: ["Schema is required"]
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/event/{url_encoded_event_name}/linked_workflows/:
    get:
      summary: Get Linked Workflows
      description: Fetch list of all workflows where this event is used
      operationId: get-linked-workflows
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Linked Workflows
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/event/{url_encoded_event_name}/linked_workflows/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: url_encoded_event_name
          required: true
          schema:
            type: string
          description: URL encoded event name. Example - `SHIPMENT%20ARRIVED`
      responses:
        '200':
          description: Successfully retrieved linked workflows
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        slug:
                          type: string
                          description: Workflow slug where this event is used
                          example: "onboarding_series"
                        usage:
                          type: array
                          items:
                            type: string
                            description: Usage of the event in the workflow. Could be one of `Trigger Event`, `Wait Event` or `Success Metric Event`
                            example: "Wait Event"
              example:
                results:
                  - slug: "onboarding_series"
                    usage:
                      - "Trigger Event"
        '404':
          description: Event not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 404
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "not_found"
                  type:
                    type: string
                    description: Error type
                    example: "NotFound"
                  message:
                    type: string
                    description: Error message
                    example: "Event 'user_signup' not found in workspace 'staging'"
                  detail:
                    type: string
                    description: Detailed error information
                    example: "Event 'user_signup' not found in workspace 'staging'"
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "Event 'user_signup' not found in workspace 'staging'"
                detail: "Event 'user_signup' not found in workspace 'staging'"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/event/{url_encoded_event_name}/delink_schema/:
    patch:
      summary: Delink Schema from Event
      description: Remove the linked schema from an event, making it schema-less. This allows the event to accept any payload structure without validation against a predefined schema.
      operationId: delink-event-schema
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delink Schema from Event
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/event/{url_encoded_event_name}/delink_schema/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: url_encoded_event_name
          required: true
          schema:
            type: string
          description: URL encoded event name. Example - `SHIPMENT%20ARRIVED`
      responses:
        '200':
          description: Successfully delinked schema from event
          content:
            application/json:
              schema:
                type: object
                properties:
                  name:
                    type: string
                    description: Event name
                    example: "user_signup"
                  description:
                    type: string
                    description: Description of the event
                    example: "Triggered whenever a new user successfully signs up on the platform"
                  payload_schema:
                    type: null
                    description: Schema has been delinked from the event
                    example: null
                  created_at:
                    type: string
                    format: date-time
                    description: When the event was created
                    example: "2025-08-27T09:30:57.945326Z"
                  $schema:
                    type: string
                    description: JSON Schema reference for how the event API call should be structured
                    example: "https://schema.suprsend.com/event/v1/schema.json"
                example:
                  name: "user_signup"
                  description: "Triggered whenever a new user successfully signs up on the platform"
                  payload_schema: null
                  created_at: "2025-08-27T09:30:57.945326Z"
                  $schema: "https://schema.suprsend.com/event/v1/schema.json"
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 400
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "error"
                  type:
                    type: string
                    description: Error type
                    example: "ValidationError"
                  message:
                    type: string
                    description: Error message
                    example: "Event does not have a linked schema to delink"
                  detail:
                    type: object
                    description: Detailed error information
                    example:
                      payload_schema: ["Event does not have a linked schema to delink"]
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "Event does not have a linked schema to delink"
                detail:
                  payload_schema: ["Event does not have a linked schema to delink"]
        '404':
          description: Event not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    description: HTTP status code
                    example: 404
                  error_code:
                    type: string
                    description: Error code identifier
                    example: "not_found"
                  type:
                    type: string
                    description: Error type
                    example: "NotFound"
                  message:
                    type: string
                    description: Error message
                    example: "Event 'user_signup' not found in workspace 'staging'"
                  detail:
                    type: string
                    description: Detailed error information
                    example: "Event 'user_signup' not found in workspace 'staging'"
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "Event 'user_signup' not found in workspace 'staging'"
                detail: "Event 'user_signup' not found in workspace 'staging'"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.

  /v1/{workspace}/preference_category/:
    get:
      summary: Get Preference Category
      description: Retrieve the current preference category for a workspace
      operationId: get-category
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Category
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/preference_category/" \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json"
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
          example: "my-workspace"
        - in: query
          name: mode
          required: true
          schema:
            type: string
            enum: [live, draft]
          description: Mode to retrieve categories. Use 'live' for active categories or 'draft' for current draft.
          example: "draft"
      responses:
        '200':
          description: Successfully retrieved 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'
                  version_no:
                    type: integer
                    description: Version number field as an identifier to track the version
                    example: 1
                  status:
                    type: string
                    description: Current status of the preference category
                    enum: [draft, active]
                  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
                      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"
                        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: null
                            properties: null
                  - root_category: "promotional"
                    sections:
                      - name: "Product Updates"
                        categories:
                          - category: "newsletter"
                            name: "Newsletter"
                            default_preference: "opt_out"
                            digest_schedule: null
                            properties: null
                version_no: 15
                status: "draft"
                validation_result:
                  is_valid: false
                  errors:
                    - "it seems some subcategories have been deleted in this version, on which active workflows are configured. missing subcategories: [\"chapter-added\" \"forecast\" \"onboarding-guide\" \"training-new\"]"
        '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"

    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
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      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
                          }
                        ]
                      }
                    ]
                  }
                ]
              }'
      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"

  /v1/{workspace}/preference_category/commit/:
    patch:
      summary: Commit Preference Category
      description: Commit draft changes to the preference category to make them live
      operationId: commit-category
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Commit Category
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/preference_category/commit/?commit_message=Added%20password-reset%20category" \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json"
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: commit_message
          required: true
          schema:
            type: string
          description: Commit message describing the changes being made live.
      responses:
        '200':
          description: Successfully committed 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: "active"
                  version_no:
                    type: integer
                    description: Version number field as an identifier to track the version
                    example: 2
                  commit_message:
                    type: string
                    description: Commit message describing the changes that were made live
                    example: "Added password-reset category"
                  committed_at:
                    type: string
                    format: date-time
                    description: Timestamp when the changes were committed
                    example: "2025-10-03T09:52:55.273317+00:00"
              example:
                $schema: "https://schema.suprsend.com/preference_category/v1/schema.json"
                root_categories:
                  - root_category: "system"
                    sections:
                      - name: "Alerts"
                        description: null
                        tags: null
                        categories:
                          - category: "critical-updates"
                            name: "Critical Updates"
                            description: "Important system alerts requiring immediate attention"
                            default_preference: "opt_in"
                            default_mandatory_channels: null
                            default_opt_in_channels: null
                            tags: null
                            digest_schedule: null
                            properties: null
                  - root_category: "transactional"
                    sections:
                      - name: "Task Updates"
                        description: null
                        tags: null
                        categories:
                          - category: "tagged-to-me"
                            name: "Tagged to Me"
                            description: "Status updates 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: null
                            properties: null
                  - 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: 2
                status: "active"
                commit_message: "Added password-reset category"
                committed_at: "2025-10-03T09:52:55.273317+00:00"
        '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"

  /v1/{workspace}/preference_category/translation/locale/:
    get:
      summary: List Category Translations
      description: Returns all the locales for which translation is uploaded for preference categories.
      operationId: list-category-translation-locales
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Translation
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/preference_category/translation/locale/" \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json"
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
          example: "my-workspace"
      responses:
        '200':
          description: Successfully retrieved list of translation locales
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    description: Array of locale objects for which translations are available
                    items:
                      type: object
                      properties:
                        locale:
                          type: string
                          description: Locale code (e.g., en, es, es-AR)
                          example: "es"
              example:
                results:
                  - locale: "en"
                  - locale: "en-NA"
                  - locale: "es"
                  - locale: "es-AR"
                  - locale: "es-BO"
        '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"

  /v1/{workspace}/preference_category/translation/content/{locale}/:
    get:
      summary: Get Category Translation
      description: Fetch translation content for a given locale for preference categories and sections.
      operationId: get-category-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Translation
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/preference_category/translation/content/{locale}/" \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json"
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
          example: "my-workspace"
        - in: path
          name: locale
          required: true
          schema:
            type: string
          description: Locale code (e.g., es, fr, de, ja)
          example: "es"
      responses:
        '200':
          description: Successfully retrieved translation content
          content:
            application/json:
              schema:
                type: object
                properties:
                  sections:
                    type: object
                    description: Translations for sections, keyed by section slug
                    additionalProperties:
                      type: object
                      properties:
                        name:
                          type: string
                          nullable: true
                          description: Translated section name
                          example: "Section Nik pour transactionnel"
                        description:
                          type: string
                          nullable: true
                          description: Translated section description
                          example: "Description de la section Nik pour transactionnel"
                  categories:
                    type: object
                    description: Translations for categories, keyed by category slug
                    additionalProperties:
                      type: object
                      properties:
                        name:
                          type: string
                          nullable: true
                          description: Translated category name
                          example: "Sous-catégorie Nik"
                        description:
                          type: string
                          nullable: true
                          description: Translated category description
                          example: "Sous-catégorie Nik 1"
              example:
                sections:
                  new-5:
                    name: "nouveau 5"
                    description: null
                  nik-section-for-transactional:
                    name: "Section Nik pour transactionnel"
                    description: "Description de la section Nik pour transactionnel"
                categories:
                  nik-sub-category:
                    name: "Sous-catégorie Nik"
                    description: "Sous-catégorie Nik 1"
                  amount-refunded:
                    name: "Montant remboursé"
                    description: null
        '400':
          description: Invalid or unsupported locale
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  message:
                    type: string
                    example: "invalid/unsupported locale: 'apl'"
              example:
                code: 400
                message: "invalid/unsupported locale: 'apl'"
        '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 or translation not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "translation not found for locale: {locale}"
              example:
                code: 404
                message: "translation not found for locale: es"

    post:
      summary: Add or Update Category Translation
      description: Add or update translation content for a given locale for preference categories and sections.
      operationId: add-category-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Add Translation
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/preference_category/translation/content/{locale}/" \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json" \
              --data '{
                "sections": {
                  "account-updates": {
                    "name": "Actualizaciones de Cuenta",
                    "description": "Notificaciones importantes relacionadas con la cuenta"
                  }
                },
                "categories": {
                  "password-reset": {
                    "name": "Restablecimiento de Contraseña",
                    "description": "Notificaciones cuando se restablece la contraseña"
                  }
                }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
          example: "my-workspace"
        - in: path
          name: locale
          required: true
          schema:
            type: string
          description: Locale code (e.g., es, fr, de, ja)
          example: "es"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                sections:
                  type: object
                  description: Translations for sections, keyed by section slug
                  additionalProperties:
                    type: object
                    properties:
                      name:
                        type: string
                        nullable: true
                        description: Translated section name
                        example: "Section Nik pour transactionnel"
                      description:
                        type: string
                        nullable: true
                        description: Translated section description
                        example: "Description de la section Nik pour transactionnel"
                categories:
                  type: object
                  description: Translations for categories, keyed by category slug
                  additionalProperties:
                    type: object
                    properties:
                      name:
                        type: string
                        nullable: true
                        description: Translated category name
                        example: "Sous-catégorie Nik"
                      description:
                        type: string
                        nullable: true
                        description: Translated category description
                        example: "Sous-catégorie Nik 1"
            example:
              sections:
                account-updates:
                  name: "Actualizaciones de Cuenta"
                  description: "Notificaciones importantes relacionadas con la cuenta"
              categories:
                password-reset:
                  name: "Restablecimiento de Contraseña"
                  description: "Notificaciones cuando se restablece la contraseña"
      responses:
        '200':
          description: Successfully added or updated translation
          content:
            application/json:
              schema:
                type: object
                properties:
                  sections:
                    type: object
                    description: Translations for sections, keyed by section slug
                    additionalProperties:
                      type: object
                      properties:
                        name:
                          type: string
                          nullable: true
                          description: Translated section name
                        description:
                          type: string
                          nullable: true
                          description: Translated section description
                  categories:
                    type: object
                    description: Translations for categories, keyed by category slug
                    additionalProperties:
                      type: object
                      properties:
                        name:
                          type: string
                          nullable: true
                          description: Translated category name
                        description:
                          type: string
                          nullable: true
                          description: Translated category description
              example:
                sections:
                  new-5:
                    name: null
                    description: null
                  nik-section-for-transactional:
                    name: null
                    description: null
                categories:
                  nik-sub-category:
                    name: null
                    description: null
                  amount-refunded:
                    name: null
                    description: null
        '400':
          description: Invalid or unsupported locale, or invalid translation data
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  message:
                    type: string
                    example: "invalid/unsupported locale: 'apl'"
              example:
                code: 400
                message: "invalid/unsupported locale: 'apl'"
        '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"

    delete:
      summary: Delete Category Translation
      description: Delete translation content for a given locale for preference categories and sections.
      operationId: delete-category-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delete Translation
          source: |
            curl -X DELETE "https://management-api.suprsend.com/v1/{workspace}/preference_category/translation/content/{locale}/" \
              --header "Authorization: ServiceToken {token}" \
              --header "Content-Type: application/json"
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
          example: "my-workspace"
        - in: path
          name: locale
          required: true
          schema:
            type: string
          description: Locale code (e.g., es, fr, de, ja)
          example: "es"
      responses:
        '204':
          description: Successfully deleted translation
        '400':
          description: Invalid or unsupported locale
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  message:
                    type: string
                    example: "invalid/unsupported locale: 'apl'"
              example:
                code: 400
                message: "invalid/unsupported locale: 'apl'"
        '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 or translation not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 404
                  message:
                    type: string
                    example: "translation not found for locale: {locale}"
              example:
                code: 404
                message: "translation not found for locale: es"

  /v1/{workspace}/translation/:
    get:
      summary: List Translations
      description: Retrieve a list of translation files in a workspace. By default, returns draft translations. Use the mode query parameter to filter by draft or live translations.
      operationId: list-translations
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Translations
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/translation/" \
              --header 'Authorization: ServiceToken <token>' 
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Mode to filter translations (draft or live). By default, draft translations are returned.
        - in: query
          name: limit
          schema:
            type: integer
            description: Maximum number of results per page
            example: 10
          description: Maximum number of results per page
        - in: query
          name: offset
          schema:
            type: integer
            example: 0
          description: Number of results to skip
      responses:
        '200':
          description: Successfully retrieved list of translations
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of translation files
                      limit:
                        type: integer
                        description: Maximum number of results per page
                      offset:
                        type: integer
                        description: Number of results to skip in case offset is passed in the request
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        filename:
                          type: string
                          description: Name of the translation file. Should be in the format of <locale>.json or <namespace>.<locale>.json.
                          example: "en.json"
                        locale:
                          type: string
                          description: Locale code for the translation file. This would be matched with user locale code to fetch translation.
                          example: "en"
                        locale_name:
                          type: string
                          description: Human-readable name of the locale
                          example: "English"
                        namespace:
                          type: string
                          nullable: true
                          description: Namespace for the translation file, if any. Namespace can be used to group translations by feature or module.
                          example: task
                        action:
                          type: string
                          description: action done in the version compared to last commit.
                          enum: ["added", "updated", "deleted", "unchanged"]
                          example: "added"
                        updated_at:
                          type: string
                          format: date-time
                          description: When the translation file was last updated
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - filename: "en.json"
                    locale: "en"
                    locale_name: "English"
                    namespace: null
                    action: "unchanged"
                    updated_at: "2025-10-30T12:23:50.380614Z"
                  - filename: "fr.json"
                    locale: "fr"
                    locale_name: "French"
                    namespace: null
                    action: "added"
                    updated_at: "2025-10-28T07:59:43.397124Z"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workspace not found
  
  /v1/{workspace}/translation/content/{locale_file}/:
    post:
      summary: Add Translation
      description: Upload or create a new translation file. The file content should be valid JSON following the translation file structure.
      operationId: add-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Add Translation
          source: |
            curl -X POST "https://management-api.suprsend.com/v1/{workspace}/translation/content/{locale_file}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "content": {
                  "welcome": "Bienvenue",
                  "goodbye": "Au revoir"
                }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: locale_file
          required: true
          schema:
            type: string
          description: Locale file name (e.g., "fr.json", "es-MX.json", "auth.en.json")
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - locale
                - content
              properties:
                locale:
                  type: string
                  description: Locale file name (e.g., "fr.json", "es-MX.json", "auth.en.json")
                  example: "fr.json"
                content:
                  type: object
                  description: Translation key-value pairs in JSON format
                  additionalProperties: true
            example:
              locale: "fr.json"
              content:
                welcome: "Bienvenue"
                goodbye: "Au revoir"
                greeting: "Bonjour, {{name}}!"
      responses:
        '201':
          description: Translation file successfully updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  filename:
                    type: string
                    description: Name of the translation file
                    example: "fr.json"
                  locale:
                    type: string
                    description: Locale code for the translation file
                    example: "fr"
                  locale_name:
                    type: string
                    description: Human-readable name of the locale
                    example: "French"
                  namespace:
                    type: string
                    nullable: true
                    description: Namespace for the translation file, if any. Namespace can be used to group translations by feature or module.
                    example: null
                  action:
                    type: string
                    description: action done in the version compared to last commit.
                    enum: ["added", "updated", "deleted", "unchanged"]
                    example: "updated"
                  updated_at:
                    type: string
                    format: date-time
                    description: When the translation file was last updated
                  content:
                    type: object
                    description: Translation key-value pairs
                    additionalProperties:
                      type: string
              example:
                filename: "fr.json"
                locale: "fr"
                locale_name: "French"
                namespace: null
                action: "updated"
                updated_at: "2025-10-29T17:14:33.048313Z"
                content:
                  task_created: "Tâche créée"
                  task_completed: "Tâche terminée"
                  task_due: "Tâche due"
                  task_assigned: "Tâche assignée"
        '400':
          description: Invalid translation format
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                    example: 400
                  error_code:
                    type: string
                    example: "validation_error"
                  type:
                    type: string
                    example: "ValidationError"
                  message:
                    type: string
                    example: "Invalid JSON format"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workspace not found
    get:
      summary: Get Translation
      description: Retrieve the content of a translation file for a specific locale file.
      operationId: get-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Translation
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/translation/content/fr.json/" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
            description: Workspace slug (staging, production, etc.)
        - in: path
          name: locale_file
          required: true
          schema:
            type: string
            description: Locale file name (e.g., "fr.json", "es-MX.json", "auth.en.json")
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
            description: Mode to fetch translation (draft or live). By default, draft translation is returned.
      responses:
        '200':
          description: Successfully retrieved translation content
          content:
            application/json:
              schema:
                type: object
                properties:
                  filename:
                    type: string
                    description: Name of the translation file
                    example: "fr.json"
                  locale:
                    type: string
                    description: Locale code for the translation file
                    example: "fr"
                  locale_name:
                    type: string
                    description: Human-readable name of the locale
                    example: "French"
                  namespace:
                    type: string
                    nullable: true
                    description: Namespace for the translation file, if any
                    example: null
                  action:
                    type: string
                    description: action done in the version compared to last commit.
                    enum: ["added", "updated", "deleted", "unchanged"]
                    example: "updated"
                  updated_at:
                    type: string
                    format: date-time
                    description: When the translation file was last updated
                  content:
                    type: object
                    description: Translation key-value pairs
                    additionalProperties:
                      type: string
              example:
                filename: "fr.json"
                locale: "fr"
                locale_name: "French"
                namespace: null
                action: "updated"
                updated_at: "2025-10-29T17:14:33.048313Z"
                content:
                  task_created: "Tâche créée"
                  task_completed: "Tâche terminée"
                  task_due: "Tâche due"
                  task_assigned: "Tâche assignée"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Translation file or workspace not found
    delete:
      summary: Delete Translation
      description: Marks a file for deletion in the next commit. Actual deletion will happen when you commit the draft.
      operationId: delete-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Delete Translation
          source: |
            curl -X DELETE "https://management-api.suprsend.com/v1/{workspace}/translation/content/{locale_file}/" \
              --header 'Authorization: ServiceToken <token>' 
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: locale_file
          required: true
          schema:
            type: string
          description: Locale file name (e.g., "fr.json", "es-MX.json", "auth.en.json")
          example: "fr.json"
      responses:
        '204':
          description: Translation file deleted successfully
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Translation file or workspace not found

  /v1/{workspace}/translation/version/{version}/:
    get:
      summary: Get Translation History
      description: Retrieve version history information for translations, including all versions and their details.
      operationId: get-translation-history
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Translation History
          source: |
            curl -X GET "https://management-api.suprsend.com/v1/{workspace}/translation/version/{version_no}/" \
              --header 'Authorization: ServiceToken <token>' 
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: version
          required: true
          schema:
            type: integer
          description: Version number to retrieve
          example: 1
      responses:
        '200':
          description: Successfully retrieved translation version history
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of translation files
                      limit:
                        type: integer
                        description: Maximum number of results per page
                      offset:
                        type: integer
                        description: Number of results to skip in case offset is passed in the request
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        filename:
                          type: string
                          description: Name of the translation file. Should be in the format of <locale>.json or <namespace>.<locale>.json.
                          example: "en.json"
                        locale:
                          type: string
                          description: Locale code for the translation file. This would be matched with user locale code to fetch translation.
                          example: "en"
                        locale_name:
                          type: string
                          description: Human-readable name of the locale
                          example: "English"
                        namespace:
                          type: string
                          nullable: true
                          description: Namespace for the translation file, if any. Namespace can be used to group translations by feature or module.
                          example: task
                        action:
                          type: string
                          description: action done in the version compared to last commit.
                          enum: ["added", "updated", "deleted", "unchanged"]
                          example: "added"
                        updated_at:
                          type: string
                          format: date-time
                          description: When the translation file was last updated
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - filename: "en.json"
                    locale: "en"
                    locale_name: "English"
                    namespace: null
                    action: "unchanged"
                    updated_at: "2025-10-30T12:23:50.380614Z"
                  - filename: "fr.json"
                    locale: "fr"
                    locale_name: "French"
                    namespace: null
                    action: "added"
                    updated_at: "2025-10-28T07:59:43.397124Z"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Version or workspace not found

  /v1/{workspace}/translation/version/{version_no}/rollback/:
    post:
      summary: Rollback Translation
      description: Rollback translations to a previous version. This will replace all files with what was available at the previous version.
      operationId: rollback-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Rollback Translation
          source: |
            curl -X POST "https://stagingapi.suprsend.com/v1/{workspace}/translation/version/{version_no}/rollback/" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: path
          name: version_no
          required: true
          schema:
            type: integer
          description: Version number to rollback to
          example: 1
      responses:
        '200':
          description: Details of available translation files after rollback.
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of translation files
                      limit:
                        type: integer
                        description: Maximum number of results per page
                      offset:
                        type: integer
                        description: Number of results to skip in case offset is passed in the request
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        filename:
                          type: string
                          description: Name of the translation file. Should be in the format of <locale>.json or <namespace>.<locale>.json.
                          example: "en.json"
                        locale:
                          type: string
                          description: Locale code for the translation file. This would be matched with user locale code to fetch translation.
                          example: "en"
                        locale_name:
                          type: string
                          description: Human-readable name of the locale
                          example: "English"
                        namespace:
                          type: string
                          nullable: true
                          description: Namespace for the translation file, if any. Namespace can be used to group translations by feature or module.
                          example: task
                        action:
                          type: string
                          description: action done in the version compared to last commit.
                          enum: ["added", "updated", "deleted", "unchanged"]
                          example: "added"
                        updated_at:
                          type: string
                          format: date-time
                          description: When the translation file was last updated
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - filename: "en.json"
                    locale: "en"
                    locale_name: "English"
                    namespace: null
                    action: "unchanged"
                    updated_at: "2025-10-30T12:23:50.380614Z"
                  - filename: "fr.json"
                    locale: "fr"
                    locale_name: "French"
                    namespace: null
                    action: "added"
                    updated_at: "2025-10-28T07:59:43.397124Z"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Version or workspace not found


  /v1/{workspace}/translation/commit/:
    patch:
      summary: Commit Translation
      description: Commit all files changes to make them live.
      operationId: commit-translation
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Commit Translation
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v1/{workspace}/translation/commit/" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (staging, production, etc.)
        - in: query
          name: commit_message
          required: false
          schema:
            type: string
          description: Commit message describing the changes
      responses:
        '202':
          description: Translations committed successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of translation files
                      limit:
                        type: integer
                        description: Maximum number of results per page
                      offset:
                        type: integer
                        description: Number of results to skip in case offset is passed in the request
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        filename:
                          type: string
                          description: Name of the translation file. Should be in the format of <locale>.json or <namespace>.<locale>.json.
                          example: "en.json"
                        locale:
                          type: string
                          description: Locale code for the translation file. This would be matched with user locale code to fetch translation.
                          example: "en"
                        locale_name:
                          type: string
                          description: Human-readable name of the locale
                          example: "English"
                        namespace:
                          type: string
                          nullable: true
                          description: Namespace for the translation file, if any. Namespace can be used to group translations by feature or module.
                          example: task
                        action:
                          type: string
                          description: action done in the version compared to last commit.
                          enum: ["added", "updated", "deleted", "unchanged"]
                          example: "added"
                        updated_at:
                          type: string
                          format: date-time
                          description: When the translation file was last updated
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - filename: "en.json"
                    locale: "en"
                    locale_name: "English"
                    namespace: null
                    action: "unchanged"
                    updated_at: "2025-10-30T12:23:50.380614Z"
                  - filename: "fr.json"
                    locale: "fr"
                    locale_name: "French"
                    namespace: null
                    action: "added"
                    updated_at: "2025-10-28T07:59:43.397124Z"
        '401':
          $ref: '#/components/responses/AuthenticationError'
          description: AuthenticationFailed - Invalid service token.
        '404':
          $ref: '#/components/responses/NotFoundError'
          description: Workspace not found

  # ===== Template Management API v2 =====

  /v2/{workspace}/template/:
    get:
      summary: List Templates
      description: Retrieve a paginated list of templates in a workspace. Returns template metadata including name, slug, status, enabled channels, and linked workflows.
      operationId: list-templates-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Templates
          source: |
            curl -X GET "https://management-api.suprsend.com/v2/{workspace}/template/?mode=live" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug (e.g., `staging`, `production`).
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Return draft or live version of templates.
        - in: query
          name: limit
          schema:
            type: integer
            default: 20
          description: Number of results per page.
        - in: query
          name: offset
          schema:
            type: integer
            default: 0
          description: Offset for pagination.
        - in: query
          name: q
          schema:
            type: string
          description: Search by template name or slug.
      responses:
        '200':
          description: Successfully retrieved list of templates
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                        description: Total number of templates matching the query
                        example: 22
                      limit:
                        type: integer
                        example: 10
                      offset:
                        type: integer
                        example: 0
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        $schema:
                          type: string
                          description: Schema URL for template validation
                          example: "https://schema.suprsend.com/template/v2/schema.json"
                        name:
                          type: string
                          example: "Order Confirmation Email"
                        slug:
                          type: string
                          example: "order-confirmation-email"
                        description:
                          type: string
                          nullable: true
                        tags:
                          type: array
                          items:
                            type: string
                        enabled_channels:
                          type: array
                          items:
                            type: string
                          example: ["email", "inbox"]
                        status:
                          type: string
                          enum: ["draft", "active"]
                          example: "active"
                        version_no:
                          type: integer
                          nullable: true
                        hash:
                          type: string
                        commit_message:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                          format: date-time
                        updated_at:
                          type: string
                          format: date-time
                        active_at:
                          type: string
                          format: date-time
                          nullable: true
                        last_triggered_at:
                          type: string
                          format: date-time
                          nullable: true
                          description: Timestamp of the last workflow run that used this template
                        updated_by:
                          type: object
                          properties:
                            name:
                              type: string
                            email:
                              type: string
                          description: User who last updated the template
                        channels:
                          type: array
                          items:
                            type: object
                            properties:
                              channel:
                                type: string
                              is_active:
                                type: boolean
                              variants_count:
                                type: integer
              example:
                meta:
                  count: 22
                  limit: 10
                  offset: 0
                results:
                  - $schema: "https://schema.suprsend.com/template/v2/schema.json"
                    slug: "order-confirmation-email"
                    created_at: "2026-04-07T10:39:28.502737Z"
                    last_triggered_at: "2026-04-07T16:45:34.549989Z"
                    name: "Order Confirmation Email"
                    description: "Email template for order confirmation notifications"
                    tags: []
                    enabled_channels: ["email"]
                    status: "active"
                    version_no: 4
                    hash: "637edaabc624d09db3793829ea872a3516ed0362ce79ee3875607fc7317381b9"
                    commit_message: null
                    active_at: "2026-04-07T16:42:13.821446Z"
                    updated_at: "2026-04-07T16:42:13.827644Z"
                    updated_by:
                      name: "Jane Smith"
                      email: "jane.smith@example.com"
                    channels:
                      - channel: "email"
                        is_active: true
                        variants_count: 1
                  - $schema: "https://schema.suprsend.com/template/v2/schema.json"
                    slug: "payment-confirmation"
                    created_at: "2026-04-07T07:05:13.747248Z"
                    last_triggered_at: null
                    name: "Payment Confirmation"
                    description: "Payment confirmation notification with order details"
                    tags: []
                    enabled_channels: ["email", "inbox"]
                    status: "active"
                    version_no: 2
                    hash: "ea6007ab4cffac8f110e15145eedbd40b5897fcc880717411416b9cdb64b170e"
                    commit_message: null
                    active_at: "2026-04-07T07:27:53.708887Z"
                    updated_at: "2026-04-07T07:27:53.715438Z"
                    updated_by:
                      name: "Alex Johnson"
                      email: "alex.johnson@example.com"
                    channels:
                      - channel: "email"
                        is_active: true
                        variants_count: 1
                      - channel: "inbox"
                        is_active: true
                        variants_count: 1
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /v2/{workspace}/template/{template_slug}/:
    get:
      summary: Get Template Detail
      description: Retrieve detailed information about a specific template including its metadata, enabled channels, and version info.
      operationId: get-template-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Template
          source: |
            curl -X GET "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/?mode=live" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug.
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
          description: Unique template slug.
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
          description: Return draft or live version.
      responses:
        '200':
          description: Template details retrieved successfully
          content:
            application/json:
              schema:
                type: object
              example:
                $schema: "https://schema.suprsend.com/template/v2/schema.json"
                slug: "order-confirmed"
                created_at: "2026-04-01T05:57:21.081312Z"
                last_triggered_at: null
                name: "Order Confirmed"
                description: null
                tags: []
                enabled_channels: ["email"]
                status: "active"
                version_no: 1
                hash: "16abf987215a02b655d5ef6a8f7f8cc150ffb03fd83b6c235d6c4cc2070ec170"
                commit_message: null
                active_at: "2026-04-01T09:22:02.382889Z"
                updated_at: "2026-04-01T09:22:02.386223Z"
                updated_by:
                  name: "Sam Wilson"
                  email: "sam.wilson@example.com"
                channels:
                  - channel: "email"
                    is_active: true
                    variants_count: 1
        '404':
          description: Template not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                  error_code:
                    type: string
                  type:
                    type: string
                  message:
                    type: string
                  detail:
                    type: string
              example:
                code: 404
                error_code: "not_found"
                type: "NotFound"
                message: "template (slug: 'order-confirmed') not found"
                detail: "template (slug: 'order-confirmed') not found"
        '401':
          $ref: '#/components/responses/AuthenticationError'
    post:
      summary: Create or Update Template
      description: |
        Create a new template or update an existing one. If the template slug already exists, the template metadata is updated. Changes are saved to the draft version.
      operationId: upsert-template-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Upsert Template
          source: |
            curl -X POST "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "name": "Order Confirmed",
                "description": "Sent when an order is placed",
                "tags": ["transactional"],
                "enabled_channels": ["email", "sms"]
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug.
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
          description: Unique template slug. Used as the identifier for the template.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: Template display name.
                  example: "Order Confirmed"
                description:
                  type: string
                  description: Optional description for the template.
                  example: "Sent when an order is placed"
                tags:
                  type: array
                  items:
                    type: string
                  description: Tags for organising templates.
                  example: ["transactional"]
                enabled_channels:
                  type: array
                  items:
                    type: string
                    enum: ["email", "sms", "whatsapp", "inbox", "androidpush", "iospush", "webpush", "slack", "ms_teams"]
                  description: Channels to enable for this template.
                  example: ["email", "sms"]
      responses:
        '200':
          description: Template created or updated successfully
          content:
            application/json:
              schema:
                type: object
              example:
                $schema: "https://schema.suprsend.com/template/v2/schema.json"
                slug: "welcome-onboarding"
                created_at: "2026-04-01T05:57:21.081312Z"
                last_triggered_at: null
                name: "Welcome Onboarding"
                description: "Welcome email for new users"
                tags: ["onboarding", "welcome"]
                enabled_channels: ["email", "slack"]
                status: "draft"
                version_no: null
                hash: "74335de96f6ddc077b90310ff746a8f8cd64852acbbe260c626be54ff28bed0d"
                commit_message: null
                active_at: null
                updated_at: "2026-04-08T09:24:38.918548Z"
                updated_by:
                  name: "API Service"
                  email: "service-token@api.example.com"
                channels:
                  - channel: "email"
                    is_active: false
                    variants_count: 1
                  - channel: "slack"
                    is_active: false
                    variants_count: 1
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /v2/{workspace}/template/{template_slug}/variant/:
    get:
      summary: List All Variants
      description: Retrieve all variants across all channels for a template. Returns variant metadata, conditions, and content.
      operationId: list-all-variants-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List All Variants
          source: |
            curl -X GET "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/variant/" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug.
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
          description: Template slug.
      responses:
        '200':
          description: Successfully retrieved variants
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                      limit:
                        type: integer
                      offset:
                        type: integer
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/TemplateVariant'
              example:
                meta:
                  count: 4
                  limit: 10
                  offset: 0
                results:
                  - $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                    channel: "email"
                    id: "default"
                    tenant_id: null
                    locale: "en"
                    conditions: []
                    hash: "dd176370a4b99c735e30f70bc98c61983671072c40db70750c3ada9e5edcabc1"
                    needs_vendor_approval: false
                    sysgen_template_name: null
                    approval_status: "auto_approved"
                    discard_comment: null
                    approval_at: "2026-04-07T10:39:28.502737Z"
                    has_error: false
                    seq_no: 1
                    action: null
                    created_at: "2026-04-07T10:39:28.510000Z"
                  - $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                    channel: "email"
                    id: "spanish"
                    tenant_id: null
                    locale: "es"
                    conditions: []
                    hash: "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
                    needs_vendor_approval: false
                    sysgen_template_name: null
                    approval_status: "auto_approved"
                    discard_comment: null
                    approval_at: "2026-04-07T11:00:00.000000Z"
                    has_error: false
                    seq_no: 2
                    action: null
                    created_at: "2026-04-07T11:00:00.000000Z"
                  - $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                    channel: "sms"
                    id: "default"
                    tenant_id: null
                    locale: "en"
                    conditions: []
                    hash: "3d99f9fa848e1997f23ebf634cdf7db37ef36f05d3433b6c14727abf494c2c56"
                    needs_vendor_approval: true
                    sysgen_template_name: "order_shipped_en_v1"
                    approval_status: "approved"
                    discard_comment: null
                    approval_at: "2026-04-07T12:00:00.000000Z"
                    has_error: false
                    seq_no: 1
                    action: null
                    created_at: "2026-04-07T12:00:00.000000Z"
                  - $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                    channel: "inbox"
                    id: "default"
                    tenant_id: null
                    locale: "en"
                    conditions: []
                    hash: "e71a233fa3af63e04beb3df6da90e7e506eef159b2599c3b42f3518b1a589c20"
                    needs_vendor_approval: false
                    sysgen_template_name: null
                    approval_status: "auto_approved"
                    discard_comment: null
                    approval_at: "2026-04-07T10:45:00.000000Z"
                    has_error: false
                    seq_no: 1
                    action: null
                    created_at: "2026-04-07T10:45:00.000000Z"
        '404':
          $ref: '#/components/responses/NotFoundError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /v2/{workspace}/template/{template_slug}/channel/{channel}/variant/:
    get:
      summary: List Channel Variants
      description: Retrieve all variants for a specific channel within a template.
      operationId: list-channel-variants-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: List Channel Variants
          source: |
            curl -X GET "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/channel/{channel}/variant/" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
          description: Workspace slug.
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
          description: Template slug.
        - in: path
          name: channel
          required: true
          schema:
            type: string
            enum: ["email", "sms", "whatsapp", "inbox", "androidpush", "iospush", "webpush", "slack", "ms_teams"]
          description: Channel slug.
      responses:
        '200':
          description: Successfully retrieved channel variants
          content:
            application/json:
              schema:
                type: object
                properties:
                  meta:
                    type: object
                    properties:
                      count:
                        type: integer
                      limit:
                        type: integer
                      offset:
                        type: integer
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/TemplateVariant'
              example:
                meta:
                  count: 2
                  limit: 10
                  offset: 0
                results:
                  - $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                    channel: "email"
                    id: "default"
                    tenant_id: null
                    locale: "en"
                    conditions: []
                    hash: "dd176370a4b99c735e30f70bc98c61983671072c40db70750c3ada9e5edcabc1"
                    needs_vendor_approval: false
                    sysgen_template_name: null
                    approval_status: "auto_approved"
                    discard_comment: null
                    approval_at: "2026-04-07T10:39:28.502737Z"
                    has_error: false
                    seq_no: 1
                    action: null
                    created_at: "2026-04-07T10:39:28.510000Z"
                  - $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                    channel: "email"
                    id: "spanish"
                    tenant_id: null
                    locale: "es"
                    conditions: []
                    hash: "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
                    needs_vendor_approval: false
                    sysgen_template_name: null
                    approval_status: "auto_approved"
                    discard_comment: null
                    approval_at: "2026-04-07T11:00:00.000000Z"
                    has_error: false
                    seq_no: 2
                    action: null
                    created_at: "2026-04-07T11:00:00.000000Z"
        '404':
          $ref: '#/components/responses/NotFoundError'
        '401':
          $ref: '#/components/responses/AuthenticationError'

  /v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/:
    get:
      summary: Get Variant Detail
      description: Retrieve detailed information about a specific variant including its content, conditions, and vendor approval status.
      operationId: get-variant-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Variant
          source: |
            curl -X GET "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
        - in: path
          name: channel
          required: true
          schema:
            type: string
            enum: ["email", "sms", "whatsapp", "inbox", "androidpush", "iospush", "webpush", "slack", "ms_teams"]
        - in: path
          name: variant_id
          required: true
          schema:
            type: string
          description: Variant identifier.
      responses:
        '200':
          description: Variant details retrieved. Includes full `content` and `vendor_approvals` objects.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateVariant'
              example:
                $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                channel: "email"
                id: "default"
                tenant_id: null
                locale: "en"
                conditions: []
                hash: "dd176370a4b99c735e30f70bc98c61983671072c40db70750c3ada9e5edcabc1"
                needs_vendor_approval: false
                sysgen_template_name: null
                approval_status: "auto_approved"
                discard_comment: null
                approval_at: "2026-04-07T10:39:28.502737Z"
                content:
                  $schema: "https://schema.suprsend.com/template/v2/channel/email_schema.json"
                  templating_language: "handlebars"
                  from_name: "Acme Store"
                  from_address: "noreply@acme-store.com"
                  extra_to: ""
                  cc: ""
                  bcc: ""
                  reply_to: ""
                  subject: "Order Confirmed - #{{order.number}}"
                  body:
                    type: "raw"
                    raw:
                      html: "<html><body><h1>Order Confirmed!</h1><p>Hi {{customer.name}}, your order #{{order.number}} has been confirmed.</p><p>Total: {{order.total}}</p></body></html>"
                      text: "Hi {{customer.name}}, your order #{{order.number}} has been confirmed. Total: {{order.total}}"
                    designer:
                      html: "..."
                      text: "..."
                      design_json: {}
                      display_conditions: []
                    preheader: "Your order #{{order.number}} is confirmed"
                    plain_text: null
                    email_markup: ""
                errors: {}
                vendor_approvals: []
                has_error: false
                seq_no: 1
                action: null
                created_at: "2026-04-07T10:39:28.510000Z"
        '404':
          $ref: '#/components/responses/NotFoundError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
    post:
      summary: Create or Update Variant
      description: |
        Create a new variant or update an existing one for a specific channel. Pass the variant content, conditions, locale, and optionally vendor approval details.

        The `content` JSON structure is channel-specific. Refer to the [variant content schema](https://schema.suprsend.com/template/v2/variant_schema.json) for each channel's structure.
      operationId: upsert-variant-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Upsert Variant
          source: |
            curl -X POST "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "locale": "en",
                "tenant_id": null,
                "conditions": [],
                "content": { ... }
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
        - in: path
          name: channel
          required: true
          schema:
            type: string
            enum: ["email", "sms", "whatsapp", "inbox", "androidpush", "iospush", "webpush", "slack", "ms_teams"]
        - in: path
          name: variant_id
          required: true
          schema:
            type: string
          description: Variant identifier. If a variant with this ID doesn't exist, a new one is created.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - locale
                - content
              properties:
                locale:
                  type: string
                  description: Locale code for the variant (e.g., `en`, `es`, `fr`).
                  example: "en"
                tenant_id:
                  type: string
                  nullable: true
                  description: Tenant ID this variant is scoped to. `null` for the default variant.
                conditions:
                  type: array
                  description: "Conditions for variant selection. Structure follows the [expression format](https://schema.suprsend.com/template/v2/variant_schema.json)."
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        enum: ["expression_v1"]
                      expression_v1:
                        type: object
                        properties:
                          op:
                            type: string
                            enum: ["AND"]
                          args:
                            type: array
                            items:
                              type: object
                              properties:
                                op:
                                  type: string
                                  enum: ["=="]
                                variable_ns:
                                  type: string
                                variable:
                                  type: string
                                value:
                                  type: string
                content:
                  type: object
                  description: "Channel-specific content. See [variant content schema](https://schema.suprsend.com/template/v2/variant_schema.json) for the structure of each channel."
                needs_vendor_approval:
                  type: boolean
                  description: "*(SMS only)* Whether this variant requires vendor (DLT) approval."
                seq_no:
                  type: integer
                  description: Ordering of the variant within the same channel + tenant + locale combination.
                vendor_approvals:
                  type: array
                  description: "Vendor approval entries for WhatsApp/SMS variants. See [approval schema](https://schema.suprsend.com/template/v2/variant_schema.json)."
                  items:
                    type: object
      responses:
        '200':
          description: Variant created or updated successfully. Returns the full variant including rendered content.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateVariant'
              example:
                $schema: "https://schema.suprsend.com/template/v2/variant_schema.json"
                channel: "email"
                id: "default"
                tenant_id: null
                locale: "en"
                conditions: []
                hash: "97f031b56ba642d137758652ce21dda6962ecee81d544fcf245661898107bcb9"
                needs_vendor_approval: false
                sysgen_template_name: null
                approval_status: "auto_approved"
                discard_comment: null
                approval_at: "2026-04-07T10:39:28.502737Z"
                content:
                  $schema: "https://schema.suprsend.com/template/v2/channel/email_schema.json"
                  templating_language: "handlebars"
                  from_name: "Acme Store"
                  from_address: "noreply@acme-store.com"
                  extra_to: ""
                  cc: ""
                  bcc: ""
                  reply_to: ""
                  subject: "Your order has been shipped - #{{order.number}}"
                  body:
                    type: "raw"
                    raw:
                      html: "<html><body><h1>Order Shipped!</h1><p>Hi {{customer.name}},</p><p>Your order <strong>#{{order.number}}</strong> has been shipped and is on its way.</p><p>Expected delivery: {{order.delivery_date}}</p><p><a href=\"{{{order.tracking_url}}}\">Track your order</a></p></body></html>"
                      text: "Hi {{customer.name}}, Your order #{{order.number}} has been shipped. Expected delivery: {{order.delivery_date}}. Track: {{{order.tracking_url}}}"
                    designer:
                      html: "..."
                      text: "..."
                      design_json: {}
                      merge_tags: []
                      display_conditions: []
                    preheader: "Your order #{{order.number}} is on its way"
                    plain_text: null
                    email_markup: ""
                errors: {}
                vendor_approvals: []
                has_error: false
                seq_no: 1
                action: null
                created_at: "2026-04-07T10:39:28.510000Z"
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v2/{workspace}/template/{template_slug}/mock_data/:
    get:
      summary: Get Mock Data
      description: Retrieve the mock data (input payload, recipient, tenant, actor settings) for a template. Used for previewing and testing.
      operationId: get-mock-data-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Get Mock Data
          source: |
            curl -X GET "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/mock_data/?mode=draft" \
              --header 'Authorization: ServiceToken <token>'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
        - in: query
          name: mode
          schema:
            type: string
            enum: ["draft", "live"]
            default: draft
      responses:
        '200':
          description: Mock data retrieved. Returns both the raw `data` (what the user configured) and the `transformed_data` (resolved values including tenant, recipient, actor properties, and batched events).
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    description: The raw mock data configuration set by the user.
                    properties:
                      payload:
                        type: object
                      tenant_id:
                        type: string
                        nullable: true
                      is_batch:
                        type: boolean
                      batch_count:
                        type: integer
                      recipient_sub_type:
                        type: string
                        enum: ["user", "object"]
                      recipient_object:
                        type: object
                        nullable: true
                      recipient_distinct_id:
                        type: string
                        nullable: true
                      actor_sub_type:
                        type: string
                        enum: ["user", "object"]
                      actor_object:
                        type: object
                        nullable: true
                      actor_distinct_id:
                        type: string
                        nullable: true
                  transformed_data:
                    type: object
                    description: Resolved data used for rendering previews - includes tenant branding, recipient/actor profiles, batched events, and preference URLs.
              example:
                data:
                  payload:
                    order_id: "ORD-8821"
                    order_total: "$149.99"
                    delivery_date: "2026-04-10"
                    tracking_url: "https://yourapp.com/track/ORD-8821"
                  tenant_id: "tenant_abc"
                  is_batch: false
                  batch_count: 2
                  recipient_sub_type: "user"
                  recipient_object: null
                  recipient_distinct_id: "user_12345"
                  actor_sub_type: "user"
                  actor_object: null
                  actor_distinct_id: null
                transformed_data:
                  order_id: "ORD-8821"
                  order_total: "$149.99"
                  delivery_date: "2026-04-10"
                  tracking_url: "https://yourapp.com/track/ORD-8821"
                  $batch_key: "evaluated batch_key"
                  $batched_events:
                    - order_id: "ORD-8821"
                      order_total: "$149.99"
                    - order_id: "ORD-8821"
                      order_total: "$149.99"
                  $batched_events_count: 2
                  $tenant:
                    id: "tenant_abc"
                    name: "Acme Inc."
                    logo: "https://cdn.acme.com/logo.png"
                    primary_color: "#1a73e8"
                    secondary_color: "#34a853"
                    tertiary_color: "#ffffff"
                    embedded_preference_url: "https://preferences.example.com/embed"
                    hosted_preference_domain: "preferences.example.com"
                    blocked_channels: null
                    social_links:
                      website: "https://www.example.com"
                      linkedin: "https://linkedin.com/company/example"
                      twitter: ""
                    properties: {}
                    timezone: "America/New_York"
                  $user:
                    name: "Jamie Rivera"
                    email: "jamie.rivera@example.com"
                  $recipient:
                    name: "Jamie Rivera"
                    email: "jamie.rivera@example.com"
                  $actor: {}
                  $embedded_preference_url: "https://preferences.example.com/embed"
                  $hosted_preference_url: "https://preferences.example.com/?key=xxxxxxxxxxxxxxx"
        '404':
          $ref: '#/components/responses/NotFoundError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
    patch:
      summary: Update Mock Data
      description: Update the mock data for a template. Sets the input payload, recipient, tenant, actor, and batching configuration used for previews and testing.
      operationId: update-mock-data-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Update Mock Data
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/mock_data/" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "payload": {"order_id": "ORD-1234", "amount": "$99.99"},
                "tenant_id": "default",
                "is_batch": false,
                "recipient_sub_type": "user",
                "recipient_distinct_id": "user-123"
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                payload:
                  type: object
                  description: Input payload data with sample variable values.
                tenant_id:
                  type: string
                  description: Tenant ID for preview.
                  example: "default"
                is_batch:
                  type: boolean
                  description: Whether to simulate batched/digest data.
                  default: false
                batch_count:
                  type: integer
                  description: Number of batched events to simulate (only relevant when `is_batch` is true).
                  example: 2
                recipient_sub_type:
                  type: string
                  enum: ["user", "object"]
                  description: Type of recipient.
                  example: "user"
                recipient_distinct_id:
                  type: string
                  description: Distinct ID of the test recipient (when `recipient_sub_type` is `user`).
                  example: "user-123"
                recipient_object:
                  type: object
                  description: Object identifier (when `recipient_sub_type` is `object`).
                  properties:
                    object_type:
                      type: string
                    id:
                      type: string
                actor_sub_type:
                  type: string
                  enum: ["user", "object"]
                  description: Type of actor.
                actor_distinct_id:
                  type: string
                  description: Distinct ID of the actor user.
                actor_object:
                  type: object
                  description: Object identifier for actor.
                  properties:
                    object_type:
                      type: string
                    id:
                      type: string
      responses:
        '200':
          description: Mock data updated successfully. Returns the same structure as Get Mock Data - both `data` (raw config) and `transformed_data` (resolved values).
          content:
            application/json:
              schema:
                type: object
              example:
                data:
                  payload:
                    user:
                      name: "Pat Morgan"
                    event:
                      status: "shipped"
                  tenant_id: "default"
                  is_batch: false
                  batch_count: 2
                  recipient_sub_type: "user"
                  recipient_object: null
                  recipient_distinct_id: "user_12345"
                  actor_sub_type: "user"
                  actor_object: null
                  actor_distinct_id: "actor_67890"
                transformed_data:
                  user:
                    name: "Pat Morgan"
                  event:
                    status: "shipped"
                  $batch_key: "evaluated batch_key"
                  $batched_events:
                    - user:
                        name: "Pat Morgan"
                      event:
                        status: "shipped"
                    - user:
                        name: "Pat Morgan"
                      event:
                        status: "shipped"
                  $batched_events_count: 2
                  $tenant:
                    id: "default"
                    name: "My Company"
                    logo: "https://cdn.example.com/logo.png"
                    primary_color: "#2E70E8"
                    secondary_color: "#63A3F7"
                    tertiary_color: "#FFFFFF"
                    embedded_preference_url: "https://preferences.example.com/embed"
                    hosted_preference_domain: "preferences.example.com"
                    blocked_channels: null
                    social_links:
                      website: "https://www.example.com"
                      linkedin: "https://linkedin.com/company/example"
                    properties: {}
                    timezone: null
                  $user:
                    name: "Jamie Rivera"
                    email: "jamie.rivera@example.com"
                    distinct_id: "user_12345"
                  $recipient:
                    name: "Jamie Rivera"
                    email: "jamie.rivera@example.com"
                    distinct_id: "user_12345"
                  $actor:
                    name: "Taylor Chen"
                    email: "taylor.chen@example.com"
                    distinct_id: "actor_67890"
                  $embedded_preference_url: "https://preferences.example.com/embed"
                  $hosted_preference_url: "https://preferences.example.com/?key=xxxxxxxxxxxxxxx"
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v2/{workspace}/template/{template_slug}/commit/:
    patch:
      summary: Commit Template
      description: |
        Commit the current draft version, making it live. All draft changes across all channels and variants are published as a new version.

        For WhatsApp and SMS (DLT) variants, committing moves them to **Approval Pending** state instead of going live immediately.
      operationId: commit-template-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Commit Template
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/commit/?commit_message=Updated%20copy" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{}'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
        - in: query
          name: commit_message
          schema:
            type: string
          description: Description of changes in this version.
      requestBody:
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: Template committed successfully. Returns the updated template detail.
          content:
            application/json:
              schema:
                type: object
              example:
                $schema: "https://schema.suprsend.com/template/v2/schema.json"
                slug: "order-confirmed"
                created_at: "2026-04-07T10:39:28.502737Z"
                last_triggered_at: null
                name: "Order Confirmed"
                description: "Sent when an order is placed"
                tags: ["transactional"]
                enabled_channels: ["email", "sms"]
                status: "active"
                version_no: 3
                hash: "637edaabc624d09db3793829ea872a3516ed0362ce79ee3875607fc7317381b9"
                commit_message: "Updated subject line for Q2 campaign"
                active_at: "2026-04-08T12:00:00.000000Z"
                updated_at: "2026-04-08T12:00:00.000000Z"
                updated_by:
                  name: "Dana Lee"
                  email: "dana.lee@example.com"
                channels:
                  - channel: "email"
                    is_active: true
                    variants_count: 2
                  - channel: "sms"
                    is_active: true
                    variants_count: 1
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/discard/:
    patch:
      summary: Discard Variant
      description: |
        Discard a variant that is in approval-pending state. Only applicable for WhatsApp and SMS channels that require vendor approval. The variant returns to draft state.
      operationId: discard-variant-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Discard Variant
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/discard/?mode=live" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{"comment": "Content needs revision"}'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
        - in: path
          name: channel
          required: true
          schema:
            type: string
            enum: ["whatsapp", "sms"]
        - in: path
          name: variant_id
          required: true
          schema:
            type: string
        - in: query
          name: mode
          schema:
            type: string
            enum: ["live"]
            default: live
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - comment
              properties:
                comment:
                  type: string
                  description: Reason for discarding the variant.
                  example: "Content needs revision before resubmission"
      responses:
        '200':
          description: Variant discarded successfully
          content:
            application/json:
              schema:
                type: object
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  /v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/vendor_approval/:
    patch:
      summary: Add or Update Vendor Approval
      description: |
        Add or update a vendor approval entry for a WhatsApp or SMS variant. Use this to record approval status from the vendor portal, including the vendor template ID and name.
      operationId: vendor-approval-v2
      servers:
        - url: https://management-api.suprsend.com
      security:
        - ServiceTokenAuth: []
      x-codeSamples:
        - lang: cURL
          label: Approve Variant
          source: |
            curl -X PATCH "https://management-api.suprsend.com/v2/{workspace}/template/{template_slug}/channel/{channel}/variant/{variant_id}/vendor_approval/?mode=live" \
              --header 'Authorization: ServiceToken <token>' \
              --header 'Content-Type: application/json' \
              --data '{
                "approval_status": "approved",
                "vendor_slug": "twilio-whatsapp",
                "vendor_uid": "waba_id-123221",
                "vendor_template_name": "tpl_v12",
                "vendor_template_id": "1232",
                "vendor_locale_code": "en",
                "vendor_template_category": "UTILITY"
              }'
      parameters:
        - in: path
          name: workspace
          required: true
          schema:
            type: string
        - in: path
          name: template_slug
          required: true
          schema:
            type: string
        - in: path
          name: channel
          required: true
          schema:
            type: string
            enum: ["whatsapp", "sms"]
        - in: path
          name: variant_id
          required: true
          schema:
            type: string
        - in: query
          name: mode
          schema:
            type: string
            enum: ["live"]
            default: live
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - approval_status
                - vendor_slug
                - vendor_uid
              properties:
                approval_status:
                  type: string
                  enum: ["pending", "sent_for_approval", "approved", "rejected"]
                  description: Current approval status.
                  example: "approved"
                vendor_slug:
                  type: string
                  description: Slug of the vendor (e.g., `twilio-whatsapp`, `gupshup-whatsapp`, `msg91-sms`).
                  example: "twilio-whatsapp"
                vendor_uid:
                  type: string
                  description: Unique vendor identifier (e.g., WABA ID for WhatsApp).
                  example: "waba_id-123221"
                vendor_template_name:
                  type: string
                  description: "*(Required if approved)* Template name as registered at the vendor portal."
                  example: "tpl_v12"
                vendor_template_id:
                  type: string
                  description: "*(Required if approved)* Template ID from the vendor portal."
                  example: "1232"
                vendor_locale_code:
                  type: string
                  description: "*(Optional)* Locale code at the vendor end."
                  example: "en"
                vendor_template_category:
                  type: string
                  description: "*(Optional)* Template category at the vendor end."
                  enum: ["UTILITY", "MARKETING", "AUTHENTICATION"]
                  example: "UTILITY"
                provider_template_id:
                  type: string
                  description: "*(Optional, SMS only for msg91-sms)* Provider-level template ID."
                comment:
                  type: string
                  description: "*(Required if rejected)* Reason for rejection."
      responses:
        '200':
          description: Vendor approval entry updated
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Validation error - one or more variants have issues
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: integer
                  error_code:
                    type: string
                  type:
                    type: string
                  message:
                    type: string
                  detail:
                    type: array
                    items:
                      type: string
              example:
                code: 400
                error_code: "error"
                type: "ValidationError"
                message: "[\"one of more variants about to be committed have issues.\\n[1] email:default errors: {'body.raw.html': ['missing']}\\n[2] slack:default errors: {'body_text': ['missing']}\"]"
                detail:
                  - "one of more variants about to be committed have issues.\n[1] email:default errors: {'body.raw.html': ['missing']}\n[2] slack:default errors: {'body_text': ['missing']}"
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '404':
          $ref: '#/components/responses/NotFoundError'

  # ===== Template Variant Schema =====

x-readme:
  headers: []
  explorer-enabled: true
  proxy-enabled: true
x-readme-fauxas: true