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 `. Get API Key from SuprSend dashboard Developers -> API Keys section." ServiceTokenAuth: type: apiKey in: header name: ServiceToken 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 `, where 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" - 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.. 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.`. 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 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.`. 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: string identifier of the tenant/tenant this workflow is associated with. Used to trigger [multi-tenant](https://docs.suprsend.com/docs/tenant-workflows) notifications $idempotency_key: type: string description: Idempotency_key (valid for 24hrs) DigestNode: 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"] description: "Type of schedule. Determines if the schedule is static or dynamic. \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`." 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: 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: 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: 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: 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: 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)" - "$brand": "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: 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), \"$brand\" (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: ["", "$brand", "$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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: "" 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 - ` and `$USER_EXITED_LIST - ` 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) 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.. 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. 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. 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" 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' 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: unique identifier of the tenant that you want to create / update schema: type: string required: true requestBody: content: application/json: schema: type: object required: - tenant_name properties: tenant_name: type: string description: Name of the tenant. You can add company / organization name here default: Awesome Tenant logo: type: string description: URL of the tenant logo default: https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend-only-logo_c8aa27faef118418e8c5bd7b31a1cafc74e09200.png primary_color: type: string description: Primary color of the tenant - used for designing tenant template. If you don't provide any of the colors for the tenant, SuprSend will assume you want to use the default values, so color settings will automatically be set to the color settings of default tenant. default: '#ff0000' secondary_color: type: string description: Secondary color of the tenant - not used for designing the default templates. You can however add this property and use it in your templates example: '#00ff00' tertiary_color: type: string description: Tertiary color of the tenant - not used for designing the default templates. You can however add this property and use it in your templates example: '#0000ff' preference_page_url: type: string description: Link of the preference page inside the tenant product social_links: type: object description: urls of social media accounts of the tenant. If you really want to remove any social link, you must set its value="" (instead of null) properties: website: type: string description: link of tenant website. While updating a social link, if you want to remove the link, you must the value="" (instead of null) default: https://suprsend.com facebook: type: string description: tenant facebook page link LinkedIn: type: string description: tenant linkedin page link x: type: string description: tenant x(previously twitter) page link instagram: type: string description: tenant instagram page link medium: type: string description: tenant medium page link discord: type: string description: tenant discord page link telegram: type: string description: tenant telegram page link youtube: type: string description: tenant youtube page link tiktok: type: string description: tenant tiktok page link properties: type: object description: Custom properties associated with the tenant. Update operation on properties works like upsert on 1st-level keys (i.e., if top-level key doesn't already exist, then it will be added, otherwise its value will be replaced by the new value. All other key-value pairs will remain unchanged). additionalProperties: type: string responses: '201': description: '201 - Created' content: application/json: examples: Result: value: { "tenant_id": "brand_id", "tenant_name": "Awesome Tenant", "logo": "https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend-only-logo_c8aa27faef118418e8c5bd7b31a1cafc74e09200.png", "timezone": null, "blocked_channels": [ "email" ], "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": "https://www.company.com", "LinkedIn": "", "x": "", "instagram": "", "medium": "", "discord": "", "telegram": "", "youtube": "" }, "properties": { "k1": "v1", "address": "my company address" }, "updated_at": "2025-04-06T21:01:35.359787Z" } schema: type: object description: Updated Object Payload is returned in response. JSON structure similar to request payload. '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 data security: - BearerAuth: [] description: API to fetch tenant settings (logo, colors, links, preference) corresponding to a tenant_id. To create or update tenant data, use the [Create/Update Tenant](#create-update-tenants) endpoint. To create or update tenant data, use the [Create/Update Tenant](#create-update-tenants) endpoint. 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: '200' content: application/json: examples: Result: value: { "tenant_id": "_tenant_id_", "tenant_name": "Awesome Tenant", "logo": "https://ik.imagekit.io/l0quatz6utm/suprsend/staging/media/suprsend-only-logo_c8aa27faef118418e8c5bd7b31a1cafc74e09200.png", "timezone": null, "blocked_channels": [ "email" ], "embedded_preference_url": "https://app.suprsend.com/en/user-settings/notifications", "hosted_preference_domain": "preferences.suprsend.com", "primary_color": "#ff0000", "secondary_color": "#0000ff", "tertiary_color": "#00ffff", "social_links": { "website": "https://suprsend.com", "facebook": "https://www.company.com", "linkedin": "", "x": "", "instagram": "", "medium": "", "discord": "", "telegram": "", "youtube": "", "tiktok": "" }, "properties": { "k1": "v1", "address": "my company address" }, "updated_at": "2025-04-06T21:01:35.359787Z" } schema: type: object description: Updated Object Payload is returned in response. JSON structure similar to [request payload](/reference/create-update-tenants). '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: API to permanently delete tenant and it's associated settings. operationId: delete-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: '204': description: '204 - No Content' '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/: get: summary: Get Tenant List 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 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 responses: '200': description: '200 - OK' content: application/json: examples: Result: value: { "meta": { "count": 28, "limit": 20, "offset": 0 }, "results": [ { "tenant_id": "random_id", "tenant_name": "Awesome Tenant", "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": "2025-04-06T20: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 same as tenant upsert response. items: type: object properties: tenant_id: type: string description: Unique identifier of the tenant. example: random_id tenant_name: type: string description: Name of the tenant. example: Awesome Tenant logo: type: string format: uri description: URL of the tenant logo. example: https://logo.png timezone: type: string nullable: true description: timezone of the tenant. Used as fallback if user's timezone is not 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 that are blocked for the tenant. embedded_preference_url: type: string format: uri example: https://app.suprsend.com/en/user-settings/notifications description: url of the preference page inside the tenant product. hosted_preference_domain: type: string example: preferences.suprsend.com description: domain of the hosted preference page. primary_color: type: string description: Primary color of the tenant used for template design. example: "#ff0000" secondary_color: type: string nullable: true description: Secondary color of the tenant. example: "#ff0000" tertiary_color: type: string nullable: true description: Tertiary color of the tenant. example: "#ff0000" social_links: type: object description: Social media links associated with the tenant. 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 properties associated with the tenant. additionalProperties: true example: {"address":"my company address"} updated_at: type: string format: date-time description: Timestamp when the tenant was last updated. example: "2025-04-06T20: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 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. 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 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_ responses: '201': description: '201' content: application/json: examples: Result: 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 } 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", "query_based"] 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 status: type: string description: Current status of the list (active or draft). example: "active" track_user_entry: type: boolean description: Event `$USER_ENTERED_LIST - ` 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 - ` 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. '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 /{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: type: string example: Newsletter category: type: string example: newsletter description: 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 '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 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. operationId: get-list parameters: - name: list_id in: path description: Unique string identifier of the list. required: true schema: type: string default: _list_id_ responses: '200': description: '200' content: application/json: examples: Result: 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 } 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", "query_based"] 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 status: type: string description: Current status of the list (active or draft). example: "active" track_user_entry: type: boolean description: Event `$USER_ENTERED_LIST - ` 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 - ` 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. '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. 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 responses: '202': description: '202' content: application/json: examples: Result: value: { "name":"Status Update Alert", "category":"status-update-alert", "description":"Send me updates when account status changes", "original_preference":"opt_in", "preference":"opt_in", "is_editable":true, "channels":[ { "channel":"email", "preference":"opt_in", "is_editable":true }, { "channel":"ms_teams", "preference":"opt_in", "is_editable":true }, { "channel":"slack", "preference":"opt_in", "is_editable":true } ] } schema: type: object properties: name: type: string example: Status Update Alert category: type: string example: status-update-alert description: type: string example: Send me updates when account status changes 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 '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 '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: true /v1/tenant/{tenant_id}/category/{category_slug}/: patch: summary: Update Tenant Default Preference security: - BearerAuth: [] description: API to update tenant default preferences for a specific notification category. operationId: update-brand-default-preference x-codeSamples: - lang: cURL label: Update Tenant Default Preference source: | curl -X PATCH "https://hub.suprsend.com/v1/tenant/brand_id/preference/status-update-alert/" \ --header 'Authorization: Bearer __YOUR_API_KEY__' \ --header 'Content-Type: application/json' \ --data '{ "preference": "opt_in", "visible_to_subscriber": true }' parameters: - name: tenant_id in: path description: unique identifier of the brand/tenant you want to update default preferences for 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: 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. enum: [opt_in, opt_out, cant_unsubscribe] 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 enum: [email, sms, whatsapp, androidpush, inbox, iospush, slack, webpush, ms_teams] 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] blocked_channels: type: array nullable: true description: Pass channels which are not applicable for the tenant. This setting will apply to all categories and user will not be able to opt-in to these channels for the tenant. items: type: string enum: [email, sms, whatsapp, androidpush, inbox, iospush, slack, webpush, ms_teams] responses: '202': description: '202' content: application/json: examples: Result: value: { "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": ['email', 'sms'], "visible_to_subscriber": true, "preference": "opt_in", "mandatory_channels": null, "opt_in_channels": null, "blocked_channels": null } schema: 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] '404': description: '404' 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}/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 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: not found", "detail": "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: 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: type: string enum: ["opt_in", "opt_out", "cant_unsubscribe"] default_mandatory_channels: type: array nullable: true items: type: string default_opt_in_channels: type: array nullable: true items: type: string enabled_for_tenant: type: boolean visible_to_subscriber: type: boolean preference: type: string nullable: true enum: ["opt_in", "opt_out", "cant_unsubscribe"] mandatory_channels: type: array nullable: true items: type: string opt_in_channels: type: array nullable: true items: type: string blocked_channels: type: array nullable: true items: type: string updated_at: type: string format: date-time nullable: 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/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: type: string enum: ["system", "transactional", "promotional"] default_preference: type: string enum: ["opt_in", "opt_out", "cant_unsubscribe"] default_mandatory_channels: type: array nullable: true items: type: string default_opt_in_channels: type: array nullable: true items: type: string enabled_for_tenant: type: boolean visible_to_subscriber: type: boolean preference: type: string nullable: true enum: ["opt_in", "opt_out", "cant_unsubscribe"] mandatory_channels: type: array nullable: true items: type: string opt_in_channels: type: array nullable: true items: type: string blocked_channels: type: array nullable: true items: type: string updated_at: type: string format: date-time nullable: 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/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: type: string enum: ["system", "transactional", "promotional"] default_preference: type: string enum: ["opt_in", "opt_out", "cant_unsubscribe"] default_mandatory_channels: type: array nullable: true items: type: string default_opt_in_channels: type: array nullable: true items: type: string enabled_for_tenant: type: boolean visible_to_subscriber: type: boolean preference: type: string nullable: true enum: ["opt_in", "opt_out", "cant_unsubscribe"] mandatory_channels: type: array nullable: true items: type: string opt_in_channels: type: array nullable: true items: type: string blocked_channels: type: array nullable: true items: type: string updated_at: type: string format: date-time nullable: true '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: 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 examples: Update Preference: value: { "preference": "opt_in" } 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": "opt_in", "mandatory_channels": null, "opt_in_channels": null, "blocked_channels": null, "updated_at": "2025-12-06T10:54:46.630096Z" } 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: type: string enum: ["system", "transactional", "promotional"] default_preference: type: string enum: ["opt_in", "opt_out", "cant_unsubscribe"] default_mandatory_channels: type: array nullable: true items: type: string default_opt_in_channels: type: array nullable: true items: type: string enabled_for_tenant: type: boolean visible_to_subscriber: type: boolean preference: type: string nullable: true enum: ["opt_in", "opt_out", "cant_unsubscribe"] mandatory_channels: type: array nullable: true items: type: string opt_in_channels: type: array nullable: true items: type: string blocked_channels: type: array nullable: true items: type: string updated_at: type: string format: date-time nullable: true '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] '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 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 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 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 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 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": "", "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. 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 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: type: string example: "Newsletter" category: type: string example: "newsletter" description: 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" 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 examples: Update Preferences: value: { "channel_preferences": [ { "channel": "email", "is_restricted": false } ], "categories": [ { "category": "_category_slug_", "preference": "opt_in", "opt_out_channels": [], "opt_in_channels": [] } ] } responses: '200': description: '200' content: application/json: examples: Result: value: { "sections": [ { "name": null, "slug": null, "subcategories": [ { "name": "Promotion de remboursement", "category": "refund-promotion", "description": "mises à jour", "original_preference": null, "preference": "opt_in", "is_editable": false, "channels": [ { "channel": "email", "preference": "opt_in", "is_editable": false }, { "channel": "inbox", "preference": "opt_in", "is_editable": false } ] } ] } ], "channel_preferences": [ { "channel": "email", "is_restricted": false }, { "channel": "inbox", "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 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 $: 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 $: 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 $: 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.. - 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.. properties: type: object description: properties defining the relation between object and its subscribers. Can be referenced as `recipient.subscription.` 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.` 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.` 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 responses: '202': description: '202' content: application/json: examples: Result: value: { "name":"Status Update Alert", "category":"status-update-alert", "description":"Send me updates when account status changes", "original_preference":"opt_in", "preference":"opt_in", "is_editable":true, "channels":[ { "channel":"email", "preference":"opt_out", "is_editable":true }, { "channel":"ms_teams", "preference":"opt_in", "is_editable":true }, { "channel":"slack", "preference":"opt_out", "is_editable":true } ] } schema: type: object properties: name: type: string description: preference category name example: "Status Update Alert" category: type: string description: unique preference category slug. You can get this by clicking on preference category name on Developers -> Preference categories page. example: "status-update-alert" description: type: string example: "Send me updates when account status changes" 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 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: false 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 '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: type: string example: Newsletter category: type: string example: newsletter description: type: string example: Send me updates on new product updates original_preference: 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 '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: type: string example: "Newsletter" category: type: string example: "newsletter" description: 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" 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 examples: Update Preferences: value: { "channel_preferences": [ { "channel": "email", "is_restricted": false } ] } responses: '200': description: '200' content: application/json: examples: Result: value: { "sections": [ { "name": null, "slug": null, "subcategories": [ { "name": "Promotion de remboursement", "category": "refund-promotion", "description": "mises à jour", "original_preference": null, "preference": "opt_in", "is_editable": false, "channels": [ { "channel": "inbox", "preference": "opt_in", "is_editable": false } ] } ] } ], "channel_preferences": [ { "channel": "inbox", "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": "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: type: string example: Newsletter category: type: string example: newsletter description: 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 '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 $: 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 $: 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 $: 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. operationId: list-users 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" } ] } 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.` 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/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. 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 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 channel_identity: sms: "+15555550100" category: "transactional" 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 ' \ --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 ' \ --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}/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 ' \ --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 ' \ --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 ' 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 ' \ --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 ' \ --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 ' \ --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 ' 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 ' 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 ' \ --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 ' \ --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 ' 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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 ' \ --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 example: "opt_in" default_mandatory_channels: type: array description: Channels that are mandatory for this category items: type: string example: ["email"] default_opt_in_channels: type: array nullable: true description: Opt-in channels set to have selective opt-in channels instead of all channels when channel preference is opt_in or cant_unsubscribe. items: type: string 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]+)*$ 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" - root_category: "promotional" sections: - name: "Product Updates" categories: - category: "newsletter" name: "Newsletter" default_preference: "opt_out" 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" } ] } ] }, { "root_category": "promotional", "sections": [ { "name": "Product Updates", "categories": [ { "category": "newsletter", "name": "Newsletter", "default_preference": "opt_out" } ] } ] } ] }' 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]+)*$ 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 items: type: object properties: name: type: string description: Name of the section example: "Account Updates" categories: type: array description: Array of categories within this section 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" default_preference: type: string description: Default preference setting for this category example: "opt_in" default_mandatory_channels: type: array description: Channels that are mandatory for this category items: type: string example: ["email"] default_opt_in_channels: type: array nullable: true description: Channels that are included in the default "On" state when default preference is opt_in items: type: string example: null status: type: string description: Current status of the preference category enum: [draft, active] example: "draft" version_no: type: integer description: Version number of the preference category 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 - 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 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 items: type: object properties: name: type: string description: Name of the section example: "Account Updates" categories: type: array description: Array of categories within this section 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" default_preference: type: string description: Default preference setting for this category example: "opt_in" status: type: string description: Current status of the preference category enum: [draft, active] example: "active" version_no: type: integer description: Version number of the preference category 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 - 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 - 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 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 ' 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 .json or ..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 ' \ --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 ' 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 ' 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 ' 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 .json or ..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 ' 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 .json or ..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 ' 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 .json or ..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 ' \ --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 ' 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 ' \ --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 ' 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 ' 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 ' 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: "

Order Confirmed!

Hi {{customer.name}}, your order #{{order.number}} has been confirmed.

Total: {{order.total}}

" 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 ' \ --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: "

Order Shipped!

Hi {{customer.name}},

Your order #{{order.number}} has been shipped and is on its way.

Expected delivery: {{order.delivery_date}}

Track your order

" 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 ' 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 $brand: brand_id: "tenant_abc" brand_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 ' \ --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 $brand: brand_id: "default" brand_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 ' \ --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 ' \ --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 ' \ --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