bento-n8n-sdk
Version:
n8n community node for Bento integration
1,252 lines • 135 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bento = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const buffer_1 = require("buffer");
const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
const INPUT_LIMITS = {
EMAIL: 254,
NAME: 50,
SUBJECT: 200,
CUSTOM_FIELD_KEY: 50,
CUSTOM_FIELD_VALUE: 500,
EVENT_NAME: 100,
EVENT_PROPERTY_KEY: 50,
EVENT_PROPERTY_VALUE: 500,
HTML_CONTENT: 50000,
TEXT_CONTENT: 50000,
USER_ID: 254,
IP_ADDRESS: 45,
VALIDATE_NAME: 100,
USER_AGENT: 512,
SEGMENT_ID: 100,
};
const DANGEROUS_HTML_PATTERNS = [
/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
/javascript:/gi,
/on\w+\s*=/gi,
/<iframe\b[^>]*>/gi,
/<object\b[^>]*>/gi,
/<embed\b[^>]*>/gi,
/<form\b[^>]*>/gi,
/<input\b[^>]*>/gi,
/<meta\b[^>]*>/gi,
/<link\b[^>]*>/gi,
/data:(?!image\/)/gi,
/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,
];
const SECURE_ERROR_MESSAGES = {
AUTHENTICATION_FAILED: 'Authentication failed. Please check your Bento API credentials.',
INVALID_REQUEST: 'Request validation failed. Please check your input parameters.',
API_ERROR: 'Bento API request failed. Please try again or contact support.',
NETWORK_ERROR: 'Network error occurred. Please check your connection and try again.',
VALIDATION_ERROR: 'Input validation failed. Please check your data format.',
RATE_LIMITED: 'Rate limit exceeded. Please wait before making more requests.',
SERVER_ERROR: 'Server error occurred. Please try again later.',
UNKNOWN_ERROR: 'An unexpected error occurred. Please contact support if the issue persists.',
};
const REQUEST_LIMITS = {
MAX_PAYLOAD_SIZE: 1024 * 1024,
DEFAULT_TIMEOUT: 30000,
MAX_RETRIES: 3,
RETRY_DELAY_BASE: 1000,
RATE_LIMIT_DELAY: 60000,
MAX_CONCURRENT_REQUESTS: 5,
};
const RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504];
const RETRYABLE_ERROR_CODES = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED'];
function isValidEmail(email) {
if (typeof email !== 'string' || email.trim() === '') {
return false;
}
const trimmedEmail = email.trim();
if (trimmedEmail.length > 254) {
return false;
}
if (!EMAIL_REGEX.test(trimmedEmail)) {
return false;
}
if (trimmedEmail.includes('..')) {
return false;
}
if (trimmedEmail.startsWith('.') || trimmedEmail.endsWith('.')) {
return false;
}
const [localPart, domainPart] = trimmedEmail.split('@');
if (localPart.length > 64) {
return false;
}
if (domainPart.length > 253) {
return false;
}
const domainParts = domainPart.split('.');
if (domainParts.length < 2) {
return false;
}
for (const part of domainParts) {
if (part.length === 0 || part.length > 63) {
return false;
}
if (part.startsWith('-') || part.endsWith('-')) {
return false;
}
}
return true;
}
function sanitizeEmail(email) {
if (typeof email !== 'string') {
return '';
}
return email.trim().toLowerCase();
}
function validateHtmlContent(html) {
if (typeof html !== 'string') {
return false;
}
for (const pattern of DANGEROUS_HTML_PATTERNS) {
const regex = new RegExp(pattern.source, pattern.flags);
if (regex.test(html)) {
return false;
}
}
return true;
}
function sanitizeHtmlContent(html) {
if (typeof html !== 'string') {
return '';
}
let sanitized = html.trim();
for (const pattern of DANGEROUS_HTML_PATTERNS) {
const regex = new RegExp(pattern.source, pattern.flags);
sanitized = sanitized.replace(regex, '');
}
sanitized = sanitized.replace(/javascript\s*:/gi, '');
sanitized = sanitized.replace(/vbscript\s*:/gi, '');
sanitized = sanitized.replace(/data\s*:/gi, '');
return sanitized;
}
function validateHtmlStructure(html) {
const issues = [];
if (typeof html !== 'string') {
issues.push('HTML content must be a string');
return { isValid: false, issues };
}
if (/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi.test(html)) {
issues.push('Script tags are not allowed');
}
if (/javascript:/gi.test(html)) {
issues.push('JavaScript URLs are not allowed');
}
if (/on\w+\s*=/gi.test(html)) {
issues.push('Event handlers (onclick, onload, etc.) are not allowed');
}
if (/<iframe\b[^>]*>/gi.test(html)) {
issues.push('Iframe tags are not allowed');
}
if (/<form\b[^>]*>/gi.test(html)) {
issues.push('Form tags are not allowed in email content');
}
if (/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi.test(html)) {
issues.push('Style tags are not recommended (use inline styles instead)');
}
const openTags = html.match(/<[^\/][^>]*>/g) || [];
const closeTags = html.match(/<\/[^>]*>/g) || [];
if (openTags.length !== closeTags.length) {
issues.push('HTML may contain unclosed tags');
}
return {
isValid: issues.length === 0,
issues
};
}
function validateInputLength(input, maxLength, fieldName, itemIndex) {
if (typeof input === 'string' && input.length > maxLength) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `${fieldName} exceeds maximum length of ${maxLength} characters (current: ${input.length})`, { itemIndex });
}
}
function createSecureErrorMessage(error, operation) {
if (error.statusCode) {
switch (error.statusCode) {
case 400:
return `${SECURE_ERROR_MESSAGES.INVALID_REQUEST} (Operation: ${operation})`;
case 401:
return SECURE_ERROR_MESSAGES.AUTHENTICATION_FAILED;
case 403:
return SECURE_ERROR_MESSAGES.AUTHENTICATION_FAILED;
case 404:
return `${SECURE_ERROR_MESSAGES.API_ERROR} Resource not found.`;
case 429:
return SECURE_ERROR_MESSAGES.RATE_LIMITED;
case 500:
case 502:
case 503:
case 504:
return SECURE_ERROR_MESSAGES.SERVER_ERROR;
default:
return SECURE_ERROR_MESSAGES.API_ERROR;
}
}
if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
return SECURE_ERROR_MESSAGES.NETWORK_ERROR;
}
if (error.message && error.message.includes('validation')) {
return SECURE_ERROR_MESSAGES.VALIDATION_ERROR;
}
return SECURE_ERROR_MESSAGES.UNKNOWN_ERROR;
}
function logSecureError(error, operation, context) {
var _a;
this.logger.error('Bento Node Error', {
operation,
itemIndex: context.itemIndex,
endpoint: context.endpoint,
statusCode: error.statusCode,
errorCode: error.code,
hasMessage: !!error.message,
messageLength: ((_a = error.message) === null || _a === void 0 ? void 0 : _a.length) || 0,
timestamp: new Date().toISOString(),
});
}
function validatePayloadSize(body) {
if (!body)
return true;
const payloadSize = JSON.stringify(body).length;
return payloadSize <= REQUEST_LIMITS.MAX_PAYLOAD_SIZE;
}
function calculateBackoffDelay(attempt, baseDelay = REQUEST_LIMITS.RETRY_DELAY_BASE) {
const exponentialDelay = baseDelay * Math.pow(2, attempt);
const jitter = Math.random() * 0.1 * exponentialDelay;
return Math.min(exponentialDelay + jitter, 30000);
}
function shouldRetryRequest(error, attempt) {
if (attempt >= REQUEST_LIMITS.MAX_RETRIES) {
return false;
}
if (error.statusCode && RETRYABLE_STATUS_CODES.includes(error.statusCode)) {
return true;
}
if (error.code && RETRYABLE_ERROR_CODES.includes(error.code)) {
return true;
}
return false;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const activeRequests = new Map();
const requestQueue = new Map();
async function acquireRequestSlot(nodeId) {
const currentRequests = activeRequests.get(nodeId) || 0;
if (currentRequests >= REQUEST_LIMITS.MAX_CONCURRENT_REQUESTS) {
const queue = requestQueue.get(nodeId) || [];
return new Promise((resolve) => {
queue.push(resolve);
requestQueue.set(nodeId, queue);
});
}
activeRequests.set(nodeId, currentRequests + 1);
}
function releaseRequestSlot(nodeId) {
const currentRequests = activeRequests.get(nodeId) || 0;
const newCount = Math.max(0, currentRequests - 1);
activeRequests.set(nodeId, newCount);
const queue = requestQueue.get(nodeId) || [];
if (queue.length > 0 && newCount < REQUEST_LIMITS.MAX_CONCURRENT_REQUESTS) {
const nextResolve = queue.shift();
if (nextResolve) {
requestQueue.set(nodeId, queue);
activeRequests.set(nodeId, newCount + 1);
nextResolve();
}
}
}
class Bento {
constructor() {
this.ai = true;
this.aiCategory = 'automation';
this.supportsStreaming = false;
this.inputType = 'json';
this.outputType = 'json';
this.description = {
displayName: 'Bento',
name: 'bento',
icon: 'file:bento.svg',
group: ['communication'],
version: 1,
subtitle: '={{$parameter["operation"]}}',
description: 'Native integration for Bento API actions',
defaults: {
name: 'Bento',
},
inputs: ["main"],
outputs: ["main"],
credentials: [
{
name: 'bentoApi',
required: true,
},
],
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Blacklist Check',
value: 'blacklistCheck',
description: 'Check an email against Bento\'s blacklist service',
action: 'Check email against blacklist',
},
{
name: 'Content Moderation',
value: 'contentModeration',
description: 'Send content to Bento\'s moderation service',
action: 'Moderate content',
},
{
name: 'Create Subscriber',
value: 'createSubscriber',
description: 'Add a new subscriber to your Bento audience with email and profile data',
action: 'Create a subscriber',
},
{
name: 'Gender Guess',
value: 'genderGuess',
description: 'Predict subscriber gender using Bento\'s experimental classifier',
action: 'Guess gender',
},
{
name: 'Geolocation Lookup',
value: 'geolocationLookup',
description: 'Look up location details for an IP address',
action: 'Look up geolocation',
},
{
name: 'Get Subscriber',
value: 'getSubscriber',
description: 'Retrieve detailed information about an existing subscriber by email',
action: 'Get a subscriber',
},
{
name: 'List Broadcasts',
value: 'listBroadcasts',
description: 'List Bento broadcasts with optional filters',
action: 'List broadcasts',
},
{
name: 'Report Metrics',
value: 'reportStats',
description: 'Pull Bento analytics reports for broadcasts, automations, or revenue',
action: 'Fetch report metrics',
},
{
name: 'Segment Metrics',
value: 'segmentStats',
description: 'Fetch segment-level analytics for a selected date range',
action: 'Fetch segment metrics',
},
{
name: 'Send Broadcast',
value: 'sendBroadcast',
description: 'Send a broadcast immediately or at a scheduled time',
action: 'Send a broadcast',
},
{
name: 'Send Transactional Email',
value: 'sendTransactionalEmail',
description: 'Send personalized transactional emails using Bento templates',
action: 'Send a transactional email',
},
{
name: 'Site Metrics',
value: 'siteStats',
description: 'Fetch site-wide analytics for a selected date range',
action: 'Fetch site metrics',
},
{
name: 'Subscriber Command',
value: 'subscriberCommand',
description: 'Execute commands on subscribers (add/remove tags, fields, subscribe/unsubscribe, etc.)',
action: 'Execute a subscriber command',
},
{
name: 'Track Event',
value: 'trackEvent',
description: 'Record custom events and behaviors for subscriber segmentation and automation',
action: 'Track an event',
},
{
name: 'Update Subscriber',
value: 'updateSubscriber',
description: 'Modify subscriber profile information and custom attributes',
action: 'Update a subscriber',
},
{
name: 'Validate Email',
value: 'validateEmail',
description: 'Validate email address for spam/throwaway detection',
action: 'Validate an email address',
},
],
default: 'createSubscriber',
},
{
displayName: 'Email',
name: 'email',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['createSubscriber', 'getSubscriber', 'updateSubscriber'],
},
},
default: '',
placeholder: 'user@example.com',
description: 'The email address of the subscriber - must be a valid email format',
},
{
displayName: 'First Name',
name: 'firstName',
type: 'string',
displayOptions: {
show: {
operation: ['createSubscriber', 'updateSubscriber'],
},
},
default: '',
placeholder: 'John',
description: 'The first name of the subscriber for personalization',
},
{
displayName: 'Last Name',
name: 'lastName',
type: 'string',
displayOptions: {
show: {
operation: ['createSubscriber', 'updateSubscriber'],
},
},
default: '',
placeholder: 'Doe',
description: 'The last name of the subscriber for personalization',
},
{
displayName: 'Custom Fields',
name: 'customFields',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
operation: ['createSubscriber', 'updateSubscriber'],
},
},
default: {},
options: [
{
name: 'field',
displayName: 'Field',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
placeholder: 'company',
description: 'Custom field name',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
placeholder: 'Acme Corp',
description: 'Custom field value',
},
],
},
],
description: 'Additional custom fields to store with the subscriber',
},
{
displayName: 'User ID',
name: 'userId',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['trackEvent'],
},
},
default: '',
placeholder: 'user123@example.com',
description: 'The unique identifier for the user (typically email address)',
},
{
displayName: 'Event Name',
name: 'eventName',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['trackEvent'],
},
},
default: '',
placeholder: 'purchase_completed',
description: 'The name of the custom event to track (e.g., purchase_completed, page_viewed)',
},
{
displayName: 'Event Properties',
name: 'eventProperties',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
operation: ['trackEvent'],
},
},
default: {},
options: [
{
name: 'property',
displayName: 'Property',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
description: 'Property key',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
description: 'Property value',
},
],
},
],
description: 'Additional properties and data to attach to the event for segmentation and personalization',
},
{
displayName: 'Recipient Email',
name: 'recipientEmail',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
},
},
default: '',
placeholder: 'recipient@example.com',
description: 'The email address of the recipient',
},
{
displayName: 'From Email',
name: 'fromEmail',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
},
},
default: '',
placeholder: 'noreply@yourcompany.com',
description: 'The sender email address',
},
{
displayName: 'Subject',
name: 'subject',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
},
},
default: '',
placeholder: 'Reset Password',
description: 'Email subject line',
},
{
displayName: 'Email Type',
name: 'emailType',
type: 'options',
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
},
},
options: [
{
name: 'HTML Body',
value: 'html',
description: 'Send HTML formatted email',
},
{
name: 'Text Body',
value: 'text',
description: 'Send plain text email',
},
],
default: 'html',
description: 'Type of email body to send',
},
{
displayName: 'HTML Body',
name: 'htmlBody',
type: 'string',
typeOptions: {
rows: 8,
},
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
emailType: ['html'],
},
},
default: '',
placeholder: '<p>Here is a link to reset your password ... {{ link }}</p>',
description: 'HTML content of the email (supports template variables like {{ variable_name }})',
},
{
displayName: 'Text Body',
name: 'textBody',
type: 'string',
typeOptions: {
rows: 8,
},
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
emailType: ['text'],
},
},
default: '',
placeholder: 'Here is a link to reset your password ... {{ link }}',
description: 'Plain text content of the email (supports template variables like {{ variable_name }})',
},
{
displayName: 'Transactional',
name: 'transactional',
type: 'boolean',
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
},
},
default: false,
description: 'Whether this is a transactional email (affects tracking and analytics)',
},
{
displayName: 'Personalizations',
name: 'personalizations',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
operation: ['sendTransactionalEmail'],
},
},
default: {},
options: [
{
name: 'personalization',
displayName: 'Personalization',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
placeholder: 'link',
description: 'Template variable name (without {{ }})',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
placeholder: 'https://example.com/reset',
description: 'Value to substitute in template',
},
],
},
],
description: 'Template variables to personalize the email (e.g., link, first_name, order_total)',
},
{
displayName: 'Email',
name: 'commandEmail',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['subscriberCommand'],
},
},
default: '',
placeholder: 'user@example.com',
description: 'The email address of the subscriber to execute the command on',
},
{
displayName: 'Command',
name: 'command',
type: 'options',
required: true,
displayOptions: {
show: {
operation: ['subscriberCommand'],
},
},
options: [
{
name: 'Add Field',
value: 'add_field',
description: 'Add a custom field to the subscriber',
},
{
name: 'Add Tag',
value: 'add_tag',
description: 'Add a tag to the subscriber',
},
{
name: 'Add Tag via Event',
value: 'add_tag_via_event',
description: 'Add a tag to the subscriber via event',
},
{
name: 'Change Email',
value: 'change_email',
description: 'Change the email address of the subscriber',
},
{
name: 'Remove Field',
value: 'remove_field',
description: 'Remove a custom field from the subscriber',
},
{
name: 'Remove Tag',
value: 'remove_tag',
description: 'Remove a tag from the subscriber',
},
{
name: 'Subscribe',
value: 'subscribe',
description: 'Subscribe the email address',
},
{
name: 'Unsubscribe',
value: 'unsubscribe',
description: 'Unsubscribe the email address',
},
],
default: 'add_tag',
description: 'The command to execute on the subscriber',
},
{
displayName: 'Tag/Field Name',
name: 'query',
type: 'string',
displayOptions: {
show: {
operation: ['subscriberCommand'],
command: ['add_tag', 'add_tag_via_event', 'remove_tag', 'remove_field'],
},
},
default: '',
placeholder: 'vip_customer',
description: 'The name of the tag or field to add/remove',
},
{
displayName: 'Field Key',
name: 'fieldKey',
type: 'string',
displayOptions: {
show: {
operation: ['subscriberCommand'],
command: ['add_field'],
},
},
default: '',
placeholder: 'company',
description: 'The key/name of the custom field',
},
{
displayName: 'Field Value',
name: 'fieldValue',
type: 'string',
displayOptions: {
show: {
operation: ['subscriberCommand'],
command: ['add_field'],
},
},
default: '',
placeholder: 'Acme Corp',
description: 'The value of the custom field',
},
{
displayName: 'New Email',
name: 'newEmail',
type: 'string',
displayOptions: {
show: {
operation: ['subscriberCommand'],
command: ['change_email'],
},
},
default: '',
placeholder: 'newemail@example.com',
description: 'The new email address for the subscriber',
},
{
displayName: 'Email',
name: 'validateEmail',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['validateEmail'],
},
},
default: '',
placeholder: 'test@example.com',
description: 'The email address to validate',
},
{
displayName: 'Name',
name: 'validateName',
type: 'string',
displayOptions: {
show: {
operation: ['validateEmail'],
},
},
default: '',
placeholder: 'John Doe',
description: 'The name associated with the email (optional but recommended for better validation)',
},
{
displayName: 'IP Address',
name: 'validateIp',
type: 'string',
displayOptions: {
show: {
operation: ['validateEmail'],
},
},
default: '',
placeholder: '1.1.1.1',
description: 'The IP address associated with the email (optional but recommended for better validation)',
},
{
displayName: 'Domain',
name: 'blacklistDomain',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['blacklistCheck'],
},
},
default: '',
placeholder: 'test.com',
description: 'Domain to evaluate against Bento\'s blacklist service',
},
{
displayName: 'IP Address',
name: 'blacklistIp',
type: 'string',
displayOptions: {
show: {
operation: ['blacklistCheck'],
},
},
default: '',
placeholder: '123.45.67.89',
description: 'Optional IP address to include in the blacklist evaluation',
},
{
displayName: 'Content',
name: 'moderationContent',
type: 'string',
typeOptions: {
rows: 6,
},
required: true,
displayOptions: {
show: {
operation: ['contentModeration'],
},
},
default: '',
placeholder: 'Message text to evaluate...',
description: 'Content that should be evaluated by Bento\'s moderation service',
},
{
displayName: 'Metadata',
name: 'moderationMetadata',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
operation: ['contentModeration'],
},
},
default: {},
description: 'Optional metadata to provide additional context for moderation (key/value pairs)',
options: [
{
name: 'metadata',
displayName: 'Metadata',
values: [
{
displayName: 'Key',
name: 'key',
type: 'string',
default: '',
placeholder: 'source',
},
{
displayName: 'Value',
name: 'value',
type: 'string',
default: '',
placeholder: 'contact_form',
},
],
},
],
},
{
displayName: 'Email',
name: 'genderGuessEmail',
type: 'string',
displayOptions: {
show: {
operation: ['genderGuess'],
},
},
default: '',
placeholder: 'subscriber@example.com',
description: 'Email address associated with the person (optional but improves accuracy)',
},
{
displayName: 'First Name',
name: 'genderGuessFirstName',
type: 'string',
displayOptions: {
show: {
operation: ['genderGuess'],
},
},
default: '',
description: 'First name to help the gender guess service',
},
{
displayName: 'Last Name',
name: 'genderGuessLastName',
type: 'string',
displayOptions: {
show: {
operation: ['genderGuess'],
},
},
default: '',
description: 'Last name to help the gender guess service',
},
{
displayName: 'IP Address',
name: 'geolocationIp',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['geolocationLookup'],
},
},
default: '',
placeholder: '203.0.113.42',
description: 'IP address to look up',
},
{
displayName: 'User Agent',
name: 'geolocationUserAgent',
type: 'string',
displayOptions: {
show: {
operation: ['geolocationLookup'],
},
},
default: '',
description: 'Optional user agent string for additional context',
},
{
displayName: 'Segment ID',
name: 'segmentStatsSegmentId',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['segmentStats'],
},
},
default: '',
placeholder: 'seg_12345',
description: 'Unique identifier of the Bento segment to analyze',
},
{
displayName: 'Report ID',
name: 'reportStatsReportId',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['reportStats'],
},
},
default: '',
placeholder: '456',
description: 'Identifier of the Bento report (report_id) to fetch metrics for',
},
{
displayName: 'Status',
name: 'listBroadcastsStatus',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
operation: ['listBroadcasts'],
},
},
options: [
{
name: 'Any',
value: 'any',
},
{
name: 'Archived',
value: 'archived',
},
{
name: 'Draft',
value: 'draft',
},
{
name: 'Scheduled',
value: 'scheduled',
},
{
name: 'Sending',
value: 'sending',
},
{
name: 'Sent',
value: 'sent',
},
],
default: 'any',
description: 'Filter broadcasts by status',
},
{
displayName: 'Created After',
name: 'listBroadcastsCreatedAfter',
type: 'dateTime',
displayOptions: {
show: {
operation: ['listBroadcasts'],
},
},
default: '',
description: 'Return broadcasts created after this date',
},
{
displayName: 'Tag IDs',
name: 'listBroadcastsTagIds',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
},
displayOptions: {
show: {
operation: ['listBroadcasts'],
},
},
default: {},
description: 'Filter broadcasts linked to specific tag IDs',
options: [
{
name: 'tagId',
displayName: 'Tag ID',
values: [
{
displayName: 'Tag ID',
name: 'id',
type: 'string',
default: '',
placeholder: 'tag_12345',
},
],
},
],
},
{
displayName: 'Campaign Name',
name: 'sendBroadcastName',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'Campaign #1 — Plain Text Example',
description: 'Name to assign to the broadcast campaign',
},
{
displayName: 'Subject',
name: 'sendBroadcastSubject',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'Hello Plain World',
description: 'Email subject line',
},
{
displayName: 'Content',
name: 'sendBroadcastContent',
type: 'string',
typeOptions: {
rows: 5,
},
required: true,
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
description: 'Email content (plain text or HTML based on Content Type)',
},
{
displayName: 'Content Type',
name: 'sendBroadcastType',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
options: [
{
name: 'Plain Text',
value: 'plain',
},
{
name: 'HTML',
value: 'html',
},
],
default: 'plain',
description: 'Render the campaign as plain text or HTML',
},
{
displayName: 'From Email',
name: 'sendBroadcastFromEmail',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'example@example.com',
description: 'Email address shown to recipients',
},
{
displayName: 'From Name',
name: 'sendBroadcastFromName',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'John Doe',
description: 'Display name shown to recipients',
},
{
displayName: 'Approved',
name: 'sendBroadcastApproved',
type: 'boolean',
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: false,
description: 'Whether to mark the broadcast as approved for sending',
},
{
displayName: 'Inclusive Tags',
name: 'sendBroadcastInclusiveTags',
type: 'string',
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'lead,mql',
description: 'Comma-separated tags to include in the audience',
},
{
displayName: 'Exclusive Tags',
name: 'sendBroadcastExclusiveTags',
type: 'string',
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'customers',
description: 'Comma-separated tags to exclude from the audience',
},
{
displayName: 'Segment ID',
name: 'sendBroadcastSegmentId',
type: 'string',
displayOptions: {
show: {
operation: ['sendBroadcast'],
},
},
default: '',
placeholder: 'segment_123456789',
description: 'Segment ide