Documentation
¶
Index ¶
- Constants
- Variables
- func CalculateNextRetryTime(attempts int) time.Time
- func ComputeEmailHMAC(email string, secretKey string) string
- func DecryptString(encrypted, passphrase string) (string, error)
- func EncryptString(plaintext, passphrase string) (string, error)
- func GenerateWebhookCallbackURL(baseURL string, provider EmailProviderKind, workspaceID string, ...) string
- func HasEmailNodes(nodes []*AutomationNode) bool
- func IsValidEventKind(kind string) bool
- func IsValidTimezone(timezone string) bool
- func NewValidationError(message string) error
- func NormalizeSlug(s string) string
- func ParseBoolParam(s string) (bool, error)
- func ParseIntParam(s string) (int, error)
- func ValidateAttachments(attachments []Attachment) error
- func ValidateSupabaseWebhookSignature(payload []byte, signatureHeader, timestampHeader, idHeader, secret string) error
- func VerifyEmailHMAC(email string, providedHMAC string, secretKey string) bool
- func WorkspaceUserKey(workspaceID string) contextKey
- type ABTestNodeConfig
- type ABTestVariant
- type ActivateAutomationRequest
- type AddToListNodeConfig
- type AmazonSESSettings
- type AnalyticsRepository
- type AnalyticsService
- type AnthropicSettings
- type Attachment
- type AttachmentMetadata
- type AttachmentRecord
- type AttachmentRepository
- type AudienceSettings
- type AuthRepository
- type AuthResponse
- type AuthService
- type Automation
- type AutomationFilter
- type AutomationNode
- type AutomationNodeStats
- type AutomationRepository
- type AutomationService
- type AutomationStats
- type AutomationStatus
- type BatchImportContactsRequest
- type BatchImportContactsResponse
- type BlogAuthor
- type BlogCategory
- type BlogCategoryListResponse
- type BlogCategoryRepository
- type BlogCategorySettings
- type BlogPost
- type BlogPostListResponse
- type BlogPostRepository
- type BlogPostSettings
- type BlogPostStatus
- type BlogPostTemplateReference
- type BlogRenderError
- type BlogService
- type BlogSettings
- type BlogTemplateDataRequest
- type BlogTheme
- type BlogThemeFileType
- type BlogThemeFiles
- type BlogThemeListResponse
- type BlogThemeRepository
- type BranchNodeConfig
- type BranchPath
- type Broadcast
- type BroadcastListResponse
- type BroadcastRepository
- type BroadcastSender
- type BroadcastService
- type BroadcastStatus
- type BroadcastTestSettings
- type BroadcastVariation
- type BuildSegmentState
- type BulkUpsertResult
- type CancelBroadcastRequest
- type ChannelOptions
- type ChannelTemplate
- type ChannelTemplates
- type CompileTemplateRequest
- type CompileTemplateResponse
- type Contact
- type ContactAutomation
- type ContactAutomationFilter
- type ContactAutomationStatus
- type ContactAutomationWithWorkspace
- type ContactCondition
- type ContactList
- type ContactListCondition
- type ContactListRepository
- type ContactListService
- type ContactListStatus
- type ContactPreferencesResponse
- type ContactRepository
- type ContactSegment
- type ContactSegmentQueueItem
- type ContactSegmentQueueRepository
- type ContactService
- type ContactTimelineCondition
- type ContactTimelineEntry
- type ContactTimelineRepository
- type ContactTimelineService
- type ContactWithList
- type ContextKey
- type CreateAPIKeyRequest
- type CreateAutomationRequest
- type CreateBlogCategoryRequest
- type CreateBlogPostRequest
- type CreateBlogThemeRequest
- type CreateBroadcastRequest
- type CreateIntegrationRequest
- type CreateListRequest
- type CreateSegmentRequest
- type CreateTaskRequest
- type CreateTemplateBlockRequest
- type CreateTemplateRequest
- type CreateTransactionalRequest
- type CreateWorkspaceRequest
- type CustomEvent
- type CustomEventFilters
- type CustomEventRepository
- type CustomEventService
- type CustomEventsGoalCondition
- type DelayNodeConfig
- type DeleteAutomationRequest
- type DeleteBlogCategoryRequest
- type DeleteBlogPostRequest
- type DeleteBroadcastRequest
- type DeleteContactRequest
- type DeleteIntegrationRequest
- type DeleteListRequest
- type DeleteSegmentRequest
- type DeleteTaskRequest
- type DeleteTemplateBlockRequest
- type DeleteTemplateRequest
- type DeleteTransactionalRequest
- type DeleteWorkspaceRequest
- type DimensionFilter
- type EmailEventType
- type EmailNodeConfig
- type EmailOptions
- type EmailProvider
- type EmailProviderKind
- type EmailProviderService
- type EmailQueueEntry
- type EmailQueuePayload
- type EmailQueueRepository
- type EmailQueueSourceType
- type EmailQueueStats
- type EmailQueueStatus
- type EmailSender
- type EmailServiceInterface
- type EmailTemplate
- type ErrBroadcastNotFound
- type ErrContactListNotFound
- type ErrInboundWebhookEventNotFound
- type ErrListNotFound
- type ErrNotFound
- type ErrSegmentNotFound
- type ErrSessionNotFound
- type ErrSettingNotFound
- type ErrTaskAlreadyRunning
- type ErrTaskExecution
- type ErrTaskTimeout
- type ErrTemplateBlockNotFound
- type ErrTemplateNotFound
- type ErrUnauthorized
- type ErrUserExists
- type ErrUserNotFound
- type ErrWorkspaceNotFound
- type EventAckCallback
- type EventBus
- type EventHandler
- type EventPayload
- type EventType
- type ExecutePendingTasksRequest
- type ExecuteTaskRequest
- type FileManagerSettings
- type FilterNodeConfig
- type FirecrawlSettings
- func (f *FirecrawlSettings) DecryptAPIKey(passphrase string) error
- func (f *FirecrawlSettings) DecryptSecretKeys(passphrase string) error
- func (f *FirecrawlSettings) EncryptAPIKey(passphrase string) error
- func (f *FirecrawlSettings) EncryptSecretKeys(passphrase string) error
- func (f *FirecrawlSettings) GetBaseURL() string
- func (f *FirecrawlSettings) Validate(passphrase string) error
- type GetAutomationRequest
- type GetBlogCategoryRequest
- type GetBlogPostRequest
- type GetBlogThemeRequest
- type GetBroadcastRequest
- type GetBroadcastsRequest
- type GetContactByEmailRequest
- type GetContactByExternalIDRequest
- type GetContactListRequest
- type GetContactNodeExecutionsRequest
- type GetContactsByListRequest
- type GetContactsRequest
- type GetContactsResponse
- type GetEventByIDRequest
- type GetEventsByMessageIDRequest
- type GetListRequest
- type GetListsByContactRequest
- type GetListsRequest
- type GetSegmentRequest
- type GetSegmentsRequest
- type GetTaskRequest
- type GetTemplateBlockRequest
- type GetTemplateRequest
- type GetTemplatesRequest
- type GetTestResultsRequest
- type GetTransactionalRequest
- type GetWebhookStatusRequest
- type GetWorkspaceRequest
- type HTTPClient
- type HttpAuth
- type HttpHeader
- type ImportCustomEventsRequest
- type InMemoryEventBus
- func (b *InMemoryEventBus) Publish(ctx context.Context, event EventPayload)
- func (b *InMemoryEventBus) PublishWithAck(ctx context.Context, event EventPayload, callback EventAckCallback)
- func (b *InMemoryEventBus) Subscribe(eventType EventType, handler EventHandler)
- func (b *InMemoryEventBus) Unsubscribe(eventType EventType, handler EventHandler)
- type InboundWebhookEvent
- type InboundWebhookEventListParams
- type InboundWebhookEventListResult
- type InboundWebhookEventRepository
- type InboundWebhookEventServiceInterface
- type Integration
- type IntegrationType
- type Integrations
- type InviteMemberRequest
- type JSONArray
- type LLMChatEvent
- type LLMChatRequest
- type LLMMessage
- type LLMProvider
- type LLMProviderKind
- type LLMService
- type LLMTool
- type List
- type ListAutomationsRequest
- type ListBlogPostsRequest
- type ListBlogThemesRequest
- type ListBroadcastsParams
- type ListCustomEventsRequest
- type ListRepository
- type ListService
- type ListStats
- type ListStatusBranchNodeConfig
- type ListTasksRequest
- type ListTemplateBlocksRequest
- type ListTransactionalRequest
- type MailgunDelivery
- type MailgunEventData
- type MailgunHeaders
- type MailgunMessage
- type MailgunServiceInterface
- type MailgunSettings
- type MailgunSignature
- type MailgunUrls
- type MailgunWebhook
- type MailgunWebhookListResponse
- type MailgunWebhookPayload
- type MailgunWebhooks
- type MailjetServiceInterface
- type MailjetSettings
- func (m *MailjetSettings) DecryptAPIKey(passphrase string) error
- func (m *MailjetSettings) DecryptSecretKey(passphrase string) error
- func (m *MailjetSettings) EncryptAPIKey(passphrase string) error
- func (m *MailjetSettings) EncryptSecretKey(passphrase string) error
- func (m *MailjetSettings) Validate(passphrase string) error
- type MailjetWebhook
- type MailjetWebhookEventType
- type MailjetWebhookPayload
- type MailjetWebhookResponse
- type MapOfAny
- type MessageData
- type MessageEvent
- type MessageEventUpdate
- type MessageHistory
- type MessageHistoryRepository
- type MessageHistoryService
- type MessageHistoryStatusSum
- type MessageListParams
- type MessageListResult
- type NodeAction
- type NodeExecution
- type NodePosition
- type NodeType
- type NotificationCenterRequest
- type NotificationCenterService
- type NullableFloat64
- type NullableJSON
- type NullableString
- type NullableTime
- type PauseAutomationRequest
- type PauseBroadcastRequest
- type PermissionError
- type PermissionResource
- type PermissionType
- type PostmarkBounceFields
- type PostmarkBounceTrigger
- type PostmarkClickTrigger
- type PostmarkComplaintFields
- type PostmarkDeliveredFields
- type PostmarkDeliveryTrigger
- type PostmarkListWebhooksResponse
- type PostmarkOpenTrigger
- type PostmarkServiceInterface
- type PostmarkSettings
- type PostmarkSpamComplaintTrigger
- type PostmarkSubscriptionChangeTrigger
- type PostmarkTriggerRule
- type PostmarkTriggers
- type PostmarkWebhookConfig
- type PostmarkWebhookPayload
- type PostmarkWebhookResponse
- type PreviewSegmentResponse
- type PublishBlogPostRequest
- type PublishBlogThemeRequest
- type RegisterWebhookRequest
- type RemoveContactFromListRequest
- type RemoveFromListNodeConfig
- type ResourcePermissions
- type ResumeBroadcastRequest
- type RootSigninInput
- type SEOSettings
- type SESBounce
- type SESBounceNotification
- type SESBouncedRecipient
- type SESClient
- type SESCommonHeaders
- type SESComplainedRecipient
- type SESComplaint
- type SESComplaintNotification
- type SESConfigurationSetEventDestination
- type SESDelivery
- type SESDeliveryNotification
- type SESHeader
- type SESMail
- type SESMessageAttribute
- type SESServiceInterface
- type SESTopicConfig
- type SESWebhookClient
- type SESWebhookPayload
- type SMTPSettings
- func (s *SMTPSettings) DecryptPassword(passphrase string) error
- func (s *SMTPSettings) DecryptUsername(passphrase string) error
- func (s *SMTPSettings) EncryptPassword(passphrase string) error
- func (s *SMTPSettings) EncryptUsername(passphrase string) error
- func (s *SMTPSettings) Validate(passphrase string) error
- type SMTPWebhookPayload
- type SNSClient
- type SNSWebhookClient
- type ScheduleBroadcastRequest
- type ScheduleSettings
- type Segment
- type SegmentRepository
- type SegmentService
- type SegmentStatus
- type SelectWinnerRequest
- type SendBroadcastState
- type SendEmailProviderRequest
- type SendEmailRequest
- type SendToIndividualRequest
- type SendTransactionalRequest
- type Session
- type SetUserPermissionsRequest
- type Setting
- type SettingRepository
- type SignInInput
- type SparkPostMSys
- type SparkPostMessageEvent
- type SparkPostServiceInterface
- type SparkPostSettings
- type SparkPostWebhook
- type SparkPostWebhookListResponse
- type SparkPostWebhookPayload
- type SparkPostWebhookResponse
- type SubscribeToListsRequest
- type SupabaseAuthEmailHookSettings
- type SupabaseAuthEmailWebhook
- type SupabaseBeforeUserCreatedWebhook
- type SupabaseEmailActionType
- type SupabaseEmailData
- type SupabaseIntegrationSettings
- type SupabaseTemplateMappings
- type SupabaseUser
- type SupabaseUserCreatedHookSettings
- type SupabaseWebhookMetadata
- type TOCItem
- type Task
- type TaskExecutor
- type TaskFilter
- type TaskListResponse
- type TaskProcessor
- type TaskRepository
- type TaskService
- type TaskState
- type TaskStatus
- type TelemetryMetrics
- type TelemetryRepository
- type Template
- type TemplateBlock
- type TemplateBlockService
- type TemplateCategory
- type TemplateDataRequest
- type TemplateReference
- type TemplateRepository
- type TemplateService
- type TestEmailProviderRequest
- type TestEmailProviderResponse
- type TestResultsResponse
- type TestTemplateRequest
- type TestTemplateResponse
- type TestWinnerMetric
- type TimelineListRequest
- type TimelineListResponse
- type TimelineTriggerConfig
- type TransactionalChannel
- type TransactionalNotification
- type TransactionalNotificationCreateParams
- type TransactionalNotificationRepository
- type TransactionalNotificationSendParams
- type TransactionalNotificationService
- type TransactionalNotificationUpdateParams
- type TreeNode
- type TreeNodeBranch
- type TreeNodeLeaf
- type TriggerFrequency
- type UTMParameters
- type UnpublishBlogPostRequest
- type UnsubscribeFromListsRequest
- type UpdateAutomationRequest
- type UpdateBlogCategoryRequest
- type UpdateBlogPostRequest
- type UpdateBlogThemeRequest
- type UpdateBroadcastRequest
- type UpdateContactListStatusRequest
- type UpdateContactListStatusResult
- type UpdateIntegrationRequest
- type UpdateListRequest
- type UpdateSegmentRequest
- type UpdateTemplateBlockRequest
- type UpdateTemplateRequest
- type UpdateTransactionalRequest
- type UpdateWorkspaceRequest
- type UpsertContactOperation
- type UpsertContactRequest
- type UpsertCustomEventRequest
- type User
- type UserPermissions
- type UserRepository
- type UserServiceInterface
- type UserType
- type UserWorkspace
- type UserWorkspaceWithEmail
- type ValidationError
- type VariationMetrics
- type VariationResult
- type VerifyCodeInput
- type WebTemplate
- type WebhookDelivery
- type WebhookDeliveryRepository
- type WebhookDeliveryWithSubscription
- type WebhookEndpointStatus
- type WebhookNodeConfig
- type WebhookProvider
- type WebhookRegistrationConfig
- type WebhookRegistrationService
- type WebhookRegistrationStatus
- type WebhookSource
- type WebhookSubscription
- type WebhookSubscriptionRepository
- type WebhookSubscriptionSettings
- type Workspace
- func (w *Workspace) AddIntegration(integration Integration)
- func (w *Workspace) AfterLoad(globalSecretKey string) error
- func (w *Workspace) BeforeSave(globalSecretKey string) error
- func (w *Workspace) GetEmailProvider(isMarketing bool) (*EmailProvider, error)
- func (w *Workspace) GetEmailProviderWithIntegrationID(isMarketing bool) (*EmailProvider, string, error)
- func (w *Workspace) GetIntegrationByID(id string) *Integration
- func (w *Workspace) GetIntegrationsByType(integrationType IntegrationType) []*Integration
- func (w *Workspace) MarshalJSON() ([]byte, error)
- func (w *Workspace) RemoveIntegration(id string) bool
- func (w *Workspace) Validate(passphrase string) error
- type WorkspaceInvitation
- type WorkspaceRepository
- type WorkspaceServiceInterface
- type WorkspaceSettings
Constants ¶
const ( ErrCodeThemeNotFound = "theme_not_found" ErrCodeThemeNotPublished = "theme_not_published" ErrCodePostNotFound = "post_not_found" ErrCodeCategoryNotFound = "category_not_found" ErrCodeRenderFailed = "render_failed" ErrCodeInvalidLiquidSyntax = "invalid_liquid_syntax" )
Error codes for blog rendering
const ( UpsertContactOperationCreate = "create" UpsertContactOperationUpdate = "update" UpsertContactOperationError = "error" )
const ( GoalTypePurchase = "purchase" // Transaction with revenue (goal_value REQUIRED) GoalTypeSubscription = "subscription" // Recurring revenue started (goal_value REQUIRED) GoalTypeLead = "lead" // Form/inquiry submission (goal_value optional) GoalTypeSignup = "signup" // Registration/account creation (goal_value optional) GoalTypeBooking = "booking" // Appointment/demo scheduled (goal_value optional) GoalTypeTrial = "trial" // Trial started (goal_value optional) GoalTypeOther = "other" // Custom goal (goal_value optional) )
Goal type constants
const ( ChannelEmail = "email" ChannelWeb = "web" )
Channel constants for templates
const ( UserIDKey contextKey = "user_id" SessionIDKey contextKey = "session_id" UserTypeKey contextKey = "type" UserWorkspaceKey contextKey = "user_workspace" )
const ( WebhookDeliveryStatusPending = "pending" WebhookDeliveryStatusDelivering = "delivering" WebhookDeliveryStatusDelivered = "delivered" WebhookDeliveryStatusFailed = "failed" )
WebhookDeliveryStatus constants
const (
BlogCacheTTL = 5 * time.Minute // TTL for cached blog pages
)
Blog cache configuration
const EmailQueuePriorityMarketing = 5
Default priority for marketing emails (broadcasts and automations)
Variables ¶
var (
ErrContactNotFound = errors.New("contact not found")
)
var ErrInsufficientPermissions = NewPermissionError( PermissionResourceWorkspace, PermissionTypeRead, "Insufficient permissions", )
ErrInsufficientPermissions is the default insufficient permissions error
var FullPermissions = UserPermissions{ PermissionResourceContacts: ResourcePermissions{Read: true, Write: true}, PermissionResourceLists: ResourcePermissions{Read: true, Write: true}, PermissionResourceTemplates: ResourcePermissions{Read: true, Write: true}, PermissionResourceBroadcasts: ResourcePermissions{Read: true, Write: true}, PermissionResourceTransactional: ResourcePermissions{Read: true, Write: true}, PermissionResourceWorkspace: ResourcePermissions{Read: true, Write: true}, PermissionResourceMessageHistory: ResourcePermissions{Read: true, Write: true}, PermissionResourceBlog: ResourcePermissions{Read: true, Write: true}, PermissionResourceAutomations: ResourcePermissions{Read: true, Write: true}, PermissionResourceLLM: ResourcePermissions{Read: true, Write: true}, }
var GoalTypesRequiringValue = []string{ GoalTypePurchase, GoalTypeSubscription, }
GoalTypesRequiringValue is the list of goal types that require goal_value
var PredefinedSchemas = map[string]analytics.SchemaDefinition{ "message_history": { Name: "message_history", Measures: map[string]analytics.MeasureDefinition{ "count": { Type: "count", Title: "Total Messages", SQL: "COUNT(*)", Description: "Total number of message history records", }, "count_sent": { Type: "count", Title: "Sent", SQL: "*", Description: "Total number of sent messages", Filters: []analytics.MeasureFilter{ {SQL: "sent_at IS NOT NULL"}, }, }, "count_delivered": { Type: "count", Title: "Delivered", SQL: "*", Description: "Total number of delivered messages", Filters: []analytics.MeasureFilter{ {SQL: "delivered_at IS NOT NULL"}, }, }, "count_bounced": { Type: "count", Title: "Bounced", SQL: "*", Description: "Total number of bounced messages", Filters: []analytics.MeasureFilter{ {SQL: "bounced_at IS NOT NULL"}, }, }, "count_complained": { Type: "count", Title: "Complaints", SQL: "*", Description: "Total number of complained messages", Filters: []analytics.MeasureFilter{ {SQL: "complained_at IS NOT NULL"}, }, }, "count_opened": { Type: "count", Title: "Opens", SQL: "*", Description: "Total number of opened messages", Filters: []analytics.MeasureFilter{ {SQL: "opened_at IS NOT NULL"}, }, }, "count_clicked": { Type: "count", Title: "Clicks", SQL: "*", Description: "Total number of clicked messages", Filters: []analytics.MeasureFilter{ {SQL: "clicked_at IS NOT NULL"}, }, }, "count_unsubscribed": { Type: "count", Title: "Unsubscribes", SQL: "*", Description: "Total number of unsubscribed messages", Filters: []analytics.MeasureFilter{ {SQL: "unsubscribed_at IS NOT NULL"}, }, }, "count_failed": { Type: "count", Title: "Failed", SQL: "*", Description: "Total number of failed messages", Filters: []analytics.MeasureFilter{ {SQL: "failed_at IS NOT NULL"}, }, }, "count_sent_emails": { Type: "count", Title: "Sent Emails", SQL: "*", Description: "Total number of sent email messages", Filters: []analytics.MeasureFilter{ {SQL: "sent_at IS NOT NULL"}, {SQL: "channel = 'email'"}, }, }, "count_delivered_emails": { Type: "count", Title: "Delivered Emails", SQL: "*", Description: "Total number of delivered email messages", Filters: []analytics.MeasureFilter{ {SQL: "delivered_at IS NOT NULL"}, {SQL: "channel = 'email'"}, }, }, "count_broadcast_messages": { Type: "count", Title: "Broadcast Messages", SQL: "*", Description: "Total number of broadcast messages", Filters: []analytics.MeasureFilter{ {SQL: "broadcast_id IS NOT NULL"}, }, }, "count_transactional_messages": { Type: "count", Title: "Transactional Messages", SQL: "*", Description: "Total number of transactional messages", Filters: []analytics.MeasureFilter{ {SQL: "broadcast_id IS NULL"}, }, }, "count_recent_messages": { Type: "count", Title: "Recent Messages", SQL: "*", Description: "Messages from the last 30 days", Filters: []analytics.MeasureFilter{ {SQL: "created_at >= NOW() - INTERVAL '30 days'"}, }, }, "count_successful_deliveries": { Type: "count", Title: "Successful Deliveries", SQL: "*", Description: "Successfully delivered messages (not bounced or failed)", Filters: []analytics.MeasureFilter{ {SQL: "delivered_at IS NOT NULL"}, {SQL: "bounced_at IS NULL"}, {SQL: "failed_at IS NULL"}, }, }, }, Dimensions: map[string]analytics.DimensionDefinition{ "created_at": { Type: "time", Title: "Created At", SQL: "created_at", Description: "Message creation timestamp", }, "sent_at": { Type: "time", Title: "Sent At", SQL: "sent_at", Description: "Message sent timestamp", }, "contact_email": { Type: "string", Title: "Contact Email", SQL: "contact_email", Description: "Recipient email address", }, "broadcast_id": { Type: "string", Title: "Broadcast ID", SQL: "broadcast_id", Description: "Associated broadcast ID", }, "channel": { Type: "string", Title: "Channel", SQL: "channel", Description: "Message channel (email, sms, etc.)", }, "template_id": { Type: "string", Title: "Template ID", SQL: "template_id", Description: "Template identifier", }, }, }, "contacts": { Name: "contacts", Measures: map[string]analytics.MeasureDefinition{ "count": { Type: "count", Title: "Total Contacts", SQL: "*", Description: "Total number of contacts", }, "count_active": { Type: "count", Title: "Active Contacts", SQL: "*", Description: "Total number of active contacts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'active'"}, }, }, "count_unsubscribed": { Type: "count", Title: "Unsubscribed Contacts", SQL: "*", Description: "Total number of unsubscribed contacts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'unsubscribed'"}, }, }, "count_bounced": { Type: "count", Title: "Bounced Contacts", SQL: "*", Description: "Total number of bounced contacts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'bounced'"}, }, }, "count_recent_contacts": { Type: "count", Title: "Recent Contacts", SQL: "*", Description: "Contacts created in the last 30 days", Filters: []analytics.MeasureFilter{ {SQL: "created_at >= NOW() - INTERVAL '30 days'"}, }, }, "count_with_source": { Type: "count", Title: "Contacts with Source", SQL: "*", Description: "Contacts with a known source", Filters: []analytics.MeasureFilter{ {SQL: "source IS NOT NULL"}, {SQL: "source != ''"}, }, }, "avg_created_days_ago": { Type: "avg", Title: "Average Days Since Creation", SQL: "EXTRACT(EPOCH FROM (NOW() - created_at)) / 86400", Description: "Average days since contact creation", }, }, Dimensions: map[string]analytics.DimensionDefinition{ "created_at": { Type: "time", Title: "Created At", SQL: "created_at", Description: "Contact creation timestamp", }, "email": { Type: "string", Title: "Email", SQL: "email", Description: "Contact email address", }, "first_name": { Type: "string", Title: "First Name", SQL: "first_name", Description: "Contact first name", }, "last_name": { Type: "string", Title: "Last Name", SQL: "last_name", Description: "Contact last name", }, "external_id": { Type: "string", Title: "External ID", SQL: "external_id", Description: "External contact identifier", }, "timezone": { Type: "string", Title: "Timezone", SQL: "timezone", Description: "Contact timezone", }, "country": { Type: "string", Title: "Country", SQL: "country", Description: "Contact country", }, }, }, "broadcasts": { Name: "broadcasts", Measures: map[string]analytics.MeasureDefinition{ "count": { Type: "count", Title: "Total Broadcasts", SQL: "*", Description: "Total number of broadcasts", }, "count_draft": { Type: "count", Title: "Draft Broadcasts", SQL: "*", Description: "Total number of draft broadcasts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'draft'"}, }, }, "count_scheduled": { Type: "count", Title: "Scheduled Broadcasts", SQL: "*", Description: "Total number of scheduled broadcasts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'scheduled'"}, }, }, "count_sending": { Type: "count", Title: "Sending Broadcasts", SQL: "*", Description: "Total number of broadcasts currently sending", Filters: []analytics.MeasureFilter{ {SQL: "status = 'sending'"}, }, }, "count_recent": { Type: "count", Title: "Recent Broadcasts", SQL: "*", Description: "Broadcasts created in the last 30 days", Filters: []analytics.MeasureFilter{ {SQL: "created_at >= NOW() - INTERVAL '30 days'"}, }, }, "avg_recipients": { Type: "avg", Title: "Average Recipients", SQL: "recipient_count", Description: "Average number of recipients per broadcast", }, "sum_recipients": { Type: "sum", Title: "Total Recipients", SQL: "recipient_count", Description: "Total number of recipients across all broadcasts", }, "max_recipients": { Type: "max", Title: "Max Recipients", SQL: "recipient_count", Description: "Maximum recipients in a single broadcast", }, "min_recipients": { Type: "min", Title: "Min Recipients", SQL: "recipient_count", Description: "Minimum recipients in a single broadcast", }, "test_recipients": { Type: "sum", Title: "Test Recipients", SQL: "test_phase_recipient_count", Description: "Total test phase recipients", }, "completed_broadcasts_count": { Type: "count", Title: "Completed Broadcasts", SQL: "*", Description: "Total number of completed broadcasts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'completed'"}, }, }, "avg_recipients_completed": { Type: "avg", SQL: "recipient_count", Description: "Average recipients for completed broadcasts only", Filters: []analytics.MeasureFilter{ {SQL: "status = 'completed'"}, }, }, "winner_recipients": { Type: "sum", SQL: "winner_phase_recipient_count", Description: "Total winner phase recipients", }, "avg_test_recipients": { Type: "avg", SQL: "test_phase_recipient_count", Description: "Average test phase recipients per broadcast", Filters: []analytics.MeasureFilter{ {SQL: "test_phase_recipient_count > 0"}, }, }, "sum_recipients_completed": { Type: "sum", SQL: "recipient_count", Description: "Total recipients for completed broadcasts", Filters: []analytics.MeasureFilter{ {SQL: "status = 'completed'"}, }, }, "count_with_ab_test": { Type: "count", SQL: "*", Description: "Broadcasts with A/B testing enabled", Filters: []analytics.MeasureFilter{ {SQL: "test_phase_recipient_count > 0"}, }, }, "count_large_broadcasts": { Type: "count", SQL: "*", Description: "Broadcasts with more than 1000 recipients", Filters: []analytics.MeasureFilter{ {SQL: "recipient_count > 1000"}, }, }, }, Dimensions: map[string]analytics.DimensionDefinition{ "id": { Type: "string", SQL: "id", Description: "Broadcast identifier", }, "name": { Type: "string", SQL: "name", Description: "Broadcast name", }, "status": { Type: "string", SQL: "status", Description: "Broadcast status", }, "created_at": { Type: "time", SQL: "created_at", Description: "Broadcast creation timestamp", }, "started_at": { Type: "time", SQL: "started_at", Description: "Broadcast start timestamp", }, "completed_at": { Type: "time", SQL: "completed_at", Description: "Broadcast completion timestamp", }, "workspace_id": { Type: "string", SQL: "workspace_id", Description: "Associated workspace ID", }, }, }, "webhook_deliveries": { Name: "webhook_deliveries", Measures: map[string]analytics.MeasureDefinition{ "count": { Type: "count", Title: "Total Deliveries", SQL: "*", Description: "Total number of webhook deliveries", }, "count_delivered": { Type: "count", Title: "Delivered", SQL: "*", Description: "Successfully delivered webhooks", Filters: []analytics.MeasureFilter{ {SQL: "status = 'delivered'"}, }, }, "count_failed": { Type: "count", Title: "Failed", SQL: "*", Description: "Failed webhook deliveries", Filters: []analytics.MeasureFilter{ {SQL: "status = 'failed'"}, }, }, }, Dimensions: map[string]analytics.DimensionDefinition{ "created_at": { Type: "time", Title: "Created At", SQL: "created_at", Description: "Delivery creation timestamp", }, "subscription_id": { Type: "string", Title: "Subscription ID", SQL: "subscription_id", Description: "Associated webhook subscription", }, "status": { Type: "string", Title: "Status", SQL: "status", Description: "Delivery status", }, }, }, "email_queue": { Name: "email_queue", Measures: map[string]analytics.MeasureDefinition{ "count": { Type: "count", Title: "Total Entries", SQL: "*", Description: "Total queue entries", }, "count_pending": { Type: "count", Title: "Pending", SQL: "*", Description: "Emails waiting to be sent", Filters: []analytics.MeasureFilter{ {SQL: "status = 'pending'"}, }, }, "count_processing": { Type: "count", Title: "Processing", SQL: "*", Description: "Emails currently being processed", Filters: []analytics.MeasureFilter{ {SQL: "status = 'processing'"}, }, }, "count_failed": { Type: "count", Title: "Failed", SQL: "*", Description: "Emails that failed and awaiting retry", Filters: []analytics.MeasureFilter{ {SQL: "status = 'failed'"}, }, }, "count_broadcast": { Type: "count", Title: "Broadcast Emails", SQL: "*", Description: "Emails from broadcasts", Filters: []analytics.MeasureFilter{ {SQL: "source_type = 'broadcast'"}, }, }, "count_automation": { Type: "count", Title: "Automation Emails", SQL: "*", Description: "Emails from automations", Filters: []analytics.MeasureFilter{ {SQL: "source_type = 'automation'"}, }, }, "avg_attempts": { Type: "avg", Title: "Average Attempts", SQL: "attempts", Description: "Average number of send attempts", }, "max_attempts": { Type: "max", Title: "Max Attempts", SQL: "attempts", Description: "Maximum number of send attempts", }, "count_retryable": { Type: "count", Title: "Retryable", SQL: "*", Description: "Failed emails that can still be retried", Filters: []analytics.MeasureFilter{ {SQL: "status = 'failed'"}, {SQL: "attempts < max_attempts"}, }, }, }, Dimensions: map[string]analytics.DimensionDefinition{ "created_at": { Type: "time", Title: "Created At", SQL: "created_at", Description: "When the email was queued", }, "updated_at": { Type: "time", Title: "Updated At", SQL: "updated_at", Description: "Last update timestamp", }, "next_retry_at": { Type: "time", Title: "Next Retry At", SQL: "next_retry_at", Description: "Scheduled retry time for failed emails", }, "status": { Type: "string", Title: "Status", SQL: "status", Description: "Queue entry status (pending, processing, failed)", }, "source_type": { Type: "string", Title: "Source Type", SQL: "source_type", Description: "Origin type (broadcast, automation)", }, "source_id": { Type: "string", Title: "Source ID", SQL: "source_id", Description: "Broadcast or automation ID", }, "integration_id": { Type: "string", Title: "Integration ID", SQL: "integration_id", Description: "Email provider integration ID", }, "provider_kind": { Type: "string", Title: "Provider Kind", SQL: "provider_kind", Description: "Email provider type (ses, smtp, etc.)", }, "priority": { Type: "number", Title: "Priority", SQL: "priority", Description: "Queue priority (lower = higher priority)", }, "template_id": { Type: "string", Title: "Template ID", SQL: "template_id", Description: "Email template identifier", }, "contact_email": { Type: "string", Title: "Contact Email", SQL: "contact_email", Description: "Recipient email address", }, }, }, "automation_node_executions": { Name: "automation_node_executions", Measures: map[string]analytics.MeasureDefinition{ "count": { Type: "count", Title: "Total Executions", SQL: "*", Description: "Total node executions", }, "count_entered": { Type: "count", Title: "Entered", SQL: "*", Description: "Contacts that entered nodes", Filters: []analytics.MeasureFilter{ {SQL: "action = 'entered'"}, }, }, "count_completed": { Type: "count", Title: "Completed", SQL: "*", Description: "Successfully completed executions", Filters: []analytics.MeasureFilter{ {SQL: "action = 'completed'"}, }, }, "count_failed": { Type: "count", Title: "Failed", SQL: "*", Description: "Failed executions", Filters: []analytics.MeasureFilter{ {SQL: "action = 'failed'"}, }, }, "count_skipped": { Type: "count", Title: "Skipped", SQL: "*", Description: "Skipped executions", Filters: []analytics.MeasureFilter{ {SQL: "action = 'skipped'"}, }, }, }, Dimensions: map[string]analytics.DimensionDefinition{ "automation_id": { Type: "string", Title: "Automation ID", SQL: "automation_id", Description: "Automation identifier", }, "node_id": { Type: "string", Title: "Node ID", SQL: "node_id", Description: "Node identifier", }, "node_type": { Type: "string", Title: "Node Type", SQL: "node_type", Description: "Type of node", }, "action": { Type: "string", Title: "Action", SQL: "action", Description: "Execution action", }, "entered_at": { Type: "time", Title: "Entered At", SQL: "entered_at", Description: "When node was entered", }, }, }, }
PredefinedSchemas contains all available analytics schemas for Notifuse
var Timezones = []string{}/* 594 elements not displayed */
Timezones contains all valid IANA timezone identifiers This list is generated from Go's embedded timezone database It includes both canonical zones and aliases (links)
To regenerate this list, run: go generate ./internal/domain
var ValidEventKinds = []string{
"contact.created", "contact.updated", "contact.deleted",
"list.subscribed", "list.unsubscribed", "list.confirmed", "list.resubscribed",
"list.bounced", "list.complained", "list.pending", "list.removed",
"segment.joined", "segment.left",
"email.sent", "email.delivered", "email.opened", "email.clicked",
"email.bounced", "email.complained", "email.unsubscribed",
"custom_event",
}
ValidEventKinds defines all allowed automation trigger event kinds
var ValidGoalTypes = []string{ GoalTypePurchase, GoalTypeSubscription, GoalTypeLead, GoalTypeSignup, GoalTypeBooking, GoalTypeTrial, GoalTypeOther, }
ValidGoalTypes is the list of all valid goal types
var WebhookEventTypes = []string{
"contact.created",
"contact.updated",
"contact.deleted",
"list.subscribed",
"list.unsubscribed",
"list.confirmed",
"list.resubscribed",
"list.bounced",
"list.complained",
"list.pending",
"list.removed",
"segment.joined",
"segment.left",
"email.sent",
"email.delivered",
"email.opened",
"email.clicked",
"email.bounced",
"email.complained",
"email.unsubscribed",
"custom_event.created",
"custom_event.updated",
"custom_event.deleted",
}
Available webhook event types
Functions ¶
func CalculateNextRetryTime ¶
CalculateNextRetryTime calculates the next retry time using exponential backoff Backoff: base, 2*base, 4*base for attempts 1, 2, 3 (default base = 1min)
func ComputeEmailHMAC ¶
ComputeEmailHMAC computes an HMAC for an email address using the workspace secret key
func DecryptString ¶
DecryptString decrypts an encrypted string
func EncryptString ¶
EncryptString encrypts a string using the same encryption as other sensitive data
func GenerateWebhookCallbackURL ¶
func GenerateWebhookCallbackURL(baseURL string, provider EmailProviderKind, workspaceID string, integrationID string) string
GenerateWebhookCallbackURL generates a standardized webhook callback URL for a specific provider The URL follows the format: {baseURL}/webhooks/email?provider={provider}&workspace_id={workspaceID}&integration_id={integrationID} This ensures a consistent URL pattern across all email provider integrations.
Parameters:
- baseURL: The base URL of the application (e.g., "https://api.example.com")
- provider: The email provider kind (e.g., domain.EmailProviderKindPostmark)
- workspaceID: The workspace ID
- integrationID: The integration ID
Returns:
- The fully formatted webhook callback URL
func HasEmailNodes ¶
func HasEmailNodes(nodes []*AutomationNode) bool
HasEmailNodes checks if any nodes in the provided list are email nodes
func IsValidEventKind ¶
IsValidEventKind checks if the given event kind is valid
func IsValidTimezone ¶
IsValidTimezone checks if the given timezone is valid
func NewValidationError ¶
NewValidationError creates a new validation error with the given message
func NormalizeSlug ¶
NormalizeSlug normalizes a string to be a valid slug
func ParseBoolParam ¶
parseBoolParam parses a string to a boolean
func ParseIntParam ¶
parseIntParam parses a string to an integer
func ValidateAttachments ¶
func ValidateAttachments(attachments []Attachment) error
ValidateAttachments validates a slice of attachments
func ValidateSupabaseWebhookSignature ¶
func ValidateSupabaseWebhookSignature(payload []byte, signatureHeader, timestampHeader, idHeader, secret string) error
ValidateSupabaseWebhookSignature validates a Supabase webhook signature Supabase uses the standard-webhooks format with webhook-id, webhook-timestamp, and webhook-signature headers
func VerifyEmailHMAC ¶
VerifyEmailHMAC verifies if the provided HMAC for an email is valid
func WorkspaceUserKey ¶
func WorkspaceUserKey(workspaceID string) contextKey
WorkspaceUserKey creates a context key for storing a workspace-specific user
Types ¶
type ABTestNodeConfig ¶
type ABTestNodeConfig struct {
Variants []ABTestVariant `json:"variants"`
}
ABTestNodeConfig configures an A/B test node
func (ABTestNodeConfig) Validate ¶
func (c ABTestNodeConfig) Validate() error
Validate validates the A/B test node config
type ABTestVariant ¶
type ABTestVariant struct {
ID string `json:"id"` // "A", "B", etc.
Name string `json:"name"` // "Control", "Variant B", etc.
Weight int `json:"weight"` // 1-100
NextNodeID string `json:"next_node_id"` // Node to execute for this variant
}
ABTestVariant represents a variant in an A/B test node
func (ABTestVariant) Validate ¶
func (v ABTestVariant) Validate() error
Validate validates the A/B test variant
type ActivateAutomationRequest ¶
type ActivateAutomationRequest struct {
WorkspaceID string `json:"workspace_id"`
AutomationID string `json:"automation_id"`
}
ActivateAutomationRequest represents the request to activate an automation
func (*ActivateAutomationRequest) Validate ¶
func (r *ActivateAutomationRequest) Validate() error
Validate validates the activate automation request
type AddToListNodeConfig ¶
type AddToListNodeConfig struct {
ListID string `json:"list_id"`
Status string `json:"status"` // "active", "pending"
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
AddToListNodeConfig configures an add-to-list node
func (AddToListNodeConfig) Validate ¶
func (c AddToListNodeConfig) Validate() error
Validate validates the add-to-list node config
type AmazonSESSettings ¶
type AmazonSESSettings struct {
Region string `json:"region"`
AccessKey string `json:"access_key"`
EncryptedSecretKey string `json:"encrypted_secret_key,omitempty"`
// decoded secret key, not stored in the database
SecretKey string `json:"secret_key,omitempty"`
}
AmazonSESSettings contains SES email provider settings
func (*AmazonSESSettings) DecryptSecretKey ¶
func (a *AmazonSESSettings) DecryptSecretKey(passphrase string) error
func (*AmazonSESSettings) EncryptSecretKey ¶
func (a *AmazonSESSettings) EncryptSecretKey(passphrase string) error
func (*AmazonSESSettings) Validate ¶
func (a *AmazonSESSettings) Validate(passphrase string) error
type AnalyticsRepository ¶
type AnalyticsRepository interface {
Query(ctx context.Context, workspaceID string, query analytics.Query) (*analytics.Response, error)
GetSchemas(ctx context.Context, workspaceID string) (map[string]analytics.SchemaDefinition, error)
}
AnalyticsRepository defines the analytics data access interface
type AnalyticsService ¶
type AnalyticsService interface {
Query(ctx context.Context, workspaceID string, query analytics.Query) (*analytics.Response, error)
GetSchemas(ctx context.Context, workspaceID string) (map[string]analytics.SchemaDefinition, error)
}
AnalyticsService defines the analytics business logic interface
type AnthropicSettings ¶
type AnthropicSettings struct {
EncryptedAPIKey string `json:"encrypted_api_key,omitempty"`
Model string `json:"model"` // free text - e.g. claude-sonnet-4-20250514
// Decoded API key, not stored in the database
APIKey string `json:"api_key,omitempty"`
}
AnthropicSettings contains configuration for Anthropic Claude
func (*AnthropicSettings) DecryptAPIKey ¶
func (a *AnthropicSettings) DecryptAPIKey(passphrase string) error
DecryptAPIKey decrypts the encrypted API key
func (*AnthropicSettings) EncryptAPIKey ¶
func (a *AnthropicSettings) EncryptAPIKey(passphrase string) error
EncryptAPIKey encrypts the API key
func (*AnthropicSettings) Validate ¶
func (a *AnthropicSettings) Validate(passphrase string) error
Validate validates the Anthropic settings
type Attachment ¶
type Attachment struct {
Filename string `json:"filename" validate:"required"`
Content string `json:"content" validate:"required"` // base64 encoded
ContentType string `json:"content_type,omitempty"`
Disposition string `json:"disposition,omitempty"` // "attachment" (default) or "inline"
}
Attachment represents an email attachment
func (*Attachment) CalculateChecksum ¶
func (a *Attachment) CalculateChecksum() (string, error)
CalculateChecksum calculates SHA256 checksum of the content
func (*Attachment) DecodeContent ¶
func (a *Attachment) DecodeContent() ([]byte, error)
DecodeContent decodes the base64 content
func (*Attachment) DetectContentType ¶
func (a *Attachment) DetectContentType() error
DetectContentType detects content type if not provided
func (*Attachment) ToMetadata ¶
func (a *Attachment) ToMetadata(checksum string) *AttachmentMetadata
ToMetadata converts an Attachment to AttachmentMetadata
func (*Attachment) Validate ¶
func (a *Attachment) Validate() error
Validate validates an attachment
type AttachmentMetadata ¶
type AttachmentMetadata struct {
Checksum string `json:"checksum"`
Filename string `json:"filename"`
ContentType string `json:"content_type"`
Disposition string `json:"disposition"`
}
AttachmentMetadata represents metadata stored in message_history
type AttachmentRecord ¶
AttachmentRecord represents a stored attachment in the database
type AttachmentRepository ¶
type AttachmentRepository interface {
// Store saves an attachment and returns its checksum
Store(ctx context.Context, workspaceID string, record *AttachmentRecord) error
// Get retrieves an attachment by checksum
Get(ctx context.Context, workspaceID string, checksum string) (*AttachmentRecord, error)
// Exists checks if an attachment exists by checksum
Exists(ctx context.Context, workspaceID string, checksum string) (bool, error)
}
AttachmentRepository defines methods for attachment persistence
type AudienceSettings ¶
type AudienceSettings struct {
List string `json:"list,omitempty"`
Segments []string `json:"segments,omitempty"`
ExcludeUnsubscribed bool `json:"exclude_unsubscribed"`
}
AudienceSettings defines how recipients are determined for a broadcast
func (*AudienceSettings) Scan ¶
func (a *AudienceSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type AuthRepository ¶
type AuthRepository interface {
GetSessionByID(ctx context.Context, sessionID string, userID string) (*time.Time, error)
GetUserByID(ctx context.Context, userID string) (*User, error)
}
AuthRepository defines the interface for auth-related database operations
type AuthResponse ¶
type AuthService ¶
type AuthService interface {
AuthenticateUserFromContext(ctx context.Context) (*User, error)
AuthenticateUserForWorkspace(ctx context.Context, workspaceID string) (context.Context, *User, *UserWorkspace, error)
VerifyUserSession(ctx context.Context, userID, sessionID string) (*User, error)
GenerateUserAuthToken(user *User, sessionID string, expiresAt time.Time) string
GenerateAPIAuthToken(user *User) string
GenerateInvitationToken(invitation *WorkspaceInvitation) string
ValidateInvitationToken(token string) (invitationID, workspaceID, email string, err error)
InvalidateSecretCache()
}
type Automation ¶
type Automation struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
Name string `json:"name"`
Status AutomationStatus `json:"status"`
ListID string `json:"list_id"`
Trigger *TimelineTriggerConfig `json:"trigger"`
TriggerSQL *string `json:"trigger_sql,omitempty"` // Generated SQL for WHEN clause
RootNodeID string `json:"root_node_id"`
Nodes []*AutomationNode `json:"nodes"` // Embedded workflow nodes
Stats *AutomationStats `json:"stats,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"` // Soft-delete timestamp
}
Automation represents an email marketing automation workflow
func (*Automation) GetNodeByID ¶
func (a *Automation) GetNodeByID(nodeID string) *AutomationNode
GetNodeByID finds a node in the automation's Nodes array by ID
func (*Automation) HasEmailNodeRestriction ¶
func (a *Automation) HasEmailNodeRestriction() bool
HasEmailNodeRestriction returns true if email nodes are not allowed for this automation. Email nodes require a list to be configured because emails need contact data from list membership.
func (*Automation) Validate ¶
func (a *Automation) Validate() error
Validate validates the automation
type AutomationFilter ¶
type AutomationFilter struct {
Status []AutomationStatus
ListID string
IncludeDeleted bool // When true, includes soft-deleted automations in results
Limit int
Offset int
}
AutomationFilter defines filtering options for listing automations
type AutomationNode ¶
type AutomationNode struct {
ID string `json:"id"`
AutomationID string `json:"automation_id"`
Type NodeType `json:"type"`
Config map[string]interface{} `json:"config"`
NextNodeID *string `json:"next_node_id,omitempty"`
Position NodePosition `json:"position"`
CreatedAt time.Time `json:"created_at"`
}
AutomationNode represents a node in an automation workflow
func (*AutomationNode) Validate ¶
func (n *AutomationNode) Validate() error
Validate validates the automation node
func (*AutomationNode) ValidateForAutomation ¶
func (n *AutomationNode) ValidateForAutomation(automation *Automation) error
ValidateForAutomation validates the node in context of its parent automation. This includes additional checks like email node restrictions.
type AutomationNodeStats ¶
type AutomationNodeStats struct {
NodeID string `json:"node_id"`
NodeType string `json:"node_type"`
Entered int64 `json:"entered"`
Completed int64 `json:"completed"`
Failed int64 `json:"failed"`
Skipped int64 `json:"skipped"`
}
AutomationNodeStats holds statistics for a single automation node
type AutomationRepository ¶
type AutomationRepository interface {
// Transaction support
WithTransaction(ctx context.Context, fn func(*sql.Tx) error) error
// Automation CRUD (nodes are embedded in automation as JSONB)
Create(ctx context.Context, workspaceID string, automation *Automation) error
CreateTx(ctx context.Context, tx *sql.Tx, workspaceID string, automation *Automation) error
GetByID(ctx context.Context, workspaceID, id string) (*Automation, error)
GetByIDTx(ctx context.Context, tx *sql.Tx, workspaceID, id string) (*Automation, error)
List(ctx context.Context, workspaceID string, filter AutomationFilter) ([]*Automation, int, error)
Update(ctx context.Context, workspaceID string, automation *Automation) error
UpdateTx(ctx context.Context, tx *sql.Tx, workspaceID string, automation *Automation) error
Delete(ctx context.Context, workspaceID, id string) error
DeleteTx(ctx context.Context, tx *sql.Tx, workspaceID, id string) error
// Trigger management (dynamic SQL execution)
CreateAutomationTrigger(ctx context.Context, workspaceID string, automation *Automation) error
DropAutomationTrigger(ctx context.Context, workspaceID, automationID string) error
// Contact automation operations
GetContactAutomation(ctx context.Context, workspaceID, id string) (*ContactAutomation, error)
GetContactAutomationTx(ctx context.Context, tx *sql.Tx, workspaceID, id string) (*ContactAutomation, error)
GetContactAutomationByEmail(ctx context.Context, workspaceID, automationID, email string) (*ContactAutomation, error)
ListContactAutomations(ctx context.Context, workspaceID string, filter ContactAutomationFilter) ([]*ContactAutomation, int, error)
UpdateContactAutomation(ctx context.Context, workspaceID string, ca *ContactAutomation) error
UpdateContactAutomationTx(ctx context.Context, tx *sql.Tx, workspaceID string, ca *ContactAutomation) error
GetScheduledContactAutomations(ctx context.Context, workspaceID string, beforeTime time.Time, limit int) ([]*ContactAutomation, error)
// Global scheduling (across all workspaces with round-robin)
GetScheduledContactAutomationsGlobal(ctx context.Context, beforeTime time.Time, limit int) ([]*ContactAutomationWithWorkspace, error)
// Node execution logging
CreateNodeExecution(ctx context.Context, workspaceID string, entry *NodeExecution) error
CreateNodeExecutionTx(ctx context.Context, tx *sql.Tx, workspaceID string, entry *NodeExecution) error
GetNodeExecutions(ctx context.Context, workspaceID, contactAutomationID string) ([]*NodeExecution, error)
UpdateNodeExecution(ctx context.Context, workspaceID string, entry *NodeExecution) error
UpdateNodeExecutionTx(ctx context.Context, tx *sql.Tx, workspaceID string, entry *NodeExecution) error
// Stats
UpdateAutomationStats(ctx context.Context, workspaceID, automationID string, stats *AutomationStats) error
UpdateAutomationStatsTx(ctx context.Context, tx *sql.Tx, workspaceID, automationID string, stats *AutomationStats) error
IncrementAutomationStat(ctx context.Context, workspaceID, automationID, statName string) error
}
AutomationRepository defines the interface for automation persistence
type AutomationService ¶
type AutomationService interface {
// CRUD (nodes are embedded in automation)
Create(ctx context.Context, workspaceID string, automation *Automation) error
Get(ctx context.Context, workspaceID, automationID string) (*Automation, error)
List(ctx context.Context, workspaceID string, filter AutomationFilter) ([]*Automation, int, error)
Update(ctx context.Context, workspaceID string, automation *Automation) error
Delete(ctx context.Context, workspaceID, automationID string) error
// Status management
Activate(ctx context.Context, workspaceID, automationID string) error
Pause(ctx context.Context, workspaceID, automationID string) error
// Node executions/debugging
GetContactNodeExecutions(ctx context.Context, workspaceID, automationID, email string) (*ContactAutomation, []*NodeExecution, error)
}
AutomationService defines the interface for automation business logic
type AutomationStats ¶
type AutomationStats struct {
Enrolled int64 `json:"enrolled"`
Completed int64 `json:"completed"`
Exited int64 `json:"exited"`
Failed int64 `json:"failed"`
}
AutomationStats holds statistics for an automation
type AutomationStatus ¶
type AutomationStatus string
AutomationStatus represents the status of an automation
const ( AutomationStatusDraft AutomationStatus = "draft" AutomationStatusLive AutomationStatus = "live" AutomationStatusPaused AutomationStatus = "paused" )
func (AutomationStatus) IsValid ¶
func (s AutomationStatus) IsValid() bool
IsValid checks if the automation status is valid
type BatchImportContactsRequest ¶
type BatchImportContactsRequest struct {
WorkspaceID string `json:"workspace_id" valid:"required"`
Contacts json.RawMessage `json:"contacts" valid:"required"`
SubscribeToLists []string `json:"subscribe_to_lists,omitempty"` // Optional: subscribe contacts to these lists
}
Add the request type for batch importing contacts
type BatchImportContactsResponse ¶
type BatchImportContactsResponse struct {
Operations []*UpsertContactOperation `json:"operations"`
Error string `json:"error,omitempty"`
}
type BlogAuthor ¶
BlogAuthor represents an author of a blog post
type BlogCategory ¶
type BlogCategory struct {
ID string `json:"id"`
Slug string `json:"slug"` // URL identifier
Settings BlogCategorySettings `json:"settings"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
BlogCategory represents a blog category
func (*BlogCategory) Validate ¶
func (c *BlogCategory) Validate() error
Validate validates the blog category
type BlogCategoryListResponse ¶
type BlogCategoryListResponse struct {
Categories []*BlogCategory `json:"categories"`
TotalCount int `json:"total_count"`
}
BlogCategoryListResponse defines the response for listing blog categories
type BlogCategoryRepository ¶
type BlogCategoryRepository interface {
CreateCategory(ctx context.Context, category *BlogCategory) error
GetCategory(ctx context.Context, id string) (*BlogCategory, error)
GetCategoryBySlug(ctx context.Context, slug string) (*BlogCategory, error)
GetCategoriesByIDs(ctx context.Context, ids []string) ([]*BlogCategory, error)
UpdateCategory(ctx context.Context, category *BlogCategory) error
DeleteCategory(ctx context.Context, id string) error
ListCategories(ctx context.Context) ([]*BlogCategory, error)
// Transaction management
WithTransaction(ctx context.Context, workspaceID string, fn func(*sql.Tx) error) error
CreateCategoryTx(ctx context.Context, tx *sql.Tx, category *BlogCategory) error
GetCategoryTx(ctx context.Context, tx *sql.Tx, id string) (*BlogCategory, error)
GetCategoryBySlugTx(ctx context.Context, tx *sql.Tx, slug string) (*BlogCategory, error)
UpdateCategoryTx(ctx context.Context, tx *sql.Tx, category *BlogCategory) error
DeleteCategoryTx(ctx context.Context, tx *sql.Tx, id string) error
}
BlogCategoryRepository defines the data access layer for blog categories
type BlogCategorySettings ¶
type BlogCategorySettings struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
SEO *SEOSettings `json:"seo,omitempty"` // SEO metadata
}
BlogCategorySettings contains the settings for a blog category
func (*BlogCategorySettings) Scan ¶
func (s *BlogCategorySettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type BlogPost ¶
type BlogPost struct {
ID string `json:"id"`
CategoryID string `json:"category_id"`
Slug string `json:"slug"` // URL identifier
Settings BlogPostSettings `json:"settings"`
PublishedAt *time.Time `json:"published_at,omitempty"` // null = draft
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
BlogPost represents a blog post
func (*BlogPost) GetEffectiveSEOSettings ¶
func (p *BlogPost) GetEffectiveSEOSettings(category *BlogCategory) *SEOSettings
GetEffectiveSEOSettings merges the post's SEO settings with the category's defaults
func (*BlogPost) IsPublished ¶
IsPublished returns true if the post is published
type BlogPostListResponse ¶
type BlogPostListResponse struct {
Posts []*BlogPost `json:"posts"`
TotalCount int `json:"total_count"`
CurrentPage int `json:"current_page"`
TotalPages int `json:"total_pages"`
HasNextPage bool `json:"has_next_page"`
HasPreviousPage bool `json:"has_previous_page"`
}
BlogPostListResponse defines the response for listing blog posts
type BlogPostRepository ¶
type BlogPostRepository interface {
CreatePost(ctx context.Context, post *BlogPost) error
GetPost(ctx context.Context, id string) (*BlogPost, error)
GetPostBySlug(ctx context.Context, slug string) (*BlogPost, error)
GetPostByCategoryAndSlug(ctx context.Context, categorySlug, postSlug string) (*BlogPost, error)
UpdatePost(ctx context.Context, post *BlogPost) error
DeletePost(ctx context.Context, id string) error
ListPosts(ctx context.Context, params ListBlogPostsRequest) (*BlogPostListResponse, error)
PublishPost(ctx context.Context, id string, publishedAt *time.Time) error
UnpublishPost(ctx context.Context, id string) error
// Transaction management
WithTransaction(ctx context.Context, workspaceID string, fn func(*sql.Tx) error) error
CreatePostTx(ctx context.Context, tx *sql.Tx, post *BlogPost) error
GetPostTx(ctx context.Context, tx *sql.Tx, id string) (*BlogPost, error)
GetPostBySlugTx(ctx context.Context, tx *sql.Tx, slug string) (*BlogPost, error)
UpdatePostTx(ctx context.Context, tx *sql.Tx, post *BlogPost) error
DeletePostTx(ctx context.Context, tx *sql.Tx, id string) error
DeletePostsByCategoryIDTx(ctx context.Context, tx *sql.Tx, categoryID string) (int64, error)
PublishPostTx(ctx context.Context, tx *sql.Tx, id string, publishedAt *time.Time) error
UnpublishPostTx(ctx context.Context, tx *sql.Tx, id string) error
}
BlogPostRepository defines the data access layer for blog posts
type BlogPostSettings ¶
type BlogPostSettings struct {
Title string `json:"title"` // H1 displayed on page
Template BlogPostTemplateReference `json:"template"`
Excerpt string `json:"excerpt,omitempty"`
FeaturedImageURL string `json:"featured_image_url,omitempty"`
Authors []BlogAuthor `json:"authors"`
ReadingTimeMinutes int `json:"reading_time_minutes"`
SEO *SEOSettings `json:"seo,omitempty"` // SEO metadata
}
BlogPostSettings contains the settings for a blog post
func (*BlogPostSettings) Scan ¶
func (s *BlogPostSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type BlogPostStatus ¶
type BlogPostStatus string
BlogPostStatus represents the status filter for listing posts
const ( BlogPostStatusAll BlogPostStatus = "all" BlogPostStatusDraft BlogPostStatus = "draft" BlogPostStatusPublished BlogPostStatus = "published" )
type BlogPostTemplateReference ¶
type BlogPostTemplateReference struct {
TemplateID string `json:"template_id"`
TemplateVersion int `json:"template_version"`
}
BlogPostTemplateReference contains template information for a blog post
type BlogRenderError ¶
type BlogRenderError struct {
Code string // Error code for handler mapping
Message string // Human-readable message
Details error // Underlying error
}
BlogRenderError represents a structured error for blog page rendering
func (*BlogRenderError) Error ¶
func (e *BlogRenderError) Error() string
type BlogService ¶
type BlogService interface {
// Category operations
CreateCategory(ctx context.Context, request *CreateBlogCategoryRequest) (*BlogCategory, error)
GetCategory(ctx context.Context, id string) (*BlogCategory, error)
GetCategoryBySlug(ctx context.Context, slug string) (*BlogCategory, error)
UpdateCategory(ctx context.Context, request *UpdateBlogCategoryRequest) (*BlogCategory, error)
DeleteCategory(ctx context.Context, request *DeleteBlogCategoryRequest) error
ListCategories(ctx context.Context) (*BlogCategoryListResponse, error)
// Post operations
CreatePost(ctx context.Context, request *CreateBlogPostRequest) (*BlogPost, error)
GetPost(ctx context.Context, id string) (*BlogPost, error)
GetPostBySlug(ctx context.Context, slug string) (*BlogPost, error)
GetPostByCategoryAndSlug(ctx context.Context, categorySlug, postSlug string) (*BlogPost, error)
UpdatePost(ctx context.Context, request *UpdateBlogPostRequest) (*BlogPost, error)
DeletePost(ctx context.Context, request *DeleteBlogPostRequest) error
ListPosts(ctx context.Context, params *ListBlogPostsRequest) (*BlogPostListResponse, error)
PublishPost(ctx context.Context, request *PublishBlogPostRequest) error
UnpublishPost(ctx context.Context, request *UnpublishBlogPostRequest) error
// Public operations (no auth required)
GetPublicCategoryBySlug(ctx context.Context, slug string) (*BlogCategory, error)
GetPublicPostByCategoryAndSlug(ctx context.Context, categorySlug, postSlug string) (*BlogPost, error)
ListPublicPosts(ctx context.Context, params *ListBlogPostsRequest) (*BlogPostListResponse, error)
// Theme operations
CreateTheme(ctx context.Context, request *CreateBlogThemeRequest) (*BlogTheme, error)
GetTheme(ctx context.Context, version int) (*BlogTheme, error)
GetPublishedTheme(ctx context.Context) (*BlogTheme, error)
UpdateTheme(ctx context.Context, request *UpdateBlogThemeRequest) (*BlogTheme, error)
PublishTheme(ctx context.Context, request *PublishBlogThemeRequest) error
ListThemes(ctx context.Context, params *ListBlogThemesRequest) (*BlogThemeListResponse, error)
// Blog page rendering (public, no auth // Rendering
RenderHomePage(ctx context.Context, workspaceID string, page int, themeVersion *int) (string, error)
RenderPostPage(ctx context.Context, workspaceID, categorySlug, postSlug string, themeVersion *int) (string, error)
RenderCategoryPage(ctx context.Context, workspaceID, categorySlug string, page int, themeVersion *int) (string, error)
}
BlogService defines the business logic layer for blog operations
type BlogSettings ¶
type BlogSettings struct {
Title string `json:"title,omitempty"`
LogoURL *string `json:"logo_url,omitempty"`
IconURL *string `json:"icon_url,omitempty"`
SEO *SEOSettings `json:"seo,omitempty"`
HomePageSize int `json:"home_page_size,omitempty"` // Posts per page on home (default: 20)
CategoryPageSize int `json:"category_page_size,omitempty"` // Posts per page on category (default: 20)
}
BlogSettings contains blog title and SEO configuration
func (*BlogSettings) GetCategoryPageSize ¶
func (bs *BlogSettings) GetCategoryPageSize() int
GetCategoryPageSize returns the category page size with validation and default
func (*BlogSettings) GetHomePageSize ¶
func (bs *BlogSettings) GetHomePageSize() int
GetHomePageSize returns the home page size with validation and default
func (*BlogSettings) Scan ¶
func (b *BlogSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type BlogTemplateDataRequest ¶
type BlogTemplateDataRequest struct {
Workspace *Workspace
Post *BlogPost // Optional, for post pages
Category *BlogCategory // Optional, for category pages
PublicLists []*List // Always included (empty array if none)
Posts []*BlogPost // For listings (home/category pages)
Categories []*BlogCategory // For navigation
ThemeVersion int // Theme version number for cache-busting
CustomData MapOfAny // Optional additional data
PaginationData *BlogPostListResponse // Pagination metadata (optional, for paginated pages)
}
BlogTemplateDataRequest groups parameters for building blog template data Similar to TemplateDataRequest for email templates
type BlogTheme ¶
type BlogTheme struct {
Version int `json:"version"`
PublishedAt *time.Time `json:"published_at,omitempty"` // non-null = published
PublishedByUserID *string `json:"published_by_user_id,omitempty"` // user who published this theme
Files BlogThemeFiles `json:"files"`
Notes *string `json:"notes,omitempty"` // optional notes/description for this version
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
BlogTheme represents a blog theme with versioned Liquid template files
func (*BlogTheme) IsPublished ¶
IsPublished returns true if the theme is published
type BlogThemeFileType ¶
type BlogThemeFileType string
BlogThemeFileType represents the type of blog theme file
const ( BlogThemeFileTypeHome BlogThemeFileType = "home" BlogThemeFileTypeCategory BlogThemeFileType = "category" BlogThemeFileTypePost BlogThemeFileType = "post" BlogThemeFileTypeHeader BlogThemeFileType = "header" )
type BlogThemeFiles ¶
type BlogThemeFiles struct {
HomeLiquid string `json:"home.liquid"`
CategoryLiquid string `json:"category.liquid"`
PostLiquid string `json:"post.liquid"`
HeaderLiquid string `json:"header.liquid"`
StylesCSS string `json:"styles.css"`
ScriptsJS string `json:"scripts.js"`
}
BlogThemeFiles contains Liquid template files and CSS for a blog theme
func (*BlogThemeFiles) Scan ¶
func (f *BlogThemeFiles) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type BlogThemeListResponse ¶
type BlogThemeListResponse struct {
Themes []*BlogTheme `json:"themes"`
TotalCount int `json:"total_count"`
}
BlogThemeListResponse defines the response for listing blog themes
type BlogThemeRepository ¶
type BlogThemeRepository interface {
CreateTheme(ctx context.Context, theme *BlogTheme) error
GetTheme(ctx context.Context, version int) (*BlogTheme, error)
GetPublishedTheme(ctx context.Context) (*BlogTheme, error)
UpdateTheme(ctx context.Context, theme *BlogTheme) error
PublishTheme(ctx context.Context, version int, publishedByUserID string) error
ListThemes(ctx context.Context, params ListBlogThemesRequest) (*BlogThemeListResponse, error)
// Transaction management
WithTransaction(ctx context.Context, workspaceID string, fn func(*sql.Tx) error) error
CreateThemeTx(ctx context.Context, tx *sql.Tx, theme *BlogTheme) error
GetThemeTx(ctx context.Context, tx *sql.Tx, version int) (*BlogTheme, error)
GetPublishedThemeTx(ctx context.Context, tx *sql.Tx) (*BlogTheme, error)
UpdateThemeTx(ctx context.Context, tx *sql.Tx, theme *BlogTheme) error
PublishThemeTx(ctx context.Context, tx *sql.Tx, version int, publishedByUserID string) error
}
BlogThemeRepository defines the data access layer for blog themes
type BranchNodeConfig ¶
type BranchNodeConfig struct {
Paths []BranchPath `json:"paths"`
DefaultPathID string `json:"default_path_id"`
}
BranchNodeConfig configures a branch node
type BranchPath ¶
type BranchPath struct {
ID string `json:"id"`
Name string `json:"name"`
Conditions *TreeNode `json:"conditions"`
NextNodeID string `json:"next_node_id"`
}
BranchPath represents a branch path in a branch node
type Broadcast ¶
type Broadcast struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
Name string `json:"name"`
ChannelType string `json:"channel_type"` // email, sms, push, etc.
Status BroadcastStatus `json:"status"` // pending, sending, completed, failed
Audience AudienceSettings `json:"audience"`
Schedule ScheduleSettings `json:"schedule"`
TestSettings BroadcastTestSettings `json:"test_settings"`
UTMParameters *UTMParameters `json:"utm_parameters,omitempty"`
Metadata MapOfAny `json:"metadata,omitempty"`
WinningTemplate *string `json:"winning_template,omitempty"`
TestSentAt *time.Time `json:"test_sent_at,omitempty"`
WinnerSentAt *time.Time `json:"winner_sent_at,omitempty"`
TestPhaseRecipientCount int `json:"test_phase_recipient_count"`
WinnerPhaseRecipientCount int `json:"winner_phase_recipient_count"`
EnqueuedCount int `json:"enqueued_count"` // Emails added to queue
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
StartedAt *time.Time `json:"started_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CancelledAt *time.Time `json:"cancelled_at,omitempty"`
PausedAt *time.Time `json:"paused_at,omitempty"`
PauseReason *string `json:"pause_reason,omitempty"`
}
Broadcast represents a broadcast message campaign
func (*Broadcast) SetTemplateForVariation ¶
SetTemplateForVariation assigns a template to a specific variation
type BroadcastListResponse ¶
type BroadcastListResponse struct {
Broadcasts []*Broadcast `json:"broadcasts"`
TotalCount int `json:"total_count"`
}
BroadcastListResponse defines the response for listing broadcasts
type BroadcastRepository ¶
type BroadcastRepository interface {
CreateBroadcast(ctx context.Context, broadcast *Broadcast) error
GetBroadcast(ctx context.Context, workspaceID, broadcastID string) (*Broadcast, error)
UpdateBroadcast(ctx context.Context, broadcast *Broadcast) error
DeleteBroadcast(ctx context.Context, workspaceID, broadcastID string) error
ListBroadcasts(ctx context.Context, params ListBroadcastsParams) (*BroadcastListResponse, error)
// Transaction management
WithTransaction(ctx context.Context, workspaceID string, fn func(*sql.Tx) error) error
// Transaction-aware methods
CreateBroadcastTx(ctx context.Context, tx *sql.Tx, broadcast *Broadcast) error
GetBroadcastTx(ctx context.Context, tx *sql.Tx, workspaceID, broadcastID string) (*Broadcast, error)
UpdateBroadcastTx(ctx context.Context, tx *sql.Tx, broadcast *Broadcast) error
DeleteBroadcastTx(ctx context.Context, tx *sql.Tx, workspaceID, broadcastID string) error
ListBroadcastsTx(ctx context.Context, tx *sql.Tx, params ListBroadcastsParams) (*BroadcastListResponse, error)
}
BroadcastRepository defines the data access layer for broadcasts
type BroadcastSender ¶
type BroadcastSender interface {
GetBroadcast(ctx context.Context, workspaceID, broadcastID string) (*Broadcast, error)
GetTemplateByID(ctx context.Context, workspaceID, templateID string) (*Template, error)
// Message history tracking methods
RecordMessageSent(ctx context.Context, workspaceID string, message *MessageHistory) error
UpdateMessageStatus(ctx context.Context, workspaceID string, messageID string, event MessageEvent, timestamp time.Time) error
}
BroadcastSender is a minimal interface needed for sending broadcasts, used by task processors to avoid circular dependencies
type BroadcastService ¶
type BroadcastService interface {
// CreateBroadcast creates a new broadcast
CreateBroadcast(ctx context.Context, request *CreateBroadcastRequest) (*Broadcast, error)
// GetBroadcast retrieves a broadcast by ID
GetBroadcast(ctx context.Context, workspaceID, id string) (*Broadcast, error)
// UpdateBroadcast updates an existing broadcast
UpdateBroadcast(ctx context.Context, request *UpdateBroadcastRequest) (*Broadcast, error)
// ListBroadcasts retrieves a list of broadcasts with pagination
ListBroadcasts(ctx context.Context, params ListBroadcastsParams) (*BroadcastListResponse, error)
// ScheduleBroadcast schedules a broadcast for sending
ScheduleBroadcast(ctx context.Context, request *ScheduleBroadcastRequest) error
// PauseBroadcast pauses a sending broadcast
PauseBroadcast(ctx context.Context, request *PauseBroadcastRequest) error
// ResumeBroadcast resumes a paused broadcast
ResumeBroadcast(ctx context.Context, request *ResumeBroadcastRequest) error
// CancelBroadcast cancels a scheduled broadcast
CancelBroadcast(ctx context.Context, request *CancelBroadcastRequest) error
// DeleteBroadcast deletes a broadcast
DeleteBroadcast(ctx context.Context, request *DeleteBroadcastRequest) error
// SendToIndividual sends a broadcast to an individual recipient
SendToIndividual(ctx context.Context, request *SendToIndividualRequest) error
// GetTestResults retrieves A/B test results for a broadcast
GetTestResults(ctx context.Context, workspaceID, broadcastID string) (*TestResultsResponse, error)
// SelectWinner manually selects the winning variation for an A/B test
SelectWinner(ctx context.Context, workspaceID, broadcastID, templateID string) error
}
BroadcastService defines the interface for broadcast operations
type BroadcastStatus ¶
type BroadcastStatus string
BroadcastStatus defines the current status of a broadcast
const ( BroadcastStatusDraft BroadcastStatus = "draft" BroadcastStatusScheduled BroadcastStatus = "scheduled" BroadcastStatusProcessing BroadcastStatus = "processing" // Orchestrator is enqueueing emails BroadcastStatusPaused BroadcastStatus = "paused" BroadcastStatusProcessed BroadcastStatus = "processed" // Enqueueing complete BroadcastStatusCancelled BroadcastStatus = "cancelled" BroadcastStatusFailed BroadcastStatus = "failed" BroadcastStatusTesting BroadcastStatus = "testing" // A/B test in progress BroadcastStatusTestCompleted BroadcastStatus = "test_completed" // Test done, awaiting winner selection BroadcastStatusWinnerSelected BroadcastStatus = "winner_selected" // Winner chosen, enqueueing to remaining )
type BroadcastTestSettings ¶
type BroadcastTestSettings struct {
Enabled bool `json:"enabled"`
SamplePercentage int `json:"sample_percentage"`
AutoSendWinner bool `json:"auto_send_winner"`
AutoSendWinnerMetric TestWinnerMetric `json:"auto_send_winner_metric,omitempty"`
TestDurationHours int `json:"test_duration_hours,omitempty"`
Variations []BroadcastVariation `json:"variations"`
}
BroadcastTestSettings contains configuration for A/B testing
func (*BroadcastTestSettings) Scan ¶
func (b *BroadcastTestSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type BroadcastVariation ¶
type BroadcastVariation struct {
VariationName string `json:"variation_name"`
TemplateID string `json:"template_id"`
Metrics *VariationMetrics `json:"metrics,omitempty"`
// joined servers-side
Template *Template `json:"template,omitempty"`
}
BroadcastVariation represents a single variation in an A/B test
func (*BroadcastVariation) Scan ¶
func (v *BroadcastVariation) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type BuildSegmentState ¶
type BuildSegmentState struct {
SegmentID string `json:"segment_id"`
Version int64 `json:"version"`
TotalContacts int `json:"total_contacts"`
ProcessedCount int `json:"processed_count"`
MatchedCount int `json:"matched_count"`
ContactOffset int64 `json:"contact_offset"` // For resumable processing
BatchSize int `json:"batch_size"` // Process 1000 at a time
StartedAt string `json:"started_at"`
}
BuildSegmentState contains state specific to segment building tasks
type BulkUpsertResult ¶
ContactRepository is the interface for contact operations BulkUpsertResult represents the result of a single contact upsert operation in a bulk operation
type CancelBroadcastRequest ¶
type CancelBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
CancelBroadcastRequest defines the request to cancel a scheduled broadcast
func (*CancelBroadcastRequest) Validate ¶
func (r *CancelBroadcastRequest) Validate() error
Validate validates the cancel broadcast request
type ChannelOptions ¶
type ChannelOptions struct {
// Email-specific options
FromName *string `json:"from_name,omitempty"`
CC []string `json:"cc,omitempty"`
BCC []string `json:"bcc,omitempty"`
ReplyTo string `json:"reply_to,omitempty"`
}
ChannelOptions represents channel-specific delivery options This structure allows future extension for SMS/push without breaking changes
func (*ChannelOptions) Scan ¶
func (co *ChannelOptions) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database retrieval
type ChannelTemplate ¶
type ChannelTemplate struct {
TemplateID string `json:"template_id"`
Settings MapOfAny `json:"settings,omitempty"`
}
ChannelTemplate represents template configuration for a specific channel
type ChannelTemplates ¶
type ChannelTemplates map[TransactionalChannel]ChannelTemplate
ChannelTemplates maps channels to their template configurations
func (*ChannelTemplates) Scan ¶
func (ct *ChannelTemplates) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database retrieval
type CompileTemplateRequest ¶
type CompileTemplateRequest = notifuse_mjml.CompileTemplateRequest
Use types from notifuse_mjml package
type CompileTemplateResponse ¶
type CompileTemplateResponse = notifuse_mjml.CompileTemplateResponse
type Contact ¶
type Contact struct {
// Required fields
Email string `json:"email" valid:"required,email"`
// Optional fields
ExternalID *NullableString `json:"external_id,omitempty" valid:"optional"`
Timezone *NullableString `json:"timezone,omitempty" valid:"optional,timezone"`
Language *NullableString `json:"language,omitempty" valid:"optional"`
FirstName *NullableString `json:"first_name,omitempty" valid:"optional"`
LastName *NullableString `json:"last_name,omitempty" valid:"optional"`
FullName *NullableString `json:"full_name,omitempty" valid:"optional"`
Phone *NullableString `json:"phone,omitempty" valid:"optional"`
AddressLine1 *NullableString `json:"address_line_1,omitempty" valid:"optional"`
AddressLine2 *NullableString `json:"address_line_2,omitempty" valid:"optional"`
Country *NullableString `json:"country,omitempty" valid:"optional"`
Postcode *NullableString `json:"postcode,omitempty" valid:"optional"`
State *NullableString `json:"state,omitempty" valid:"optional"`
JobTitle *NullableString `json:"job_title,omitempty" valid:"optional"`
// Custom fields
CustomString1 *NullableString `json:"custom_string_1,omitempty" valid:"optional"`
CustomString2 *NullableString `json:"custom_string_2,omitempty" valid:"optional"`
CustomString3 *NullableString `json:"custom_string_3,omitempty" valid:"optional"`
CustomString4 *NullableString `json:"custom_string_4,omitempty" valid:"optional"`
CustomString5 *NullableString `json:"custom_string_5,omitempty" valid:"optional"`
CustomNumber1 *NullableFloat64 `json:"custom_number_1,omitempty" valid:"optional"`
CustomNumber2 *NullableFloat64 `json:"custom_number_2,omitempty" valid:"optional"`
CustomNumber3 *NullableFloat64 `json:"custom_number_3,omitempty" valid:"optional"`
CustomNumber4 *NullableFloat64 `json:"custom_number_4,omitempty" valid:"optional"`
CustomNumber5 *NullableFloat64 `json:"custom_number_5,omitempty" valid:"optional"`
CustomDatetime1 *NullableTime `json:"custom_datetime_1,omitempty" valid:"optional"`
CustomDatetime2 *NullableTime `json:"custom_datetime_2,omitempty" valid:"optional"`
CustomDatetime3 *NullableTime `json:"custom_datetime_3,omitempty" valid:"optional"`
CustomDatetime4 *NullableTime `json:"custom_datetime_4,omitempty" valid:"optional"`
CustomDatetime5 *NullableTime `json:"custom_datetime_5,omitempty" valid:"optional"`
CustomJSON1 *NullableJSON `json:"custom_json_1,omitempty" valid:"optional"`
CustomJSON2 *NullableJSON `json:"custom_json_2,omitempty" valid:"optional"`
CustomJSON3 *NullableJSON `json:"custom_json_3,omitempty" valid:"optional"`
CustomJSON4 *NullableJSON `json:"custom_json_4,omitempty" valid:"optional"`
CustomJSON5 *NullableJSON `json:"custom_json_5,omitempty" valid:"optional"`
// Timestamps
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Database timestamps for internal tracking (not exposed via JSON)
DBCreatedAt time.Time `json:"-"`
DBUpdatedAt time.Time `json:"-"`
// Join contact_lists
ContactLists []*ContactList `json:"contact_lists"`
// Join contact_segments
ContactSegments []*ContactSegment `json:"contact_segments"`
// Not persisted
EmailHMAC string `json:"email_hmac,omitempty"`
}
Contact represents a contact in the system
func FromJSON ¶
FromJSON parses JSON data into a Contact struct The JSON data can be provided as a []byte or as a gjson.Result
func ScanContact ¶
ScanContact scans a contact from the database
func (*Contact) MergeContactLists ¶
func (c *Contact) MergeContactLists(list *ContactList)
MergeContactLists merges a new contact list into the contact's existing lists
func (*Contact) ToMapOfAny ¶
ToMapOfAny converts the contact to a MapOfAny using JSON marshal/unmarshal This is useful for template rendering or API responses
type ContactAutomation ¶
type ContactAutomation struct {
ID string `json:"id"`
AutomationID string `json:"automation_id"`
ContactEmail string `json:"contact_email"`
CurrentNodeID *string `json:"current_node_id,omitempty"`
Status ContactAutomationStatus `json:"status"`
ExitReason *string `json:"exit_reason,omitempty"` // Why contact exited: completed, filter_rejected, automation_node_deleted, manual, unsubscribed
EnteredAt time.Time `json:"entered_at"`
ScheduledAt *time.Time `json:"scheduled_at,omitempty"`
Context map[string]interface{} `json:"context,omitempty"`
RetryCount int `json:"retry_count"`
LastError *string `json:"last_error,omitempty"`
LastRetryAt *time.Time `json:"last_retry_at,omitempty"`
MaxRetries int `json:"max_retries"`
}
ContactAutomation tracks a contact's journey through an automation
func (*ContactAutomation) Validate ¶
func (ca *ContactAutomation) Validate() error
Validate validates the contact automation
type ContactAutomationFilter ¶
type ContactAutomationFilter struct {
AutomationID string
ContactEmail string
Status []ContactAutomationStatus
ScheduledBy *time.Time // Get contacts scheduled before this time
Limit int
Offset int
}
ContactAutomationFilter defines filtering options for listing contact automations
type ContactAutomationStatus ¶
type ContactAutomationStatus string
ContactAutomationStatus represents the status of a contact's journey in an automation
const ( ContactAutomationStatusActive ContactAutomationStatus = "active" ContactAutomationStatusCompleted ContactAutomationStatus = "completed" ContactAutomationStatusExited ContactAutomationStatus = "exited" ContactAutomationStatusFailed ContactAutomationStatus = "failed" )
func (ContactAutomationStatus) IsValid ¶
func (s ContactAutomationStatus) IsValid() bool
IsValid checks if the contact automation status is valid
type ContactAutomationWithWorkspace ¶
type ContactAutomationWithWorkspace struct {
WorkspaceID string
ContactAutomation
}
ContactAutomationWithWorkspace includes workspace ID for global processing
type ContactCondition ¶
type ContactCondition struct {
Filters []*DimensionFilter `json:"filters"`
}
ContactCondition represents filters on the contacts table
func (*ContactCondition) Validate ¶
func (c *ContactCondition) Validate() error
Validate validates contact conditions
type ContactList ¶
type ContactList struct {
Email string `json:"email"`
ListID string `json:"list_id"`
ListName string `json:"list_name"`
Status ContactListStatus `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at"`
}
ContactList represents the relationship between a contact and a list
func ScanContactList ¶
func ScanContactList(scanner interface {
Scan(dest ...interface{}) error
}) (*ContactList, error)
ScanContactList scans a contact list from the database
func (*ContactList) Validate ¶
func (cl *ContactList) Validate() error
Validate performs validation on the contact list fields
type ContactListCondition ¶
type ContactListCondition struct {
Operator string `json:"operator"` // "in" or "not_in"
ListID string `json:"list_id"`
Status *string `json:"status,omitempty"`
}
ContactListCondition represents membership conditions for contact lists
func (*ContactListCondition) Validate ¶
func (c *ContactListCondition) Validate() error
Validate validates contact list conditions
type ContactListRepository ¶
type ContactListRepository interface {
// AddContactToList adds a contact to a list
AddContactToList(ctx context.Context, workspaceID string, contactList *ContactList) error
// BulkAddContactsToLists adds multiple contacts to multiple lists in a single operation
BulkAddContactsToLists(ctx context.Context, workspaceID string, emails []string, listIDs []string, status ContactListStatus) error
// GetContactListByIDs retrieves a contact list by email and list ID
GetContactListByIDs(ctx context.Context, workspaceID string, email, listID string) (*ContactList, error)
// GetContactsByListID retrieves all contacts for a list
GetContactsByListID(ctx context.Context, workspaceID string, listID string) ([]*ContactList, error)
// GetListsByEmail retrieves all lists for a contact
GetListsByEmail(ctx context.Context, workspaceID string, email string) ([]*ContactList, error)
// UpdateContactListStatus updates the status of a contact on a list
UpdateContactListStatus(ctx context.Context, workspaceID string, email, listID string, status ContactListStatus) error
// RemoveContactFromList removes a contact from a list
RemoveContactFromList(ctx context.Context, workspaceID string, email, listID string) error
// DeleteForEmail deletes all contact list relationships for a specific email
DeleteForEmail(ctx context.Context, workspaceID, email string) error
}
type ContactListService ¶
type ContactListService interface {
// GetContactListByIDs retrieves a contact list by email and list ID
GetContactListByIDs(ctx context.Context, workspaceID string, email, listID string) (*ContactList, error)
// GetContactsByListID retrieves all contacts for a list
GetContactsByListID(ctx context.Context, workspaceID string, listID string) ([]*ContactList, error)
// GetListsByEmail retrieves all lists for a contact
GetListsByEmail(ctx context.Context, workspaceID string, email string) ([]*ContactList, error)
// UpdateContactListStatus updates the status of a contact on a list
UpdateContactListStatus(ctx context.Context, workspaceID string, email, listID string, status ContactListStatus) (*UpdateContactListStatusResult, error)
// RemoveContactFromList removes a contact from a list
RemoveContactFromList(ctx context.Context, workspaceID string, email, listID string) error
}
ContactListService provides operations for managing contact list relationships
type ContactListStatus ¶
type ContactListStatus string
ContactListStatus represents the status of a contact's subscription to a list
const ( // ContactListStatusActive indicates an active subscription ContactListStatusActive ContactListStatus = "active" // ContactListStatusPending indicates a pending subscription (e.g., waiting for double opt-in) ContactListStatusPending ContactListStatus = "pending" // ContactListStatusUnsubscribed indicates an unsubscribed status ContactListStatusUnsubscribed ContactListStatus = "unsubscribed" // ContactListStatusBounced indicates the contact's email has bounced ContactListStatusBounced ContactListStatus = "bounced" // ContactListStatusComplained indicates the contact has complained (e.g., marked as spam) ContactListStatusComplained ContactListStatus = "complained" )
type ContactPreferencesResponse ¶
type ContactPreferencesResponse struct {
Contact *Contact `json:"contact"`
PublicLists []*List `json:"public_lists"`
ContactLists []*ContactList `json:"contact_lists"`
LogoURL string `json:"logo_url"`
WebsiteURL string `json:"website_url"`
}
ContactPreferencesResponse contains the response data for the notification center
type ContactRepository ¶
type ContactRepository interface {
// GetContactByEmail retrieves a contact by email
GetContactByEmail(ctx context.Context, workspaceID, email string) (*Contact, error)
// GetContactByExternalID retrieves a contact by external ID
GetContactByExternalID(ctx context.Context, workspaceID string, externalID string) (*Contact, error)
// GetContacts retrieves contacts with filtering and pagination
GetContacts(ctx context.Context, req *GetContactsRequest) (*GetContactsResponse, error)
// DeleteContact deletes a contact
DeleteContact(ctx context.Context, workspaceID string, email string) error
// UpsertContact creates or updates a contact
UpsertContact(ctx context.Context, workspaceID string, contact *Contact) (bool, error)
// BulkUpsertContacts creates or updates multiple contacts in a single operation
BulkUpsertContacts(ctx context.Context, workspaceID string, contacts []*Contact) ([]BulkUpsertResult, error)
// GetContactsForBroadcast retrieves contacts based on broadcast audience settings
// Uses cursor-based pagination: afterEmail is the last email from the previous batch (empty for first batch)
GetContactsForBroadcast(ctx context.Context, workspaceID string, audience AudienceSettings, limit int, afterEmail string) ([]*ContactWithList, error)
// CountContactsForBroadcast counts contacts based on broadcast audience settings
CountContactsForBroadcast(ctx context.Context, workspaceID string, audience AudienceSettings) (int, error)
// Count returns the total number of contacts in a workspace
Count(ctx context.Context, workspaceID string) (int, error)
// GetBatchForSegment retrieves a batch of email addresses for segment processing
GetBatchForSegment(ctx context.Context, workspaceID string, offset int64, limit int) ([]string, error)
}
type ContactSegment ¶
type ContactSegment struct {
Email string `json:"email"`
SegmentID string `json:"segment_id"`
Version int64 `json:"version"`
MatchedAt time.Time `json:"matched_at"`
ComputedAt time.Time `json:"computed_at"`
}
ContactSegment represents the relationship between a contact and a segment
type ContactSegmentQueueItem ¶
type ContactSegmentQueueItem struct {
Email string `json:"email"`
QueuedAt time.Time `json:"queued_at"`
}
ContactSegmentQueueItem represents a contact that needs segment recomputation
type ContactSegmentQueueRepository ¶
type ContactSegmentQueueRepository interface {
// GetPendingEmails retrieves emails that need segment recomputation
GetPendingEmails(ctx context.Context, workspaceID string, limit int) ([]string, error)
// RemoveFromQueue removes an email from the queue after processing
RemoveFromQueue(ctx context.Context, workspaceID string, email string) error
// RemoveBatchFromQueue removes multiple emails from the queue
RemoveBatchFromQueue(ctx context.Context, workspaceID string, emails []string) error
// GetQueueSize returns the number of contacts in the queue
GetQueueSize(ctx context.Context, workspaceID string) (int, error)
// ClearQueue removes all items from the queue
ClearQueue(ctx context.Context, workspaceID string) error
}
ContactSegmentQueueRepository defines the interface for contact segment queue operations
type ContactService ¶
type ContactService interface {
// GetContactByEmail retrieves a contact by email
GetContactByEmail(ctx context.Context, workspaceID string, email string) (*Contact, error)
// GetContactByExternalID retrieves a contact by external ID
GetContactByExternalID(ctx context.Context, workspaceID string, externalID string) (*Contact, error)
// GetContacts retrieves contacts with filters and pagination
GetContacts(ctx context.Context, req *GetContactsRequest) (*GetContactsResponse, error)
// DeleteContact deletes a contact by email
DeleteContact(ctx context.Context, workspaceID string, email string) error
// BatchImportContacts imports a batch of contacts (create or update)
BatchImportContacts(ctx context.Context, workspaceID string, contacts []*Contact, listIDs []string) *BatchImportContactsResponse
// UpsertContact creates a new contact or updates an existing one
UpsertContact(ctx context.Context, workspaceID string, contact *Contact) UpsertContactOperation
// CountContacts returns the total number of contacts in a workspace
CountContacts(ctx context.Context, workspaceID string) (int, error)
}
ContactService provides operations for managing contacts
type ContactTimelineCondition ¶
type ContactTimelineCondition struct {
Kind string `json:"kind"` // Timeline event kind
CountOperator string `json:"count_operator"` // "at_least", "at_most", "exactly"
CountValue int `json:"count_value"`
TimeframeOperator *string `json:"timeframe_operator,omitempty"` // "anytime", "in_date_range", "before_date", "after_date", "in_the_last_days"
TimeframeValues []string `json:"timeframe_values,omitempty"`
Filters []*DimensionFilter `json:"filters,omitempty"`
}
ContactTimelineCondition represents conditions on contact timeline events
func (*ContactTimelineCondition) Validate ¶
func (c *ContactTimelineCondition) Validate() error
Validate validates contact timeline conditions
type ContactTimelineEntry ¶
type ContactTimelineEntry struct {
ID string `json:"id"`
Email string `json:"email"`
Operation string `json:"operation"` // 'insert', 'update', 'delete'
EntityType string `json:"entity_type"` // 'contact', 'contact_list', 'message_history'
Kind string `json:"kind"` // operation_entityType (e.g., 'insert_contact', 'update_message_history')
Changes map[string]interface{} `json:"changes"`
EntityID *string `json:"entity_id,omitempty"` // NULL for contact, list_id for contact_list, message_id for message_history
EntityData map[string]interface{} `json:"entity_data,omitempty"` // Joined entity data (contact, list, or message details)
CreatedAt time.Time `json:"created_at"` // Can be set to historical data
DBCreatedAt time.Time `json:"db_created_at"` // Timestamp when record was inserted into database
}
ContactTimelineEntry represents a timeline entry for a contact
type ContactTimelineRepository ¶
type ContactTimelineRepository interface {
// Create inserts a new timeline entry
Create(ctx context.Context, workspaceID string, entry *ContactTimelineEntry) error
// List retrieves timeline entries for a contact
List(ctx context.Context, workspaceID string, email string, limit int, cursor *string) ([]*ContactTimelineEntry, *string, error)
// DeleteForEmail deletes all timeline entries for a contact
DeleteForEmail(ctx context.Context, workspaceID string, email string) error
}
ContactTimelineRepository defines methods for contact timeline persistence
type ContactTimelineService ¶
type ContactTimelineService interface {
// List retrieves timeline entries for a contact with pagination
List(ctx context.Context, workspaceID string, email string, limit int, cursor *string) ([]*ContactTimelineEntry, *string, error)
}
ContactTimelineService defines business logic for contact timeline
type ContactWithList ¶
type ContactWithList struct {
Contact *Contact `json:"contact"` // The contact
ListID string `json:"list_id"` // ID of the list that the contact belongs to
ListName string `json:"list_name"` // Name of the list that the contact belongs to
}
ContactWithList represents a contact with information about which list it belongs to
type ContextKey ¶
type ContextKey string
const SystemCallKey ContextKey = "system_call"
const WorkspaceIDKey ContextKey = "workspace_id"
WorkspaceIDKey is the context key for workspace ID
type CreateAPIKeyRequest ¶
type CreateAPIKeyRequest struct {
WorkspaceID string `json:"workspace_id"`
EmailPrefix string `json:"email_prefix"`
}
CreateAPIKeyRequest defines the request structure for creating an API key
func (*CreateAPIKeyRequest) Validate ¶
func (r *CreateAPIKeyRequest) Validate() error
Validate validates the create API key request
type CreateAutomationRequest ¶
type CreateAutomationRequest struct {
WorkspaceID string `json:"workspace_id"`
Automation *Automation `json:"automation"`
}
CreateAutomationRequest represents the request to create an automation
func (*CreateAutomationRequest) Validate ¶
func (r *CreateAutomationRequest) Validate() error
Validate validates the create automation request
type CreateBlogCategoryRequest ¶
type CreateBlogCategoryRequest struct {
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description,omitempty"`
SEO *SEOSettings `json:"seo,omitempty"`
}
CreateBlogCategoryRequest defines the request to create a blog category
func (*CreateBlogCategoryRequest) Validate ¶
func (r *CreateBlogCategoryRequest) Validate() error
Validate validates the create blog category request
type CreateBlogPostRequest ¶
type CreateBlogPostRequest struct {
CategoryID string `json:"category_id"`
Slug string `json:"slug"`
Title string `json:"title"`
TemplateID string `json:"template_id"`
TemplateVersion int `json:"template_version"`
Excerpt string `json:"excerpt,omitempty"`
FeaturedImageURL string `json:"featured_image_url,omitempty"`
Authors []BlogAuthor `json:"authors"`
ReadingTimeMinutes int `json:"reading_time_minutes"`
SEO *SEOSettings `json:"seo,omitempty"`
}
CreateBlogPostRequest defines the request to create a blog post
func (*CreateBlogPostRequest) Validate ¶
func (r *CreateBlogPostRequest) Validate() error
Validate validates the create blog post request
type CreateBlogThemeRequest ¶
type CreateBlogThemeRequest struct {
Files BlogThemeFiles `json:"files"`
Notes *string `json:"notes,omitempty"`
}
CreateBlogThemeRequest defines the request to create a blog theme
func (*CreateBlogThemeRequest) Validate ¶
func (r *CreateBlogThemeRequest) Validate() error
Validate validates the create blog theme request
type CreateBroadcastRequest ¶
type CreateBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
Name string `json:"name"`
Audience AudienceSettings `json:"audience"`
TestSettings BroadcastTestSettings `json:"test_settings"`
TrackingEnabled bool `json:"tracking_enabled"`
UTMParameters *UTMParameters `json:"utm_parameters,omitempty"`
Metadata MapOfAny `json:"metadata,omitempty"`
}
CreateBroadcastRequest defines the request to create a new broadcast. Note: Scheduling must be done via the ScheduleBroadcastRequest after creation.
func (*CreateBroadcastRequest) Validate ¶
func (r *CreateBroadcastRequest) Validate() (*Broadcast, error)
Validate validates the create broadcast request
type CreateIntegrationRequest ¶
type CreateIntegrationRequest struct {
WorkspaceID string `json:"workspace_id"`
Name string `json:"name"`
Type IntegrationType `json:"type"`
Provider EmailProvider `json:"provider,omitempty"` // For email integrations
SupabaseSettings *SupabaseIntegrationSettings `json:"supabase_settings,omitempty"` // For Supabase integrations
LLMProvider *LLMProvider `json:"llm_provider,omitempty"` // For LLM integrations
FirecrawlSettings *FirecrawlSettings `json:"firecrawl_settings,omitempty"` // For Firecrawl integrations
}
CreateIntegrationRequest defines the request structure for creating an integration
func (*CreateIntegrationRequest) Validate ¶
func (r *CreateIntegrationRequest) Validate(passphrase string) error
type CreateListRequest ¶
type CreateListRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
IsDoubleOptin bool `json:"is_double_optin"`
IsPublic bool `json:"is_public"`
Description string `json:"description,omitempty"`
DoubleOptInTemplate *TemplateReference `json:"double_optin_template,omitempty"`
}
Request/Response types
type CreateSegmentRequest ¶
type CreateSegmentRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
Tree *TreeNode `json:"tree"`
Timezone string `json:"timezone"`
}
Request/Response types
type CreateTaskRequest ¶
type CreateTaskRequest struct {
WorkspaceID string `json:"workspace_id"`
Type string `json:"type"`
State *TaskState `json:"state,omitempty"` // New typed state struct
MaxRuntime int `json:"max_runtime"`
MaxRetries int `json:"max_retries"`
RetryInterval int `json:"retry_interval"`
NextRunAfter *time.Time `json:"next_run_after,omitempty"`
}
CreateTaskRequest defines the request to create a new task
func (*CreateTaskRequest) Validate ¶
func (r *CreateTaskRequest) Validate() (*Task, error)
Validate validates the create task request
type CreateTemplateBlockRequest ¶
type CreateTemplateBlockRequest struct {
WorkspaceID string `json:"workspace_id"`
Name string `json:"name"`
Block notifuse_mjml.EmailBlock `json:"block"`
}
CreateTemplateBlockRequest defines the request structure for creating a template block
func (*CreateTemplateBlockRequest) UnmarshalJSON ¶
func (r *CreateTemplateBlockRequest) UnmarshalJSON(data []byte) error
UnmarshalJSON implements custom JSON unmarshaling for CreateTemplateBlockRequest
func (*CreateTemplateBlockRequest) Validate ¶
func (r *CreateTemplateBlockRequest) Validate() (block *TemplateBlock, workspaceID string, err error)
Validate validates the create template block request
type CreateTemplateRequest ¶
type CreateTemplateRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
Channel string `json:"channel"`
Email *EmailTemplate `json:"email,omitempty"`
Web *WebTemplate `json:"web,omitempty"`
Category string `json:"category"`
TemplateMacroID *string `json:"template_macro_id,omitempty"`
TestData MapOfAny `json:"test_data,omitempty"`
Settings MapOfAny `json:"settings,omitempty"`
}
Request/Response types
type CreateTransactionalRequest ¶
type CreateTransactionalRequest struct {
WorkspaceID string `json:"workspace_id"`
Notification TransactionalNotificationCreateParams `json:"notification"`
}
CreateTransactionalRequest represents a request to create a transactional notification
func (*CreateTransactionalRequest) Validate ¶
func (req *CreateTransactionalRequest) Validate() error
Validate validates the create request
type CreateWorkspaceRequest ¶
type CreateWorkspaceRequest struct {
ID string `json:"id"`
Name string `json:"name"`
Settings WorkspaceSettings `json:"settings"`
}
func (*CreateWorkspaceRequest) Validate ¶
func (r *CreateWorkspaceRequest) Validate(passphrase string) error
type CustomEvent ¶
type CustomEvent struct {
ExternalID string `json:"external_id"` // Primary key: external system's unique ID
Email string `json:"email"`
EventName string `json:"event_name"` // Generic: "shopify.order", "stripe.payment"
Properties map[string]interface{} `json:"properties"` // Current state of the resource
OccurredAt time.Time `json:"occurred_at"` // When this version was created
Source string `json:"source"` // "api", "integration", "import"
IntegrationID *string `json:"integration_id,omitempty"` // Optional integration ID
// Goal tracking fields
GoalName *string `json:"goal_name,omitempty"` // Optional goal name for categorization
GoalType *string `json:"goal_type,omitempty"` // purchase, subscription, lead, signup, booking, trial, other
GoalValue *float64 `json:"goal_value,omitempty"` // Monetary value (required for purchase/subscription, can be negative for refunds)
// Soft delete
DeletedAt *time.Time `json:"deleted_at,omitempty"` // Soft delete timestamp
// Timestamps
CreatedAt time.Time `json:"created_at"` // When first inserted
UpdatedAt time.Time `json:"updated_at"` // When last updated
}
CustomEvent represents the current state of an external resource Note: ExternalID is the primary key and represents the unique identifier from the external system (e.g., "shopify_order_12345", "stripe_pi_abc123")
func (*CustomEvent) IsDeleted ¶
func (e *CustomEvent) IsDeleted() bool
IsDeleted returns true if the event has been soft-deleted
func (*CustomEvent) Validate ¶
func (e *CustomEvent) Validate() error
Validate validates the custom event
type CustomEventFilters ¶
type CustomEventFilters struct {
GoalTypes []string `json:"goal_types,omitempty"` // Filter by goal_type enum
EventNames []string `json:"event_names,omitempty"` // Filter by event_name
}
CustomEventFilters defines filters for custom event subscriptions
type CustomEventRepository ¶
type CustomEventRepository interface {
Upsert(ctx context.Context, workspaceID string, event *CustomEvent) error
BatchUpsert(ctx context.Context, workspaceID string, events []*CustomEvent) error
GetByID(ctx context.Context, workspaceID, eventName, externalID string) (*CustomEvent, error)
ListByEmail(ctx context.Context, workspaceID, email string, limit int, offset int) ([]*CustomEvent, error)
ListByEventName(ctx context.Context, workspaceID, eventName string, limit int, offset int) ([]*CustomEvent, error)
DeleteForEmail(ctx context.Context, workspaceID, email string) error
}
CustomEventRepository defines persistence methods
type CustomEventService ¶
type CustomEventService interface {
UpsertEvent(ctx context.Context, req *UpsertCustomEventRequest) (*CustomEvent, error)
ImportEvents(ctx context.Context, req *ImportCustomEventsRequest) ([]string, error)
GetEvent(ctx context.Context, workspaceID, eventName, externalID string) (*CustomEvent, error)
ListEvents(ctx context.Context, req *ListCustomEventsRequest) ([]*CustomEvent, error)
}
CustomEventService defines business logic
type CustomEventsGoalCondition ¶
type CustomEventsGoalCondition struct {
GoalType string `json:"goal_type"` // purchase, subscription, lead, signup, booking, trial, other, or "*" for all
GoalName *string `json:"goal_name,omitempty"` // Optional filter by goal name
AggregateOperator string `json:"aggregate_operator"` // sum, count, avg, min, max
Operator string `json:"operator"` // gte, lte, eq, between
Value float64 `json:"value"`
Value2 *float64 `json:"value_2,omitempty"` // For between operator
TimeframeOperator string `json:"timeframe_operator"` // anytime, in_the_last_days, in_date_range, before_date, after_date
TimeframeValues []string `json:"timeframe_values,omitempty"`
}
CustomEventsGoalCondition represents conditions on goal aggregations from custom_events Used for segmentation based on LTV, transaction counts, etc.
func (*CustomEventsGoalCondition) Validate ¶
func (g *CustomEventsGoalCondition) Validate() error
Validate validates custom events goal conditions
type DelayNodeConfig ¶
type DelayNodeConfig struct {
Duration int `json:"duration"`
Unit string `json:"unit"` // "minutes", "hours", "days"
}
DelayNodeConfig configures a delay node
func (DelayNodeConfig) Validate ¶
func (c DelayNodeConfig) Validate() error
Validate validates the delay node config
type DeleteAutomationRequest ¶
type DeleteAutomationRequest struct {
WorkspaceID string `json:"workspace_id"`
AutomationID string `json:"automation_id"`
}
DeleteAutomationRequest represents the request to delete an automation
func (*DeleteAutomationRequest) Validate ¶
func (r *DeleteAutomationRequest) Validate() error
Validate validates the delete automation request
type DeleteBlogCategoryRequest ¶
type DeleteBlogCategoryRequest struct {
ID string `json:"id"`
}
DeleteBlogCategoryRequest defines the request to delete a blog category
func (*DeleteBlogCategoryRequest) Validate ¶
func (r *DeleteBlogCategoryRequest) Validate() error
Validate validates the delete blog category request
type DeleteBlogPostRequest ¶
type DeleteBlogPostRequest struct {
ID string `json:"id"`
}
DeleteBlogPostRequest defines the request to delete a blog post
func (*DeleteBlogPostRequest) Validate ¶
func (r *DeleteBlogPostRequest) Validate() error
Validate validates the delete blog post request
type DeleteBroadcastRequest ¶
type DeleteBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
DeleteBroadcastRequest defines the request to delete a broadcast
func (*DeleteBroadcastRequest) Validate ¶
func (r *DeleteBroadcastRequest) Validate() error
Validate validates the delete broadcast request
type DeleteContactRequest ¶
type DeleteContactRequest struct {
WorkspaceID string `json:"workspace_id" valid:"required"`
Email string `json:"email" valid:"required,email"`
}
func (*DeleteContactRequest) Validate ¶
func (r *DeleteContactRequest) Validate() error
type DeleteIntegrationRequest ¶
type DeleteIntegrationRequest struct {
WorkspaceID string `json:"workspace_id"`
IntegrationID string `json:"integration_id"`
}
DeleteIntegrationRequest defines the request structure for deleting an integration
func (*DeleteIntegrationRequest) Validate ¶
func (r *DeleteIntegrationRequest) Validate() error
type DeleteListRequest ¶
func (*DeleteListRequest) Validate ¶
func (r *DeleteListRequest) Validate() (workspaceID string, err error)
type DeleteSegmentRequest ¶
type DeleteTaskRequest ¶
DeleteTaskRequest defines the request to delete a task
func (*DeleteTaskRequest) FromURLParams ¶
func (r *DeleteTaskRequest) FromURLParams(values url.Values) error
FromURLParams parses URL query parameters into the request
type DeleteTemplateBlockRequest ¶
type DeleteTemplateBlockRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
DeleteTemplateBlockRequest defines the request structure for deleting a template block
type DeleteTemplateRequest ¶
type DeleteTransactionalRequest ¶
type DeleteTransactionalRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
DeleteTransactionalRequest represents a request to delete a transactional notification
func (*DeleteTransactionalRequest) Validate ¶
func (req *DeleteTransactionalRequest) Validate() error
Validate validates the delete request
type DeleteWorkspaceRequest ¶
type DeleteWorkspaceRequest struct {
ID string `json:"id"`
}
func (*DeleteWorkspaceRequest) Validate ¶
func (r *DeleteWorkspaceRequest) Validate() error
type DimensionFilter ¶
type DimensionFilter struct {
FieldName string `json:"field_name"`
FieldType string `json:"field_type"` // "string", "number", "time", "json"
Operator string `json:"operator"` // "equals", "not_equals", "gt", "gte", "lt", "lte", "contains", etc.
StringValues []string `json:"string_values,omitempty"`
NumberValues []float64 `json:"number_values,omitempty"`
// JSON-specific field for navigating nested JSON structures
// Each element is either a key name or a numeric index (as string)
// Example: ["user", "tags", "0"] represents user.tags[0]
JSONPath []string `json:"json_path,omitempty"`
}
DimensionFilter represents a single filter condition on a field
func (*DimensionFilter) Validate ¶
func (f *DimensionFilter) Validate() error
Validate validates a dimension filter
type EmailEventType ¶
type EmailEventType string
EmailEventType defines the type of email webhook event
const ( // EmailEventDelivered indicates a successful email delivery EmailEventDelivered EmailEventType = "delivered" // EmailEventBounce indicates a bounced email EmailEventBounce EmailEventType = "bounce" // EmailEventComplaint indicates a complaint was filed for the email EmailEventComplaint EmailEventType = "complaint" // EmailEventAuthEmail indicates a Supabase auth email webhook EmailEventAuthEmail EmailEventType = "auth_email" // EmailEventBeforeUserCreated indicates a Supabase before user created webhook EmailEventBeforeUserCreated EmailEventType = "before_user_created" )
type EmailNodeConfig ¶
type EmailNodeConfig struct {
TemplateID string `json:"template_id"`
SubjectOverride *string `json:"subject_override,omitempty"`
FromOverride *string `json:"from_override,omitempty"`
}
EmailNodeConfig configures an email node
func (EmailNodeConfig) Validate ¶
func (c EmailNodeConfig) Validate() error
Validate validates the email node config
type EmailOptions ¶
type EmailOptions struct {
FromName *string `json:"from_name,omitempty"` // Override default sender from name
CC []string `json:"cc,omitempty"`
BCC []string `json:"bcc,omitempty"`
ReplyTo string `json:"reply_to,omitempty"`
Attachments []Attachment `json:"attachments,omitempty"`
ListUnsubscribeURL string `json:"list_unsubscribe_url,omitempty"` // RFC-8058 one-click unsubscribe URL
}
func (EmailOptions) IsEmpty ¶
func (eo EmailOptions) IsEmpty() bool
IsEmpty returns true if no email options are set
func (EmailOptions) ToChannelOptions ¶
func (eo EmailOptions) ToChannelOptions() *ChannelOptions
ToChannelOptions converts EmailOptions to ChannelOptions for storage
type EmailProvider ¶
type EmailProvider struct {
Kind EmailProviderKind `json:"kind"`
SES *AmazonSESSettings `json:"ses,omitempty"`
SMTP *SMTPSettings `json:"smtp,omitempty"`
SparkPost *SparkPostSettings `json:"sparkpost,omitempty"`
Postmark *PostmarkSettings `json:"postmark,omitempty"`
Mailgun *MailgunSettings `json:"mailgun,omitempty"`
Mailjet *MailjetSettings `json:"mailjet,omitempty"`
Senders []EmailSender `json:"senders"`
RateLimitPerMinute int `json:"rate_limit_per_minute"`
}
EmailProvider contains configuration for an email service provider
func (*EmailProvider) DecryptSecretKeys ¶
func (e *EmailProvider) DecryptSecretKeys(passphrase string) error
DecryptSecretKeys decrypts all encrypted secret keys in the email provider
func (*EmailProvider) EncryptSecretKeys ¶
func (e *EmailProvider) EncryptSecretKeys(passphrase string) error
EncryptSecretKeys encrypts all secret keys in the email provider
func (*EmailProvider) GetSender ¶
func (e *EmailProvider) GetSender(id string) *EmailSender
func (*EmailProvider) Validate ¶
func (e *EmailProvider) Validate(passphrase string) error
Validate validates the email provider settings
type EmailProviderKind ¶
type EmailProviderKind string
EmailProviderKind defines the type of email provider
const ( EmailProviderKindSMTP EmailProviderKind = "smtp" EmailProviderKindSES EmailProviderKind = "ses" EmailProviderKindSparkPost EmailProviderKind = "sparkpost" EmailProviderKindPostmark EmailProviderKind = "postmark" EmailProviderKindMailgun EmailProviderKind = "mailgun" EmailProviderKindMailjet EmailProviderKind = "mailjet" )
type EmailProviderService ¶
type EmailProviderService interface {
SendEmail(ctx context.Context, request SendEmailProviderRequest) error
}
type EmailQueueEntry ¶
type EmailQueueEntry struct {
ID string `json:"id"`
Status EmailQueueStatus `json:"status"`
Priority int `json:"priority"`
SourceType EmailQueueSourceType `json:"source_type"`
SourceID string `json:"source_id"` // BroadcastID or AutomationID
IntegrationID string `json:"integration_id"`
ProviderKind EmailProviderKind `json:"provider_kind"`
// Email identification
ContactEmail string `json:"contact_email"`
MessageID string `json:"message_id"`
TemplateID string `json:"template_id"`
// Serialized payload for sending (contains all data needed to send)
Payload EmailQueuePayload `json:"payload"`
// Retry tracking
Attempts int `json:"attempts"`
MaxAttempts int `json:"max_attempts"`
LastError *string `json:"last_error,omitempty"`
NextRetryAt *time.Time `json:"next_retry_at,omitempty"`
// Timestamps
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ProcessedAt *time.Time `json:"processed_at,omitempty"`
}
EmailQueueEntry represents a single email in the queue
type EmailQueuePayload ¶
type EmailQueuePayload struct {
// Email content (compiled and ready to send)
FromAddress string `json:"from_address"`
FromName string `json:"from_name"`
Subject string `json:"subject"`
HTMLContent string `json:"html_content"`
// Options
EmailOptions EmailOptions `json:"email_options"`
// Provider configuration (rate limit needed for worker)
RateLimitPerMinute int `json:"rate_limit_per_minute"`
// Provider settings (encrypted, will be decrypted by worker)
ProviderSettings map[string]interface{} `json:"provider_settings"`
// Message history tracking fields
TemplateVersion int `json:"template_version"` // Needed for message_history
ListID string `json:"list_id,omitempty"` // For broadcasts
TemplateData map[string]interface{} `json:"template_data,omitempty"` // For message history logging
}
EmailQueuePayload contains all data needed to send the email This is stored as JSONB in the database
func (*EmailQueuePayload) ToSendEmailProviderRequest ¶
func (p *EmailQueuePayload) ToSendEmailProviderRequest(workspaceID, integrationID, messageID, toEmail string, provider *EmailProvider) *SendEmailProviderRequest
ToSendEmailProviderRequest converts the payload to a SendEmailProviderRequest The provider must be passed in separately as it's not stored in the payload
type EmailQueueRepository ¶
type EmailQueueRepository interface {
// Enqueue adds emails to the queue
Enqueue(ctx context.Context, workspaceID string, entries []*EmailQueueEntry) error
// EnqueueTx adds emails to the queue within an existing transaction
EnqueueTx(ctx context.Context, tx *sql.Tx, entries []*EmailQueueEntry) error
// FetchPending retrieves pending emails for processing
// Uses FOR UPDATE SKIP LOCKED to allow concurrent workers
// Orders by priority ASC (lower = higher priority), then created_at ASC
FetchPending(ctx context.Context, workspaceID string, limit int) ([]*EmailQueueEntry, error)
// MarkAsProcessing atomically marks an entry as processing
MarkAsProcessing(ctx context.Context, workspaceID string, id string) error
// MarkAsSent deletes the entry after successful send
// (entries are removed immediately rather than marked with a "sent" status)
MarkAsSent(ctx context.Context, workspaceID string, id string) error
// MarkAsFailed marks an entry as failed and schedules retry
MarkAsFailed(ctx context.Context, workspaceID string, id string, errorMsg string, nextRetryAt *time.Time) error
// Delete removes a queue entry (used when max retries exhausted)
Delete(ctx context.Context, workspaceID string, entryID string) error
// SetNextRetry updates next_retry_at WITHOUT incrementing attempts
// Used by circuit breaker to schedule retry without burning retry attempts
SetNextRetry(ctx context.Context, workspaceID string, entryID string, nextRetry time.Time) error
// GetStats returns queue statistics for a workspace
GetStats(ctx context.Context, workspaceID string) (*EmailQueueStats, error)
// GetBySourceID retrieves queue entries by source type and ID
// Useful for tracking broadcast/automation progress
GetBySourceID(ctx context.Context, workspaceID string, sourceType EmailQueueSourceType, sourceID string) ([]*EmailQueueEntry, error)
// CountBySourceAndStatus counts entries by source and status
CountBySourceAndStatus(ctx context.Context, workspaceID string, sourceType EmailQueueSourceType, sourceID string, status EmailQueueStatus) (int64, error)
}
EmailQueueRepository defines data access for the email queue
type EmailQueueSourceType ¶
type EmailQueueSourceType string
EmailQueueSourceType identifies the origin of the queued email
const ( EmailQueueSourceBroadcast EmailQueueSourceType = "broadcast" EmailQueueSourceAutomation EmailQueueSourceType = "automation" )
type EmailQueueStats ¶
type EmailQueueStats struct {
Pending int64 `json:"pending"`
Processing int64 `json:"processing"`
Failed int64 `json:"failed"`
}
EmailQueueStats provides queue statistics for a workspace
type EmailQueueStatus ¶
type EmailQueueStatus string
EmailQueueStatus represents the status of a queued email
const ( EmailQueueStatusPending EmailQueueStatus = "pending" EmailQueueStatusProcessing EmailQueueStatus = "processing" EmailQueueStatusFailed EmailQueueStatus = "failed" )
type EmailSender ¶
type EmailSender struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
IsDefault bool `json:"is_default"`
}
EmailSender represents an email sender with name and email address
func NewEmailSender ¶
func NewEmailSender(email, name string) EmailSender
NewEmailSender creates a new sender with the given email and name
type EmailServiceInterface ¶
type EmailServiceInterface interface {
TestEmailProvider(ctx context.Context, workspaceID string, provider EmailProvider, to string) error
SendEmail(ctx context.Context, request SendEmailProviderRequest, isMarketing bool) error
SendEmailForTemplate(ctx context.Context, request SendEmailRequest) error
VisitLink(ctx context.Context, messageID string, workspaceID string) error
OpenEmail(ctx context.Context, messageID string, workspaceID string) error
}
EmailServiceInterface defines the interface for the email service
type EmailTemplate ¶
type EmailTemplate struct {
SenderID string `json:"sender_id,omitempty"`
ReplyTo string `json:"reply_to,omitempty"`
Subject string `json:"subject"`
SubjectPreview *string `json:"subject_preview,omitempty"`
CompiledPreview string `json:"compiled_preview"` // compiled html
VisualEditorTree notifuse_mjml.EmailBlock `json:"visual_editor_tree"`
Text *string `json:"text,omitempty"`
}
func (EmailTemplate) MarshalJSON ¶
func (x EmailTemplate) MarshalJSON() ([]byte, error)
MarshalJSON implements custom JSON marshaling for EmailTemplate
func (*EmailTemplate) Scan ¶
func (x *EmailTemplate) Scan(val interface{}) error
func (*EmailTemplate) UnmarshalJSON ¶
func (x *EmailTemplate) UnmarshalJSON(data []byte) error
UnmarshalJSON implements custom JSON unmarshaling for EmailTemplate
func (*EmailTemplate) Validate ¶
func (e *EmailTemplate) Validate(testData MapOfAny) error
type ErrBroadcastNotFound ¶
type ErrBroadcastNotFound struct {
ID string
}
ErrBroadcastNotFound is an error type for when a broadcast is not found
func (*ErrBroadcastNotFound) Error ¶
func (e *ErrBroadcastNotFound) Error() string
Error returns the error message
type ErrContactListNotFound ¶
type ErrContactListNotFound struct {
Message string
}
ErrContactListNotFound is returned when a contact list is not found
func (*ErrContactListNotFound) Error ¶
func (e *ErrContactListNotFound) Error() string
type ErrInboundWebhookEventNotFound ¶
type ErrInboundWebhookEventNotFound struct {
ID string
}
ErrInboundWebhookEventNotFound is returned when an inbound webhook event is not found
func (*ErrInboundWebhookEventNotFound) Error ¶
func (e *ErrInboundWebhookEventNotFound) Error() string
Error returns the error message
type ErrListNotFound ¶
type ErrListNotFound struct {
Message string
}
ErrListNotFound is returned when a list is not found
func (*ErrListNotFound) Error ¶
func (e *ErrListNotFound) Error() string
type ErrNotFound ¶
Common error types
func (*ErrNotFound) Error ¶
func (e *ErrNotFound) Error() string
type ErrSegmentNotFound ¶
type ErrSegmentNotFound struct {
Message string
}
ErrSegmentNotFound is returned when a segment is not found
func (*ErrSegmentNotFound) Error ¶
func (e *ErrSegmentNotFound) Error() string
type ErrSessionNotFound ¶
type ErrSessionNotFound struct {
Message string
}
ErrSessionNotFound is returned when a session is not found
func (*ErrSessionNotFound) Error ¶
func (e *ErrSessionNotFound) Error() string
type ErrSettingNotFound ¶
type ErrSettingNotFound struct {
Key string
}
ErrSettingNotFound is returned when a setting is not found
func (*ErrSettingNotFound) Error ¶
func (e *ErrSettingNotFound) Error() string
type ErrTaskAlreadyRunning ¶
type ErrTaskAlreadyRunning struct {
TaskID string
}
ErrTaskAlreadyRunning is returned when attempting to execute a task that is already running
func (*ErrTaskAlreadyRunning) Error ¶
func (e *ErrTaskAlreadyRunning) Error() string
type ErrTaskExecution ¶
Task-specific errors
func (*ErrTaskExecution) Error ¶
func (e *ErrTaskExecution) Error() string
func (*ErrTaskExecution) Unwrap ¶
func (e *ErrTaskExecution) Unwrap() error
type ErrTaskTimeout ¶
func (*ErrTaskTimeout) Error ¶
func (e *ErrTaskTimeout) Error() string
type ErrTemplateBlockNotFound ¶
type ErrTemplateBlockNotFound struct {
Message string
}
ErrTemplateBlockNotFound is returned when a template block is not found
func (*ErrTemplateBlockNotFound) Error ¶
func (e *ErrTemplateBlockNotFound) Error() string
type ErrTemplateNotFound ¶
type ErrTemplateNotFound struct {
Message string
}
ErrTemplateNotFound is returned when a template is not found
func (*ErrTemplateNotFound) Error ¶
func (e *ErrTemplateNotFound) Error() string
type ErrUnauthorized ¶
type ErrUnauthorized struct {
}
ErrUnauthorized is returned when a user is not authorized to perform an action
func (*ErrUnauthorized) Error ¶
func (e *ErrUnauthorized) Error() string
type ErrUserExists ¶
type ErrUserExists struct {
Message string
}
ErrUserExists is returned when trying to create a user that already exists
func (*ErrUserExists) Error ¶
func (e *ErrUserExists) Error() string
type ErrUserNotFound ¶
type ErrUserNotFound struct {
Message string
}
ErrUserNotFound is returned when a user is not found
func (*ErrUserNotFound) Error ¶
func (e *ErrUserNotFound) Error() string
type ErrWorkspaceNotFound ¶
type ErrWorkspaceNotFound struct {
WorkspaceID string
}
ErrWorkspaceNotFound is returned when a workspace is not found
func (*ErrWorkspaceNotFound) Error ¶
func (e *ErrWorkspaceNotFound) Error() string
type EventAckCallback ¶
type EventAckCallback func(err error)
EventAckCallback is a function that's called after an event is processed to acknowledge success or failure
type EventBus ¶
type EventBus interface {
// Publish sends an event to all subscribers
Publish(ctx context.Context, event EventPayload)
// PublishWithAck sends an event to all subscribers and calls the acknowledgment callback
// when all subscribers have processed the event or if an error occurs
PublishWithAck(ctx context.Context, event EventPayload, callback EventAckCallback)
// Subscribe registers a handler for a specific event type
Subscribe(eventType EventType, handler EventHandler)
// Unsubscribe removes a handler for an event type
Unsubscribe(eventType EventType, handler EventHandler)
}
EventBus provides a way for services to publish and subscribe to events
type EventHandler ¶
type EventHandler func(ctx context.Context, payload EventPayload)
EventHandler is a function that handles events
type EventPayload ¶
type EventPayload struct {
Type EventType `json:"type"`
WorkspaceID string `json:"workspace_id"`
EntityID string `json:"entity_id"`
Data map[string]interface{} `json:"data,omitempty"`
}
EventPayload represents the data associated with an event
type EventType ¶
type EventType string
EventType defines the type of an event
const ( EventBroadcastScheduled EventType = "broadcast.scheduled" EventBroadcastPaused EventType = "broadcast.paused" EventBroadcastResumed EventType = "broadcast.resumed" EventBroadcastSent EventType = "broadcast.sent" EventBroadcastFailed EventType = "broadcast.failed" EventBroadcastCancelled EventType = "broadcast.cancelled" EventBroadcastCircuitBreaker EventType = "broadcast.circuit_breaker" )
Define event types
type ExecutePendingTasksRequest ¶
type ExecutePendingTasksRequest struct {
MaxTasks int `json:"max_tasks,omitempty"`
}
ExecutePendingTasksRequest defines the request to execute pending tasks
func (*ExecutePendingTasksRequest) FromURLParams ¶
func (r *ExecutePendingTasksRequest) FromURLParams(values url.Values) error
FromURLParams parses URL query parameters into the request
type ExecuteTaskRequest ¶
ExecuteTaskRequest defines the request to execute a specific task
func (*ExecuteTaskRequest) Validate ¶
func (r *ExecuteTaskRequest) Validate() error
Validate validates the execute task request
type FileManagerSettings ¶
type FileManagerSettings struct {
Provider string `json:"provider,omitempty"`
Endpoint string `json:"endpoint"`
Bucket string `json:"bucket"`
AccessKey string `json:"access_key"`
EncryptedSecretKey string `json:"encrypted_secret_key,omitempty"`
Region *string `json:"region,omitempty"`
CDNEndpoint *string `json:"cdn_endpoint,omitempty"`
ForcePathStyle bool `json:"force_path_style"`
// decoded secret key, not stored in the database
SecretKey string `json:"secret_key,omitempty"`
}
func (*FileManagerSettings) DecryptSecretKey ¶
func (f *FileManagerSettings) DecryptSecretKey(passphrase string) error
func (*FileManagerSettings) EncryptSecretKey ¶
func (f *FileManagerSettings) EncryptSecretKey(passphrase string) error
func (*FileManagerSettings) Validate ¶
func (f *FileManagerSettings) Validate(passphrase string) error
type FilterNodeConfig ¶
type FilterNodeConfig struct {
Description string `json:"description,omitempty"`
Conditions *TreeNode `json:"conditions"`
ContinueNodeID string `json:"continue_node_id"`
ExitNodeID string `json:"exit_node_id"`
}
FilterNodeConfig configures a filter node
type FirecrawlSettings ¶
type FirecrawlSettings struct {
EncryptedAPIKey string `json:"encrypted_api_key,omitempty"`
BaseURL string `json:"base_url,omitempty"` // Optional, for self-hosted
// Decoded API key, not stored in the database
APIKey string `json:"api_key,omitempty"`
}
FirecrawlSettings contains configuration for Firecrawl integration
func (*FirecrawlSettings) DecryptAPIKey ¶
func (f *FirecrawlSettings) DecryptAPIKey(passphrase string) error
DecryptAPIKey decrypts the encrypted API key
func (*FirecrawlSettings) DecryptSecretKeys ¶
func (f *FirecrawlSettings) DecryptSecretKeys(passphrase string) error
DecryptSecretKeys decrypts all secret keys (wrapper for integration compatibility)
func (*FirecrawlSettings) EncryptAPIKey ¶
func (f *FirecrawlSettings) EncryptAPIKey(passphrase string) error
EncryptAPIKey encrypts the API key
func (*FirecrawlSettings) EncryptSecretKeys ¶
func (f *FirecrawlSettings) EncryptSecretKeys(passphrase string) error
EncryptSecretKeys encrypts all secret keys (wrapper for integration compatibility)
func (*FirecrawlSettings) GetBaseURL ¶
func (f *FirecrawlSettings) GetBaseURL() string
GetBaseURL returns the API base URL (default or custom)
func (*FirecrawlSettings) Validate ¶
func (f *FirecrawlSettings) Validate(passphrase string) error
Validate validates the Firecrawl settings and encrypts API key
type GetAutomationRequest ¶
type GetAutomationRequest struct {
WorkspaceID string `json:"workspace_id"`
AutomationID string `json:"automation_id"`
}
GetAutomationRequest represents the request to get an automation
func (*GetAutomationRequest) FromURLParams ¶
func (r *GetAutomationRequest) FromURLParams(params map[string][]string) error
FromURLParams parses the request from URL parameters
func (*GetAutomationRequest) Validate ¶
func (r *GetAutomationRequest) Validate() error
Validate validates the get automation request
type GetBlogCategoryRequest ¶
type GetBlogCategoryRequest struct {
ID string `json:"id,omitempty"`
Slug string `json:"slug,omitempty"`
}
GetBlogCategoryRequest defines the request to get a blog category
func (*GetBlogCategoryRequest) Validate ¶
func (r *GetBlogCategoryRequest) Validate() error
Validate validates the get blog category request
type GetBlogPostRequest ¶
type GetBlogPostRequest struct {
ID string `json:"id,omitempty"`
Slug string `json:"slug,omitempty"`
CategorySlug string `json:"category_slug,omitempty"`
}
GetBlogPostRequest defines the request to get a blog post
func (*GetBlogPostRequest) Validate ¶
func (r *GetBlogPostRequest) Validate() error
Validate validates the get blog post request
type GetBlogThemeRequest ¶
type GetBlogThemeRequest struct {
Version int `json:"version"`
}
GetBlogThemeRequest defines the request to get a blog theme
func (*GetBlogThemeRequest) Validate ¶
func (r *GetBlogThemeRequest) Validate() error
Validate validates the get blog theme request
type GetBroadcastRequest ¶
type GetBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
WithTemplates bool `json:"with_templates,omitempty"`
}
GetBroadcastRequest represents the request to get a single broadcast
func (*GetBroadcastRequest) FromURLParams ¶
func (r *GetBroadcastRequest) FromURLParams(values url.Values) error
FromURLParams parses URL query parameters into the request
type GetBroadcastsRequest ¶
type GetBroadcastsRequest struct {
WorkspaceID string `json:"workspace_id"`
Status string `json:"status,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
WithTemplates bool `json:"with_templates,omitempty"`
}
GetBroadcastsRequest is used to extract query parameters for listing broadcasts
func (*GetBroadcastsRequest) FromURLParams ¶
func (r *GetBroadcastsRequest) FromURLParams(values url.Values) error
FromURLParams parses URL query parameters into the request
type GetContactByEmailRequest ¶
type GetContactByEmailRequest struct {
WorkspaceID string `json:"workspace_id" valid:"required"`
Email string `json:"email" valid:"required,email"`
}
Request/Response types
type GetContactListRequest ¶
type GetContactListRequest struct {
WorkspaceID string `json:"workspace_id"`
Email string `json:"email"`
ListID string `json:"list_id"`
}
func (*GetContactListRequest) FromURLParams ¶
func (r *GetContactListRequest) FromURLParams(queryParams url.Values) (err error)
type GetContactNodeExecutionsRequest ¶
type GetContactNodeExecutionsRequest struct {
WorkspaceID string `json:"workspace_id"`
AutomationID string `json:"automation_id"`
Email string `json:"email"`
}
GetContactNodeExecutionsRequest represents the request to get a contact's node executions
func (*GetContactNodeExecutionsRequest) FromURLParams ¶
func (r *GetContactNodeExecutionsRequest) FromURLParams(params map[string][]string) error
FromURLParams parses the request from URL parameters
func (*GetContactNodeExecutionsRequest) Validate ¶
func (r *GetContactNodeExecutionsRequest) Validate() error
Validate validates the get contact node executions request
type GetContactsByListRequest ¶
type GetContactsByListRequest struct {
WorkspaceID string `json:"workspace_id"`
ListID string `json:"list_id"`
}
func (*GetContactsByListRequest) FromURLParams ¶
func (r *GetContactsByListRequest) FromURLParams(queryParams url.Values) (err error)
type GetContactsRequest ¶
type GetContactsRequest struct {
// Required fields
WorkspaceID string `json:"workspace_id" valid:"required,alphanum,stringlength(1|20)"`
// Optional filters
Email string `json:"email,omitempty" valid:"optional,email"`
ExternalID string `json:"external_id,omitempty" valid:"optional"`
FirstName string `json:"first_name,omitempty" valid:"optional"`
LastName string `json:"last_name,omitempty" valid:"optional"`
FullName string `json:"full_name,omitempty" valid:"optional"`
Phone string `json:"phone,omitempty" valid:"optional"`
Country string `json:"country,omitempty" valid:"optional"`
Language string `json:"language,omitempty" valid:"optional"`
ListID string `json:"list_id,omitempty" valid:"optional"`
ContactListStatus string `json:"contact_list_status,omitempty" valid:"optional"`
Segments []string `json:"segments,omitempty" valid:"optional"`
// Join contact_lists
WithContactLists bool `json:"with_contact_lists,omitempty" valid:"optional"`
// Pagination
Limit int `json:"limit,omitempty" valid:"optional,range(1|100)"`
Cursor string `json:"cursor,omitempty" valid:"optional"`
}
GetContactsRequest represents a request to get contacts with filters and pagination
func (*GetContactsRequest) FromQueryParams ¶
func (r *GetContactsRequest) FromQueryParams(params url.Values) error
FromQueryParams populates the request from URL query parameters
func (*GetContactsRequest) Validate ¶
func (r *GetContactsRequest) Validate() error
Validate ensures that the request has all required fields and valid values
type GetContactsResponse ¶
type GetContactsResponse struct {
Contacts []*Contact `json:"contacts"`
NextCursor string `json:"next_cursor,omitempty"`
}
GetContactsResponse represents the response from getting contacts
type GetEventByIDRequest ¶
type GetEventByIDRequest struct {
ID string `json:"id"`
}
GetEventByIDRequest defines the parameters for retrieving a webhook event by ID
type GetEventsByMessageIDRequest ¶
type GetEventsByMessageIDRequest struct {
MessageID string `json:"message_id"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
}
GetEventsByMessageIDRequest defines the parameters for retrieving webhook events by message ID
type GetListRequest ¶
func (*GetListRequest) FromURLParams ¶
func (r *GetListRequest) FromURLParams(queryParams url.Values) (err error)
type GetListsByContactRequest ¶
type GetListsByContactRequest struct {
WorkspaceID string `json:"workspace_id"`
Email string `json:"email"`
}
func (*GetListsByContactRequest) FromURLParams ¶
func (r *GetListsByContactRequest) FromURLParams(queryParams url.Values) (err error)
type GetListsRequest ¶
type GetListsRequest struct {
WorkspaceID string `json:"workspace_id"`
}
func (*GetListsRequest) FromURLParams ¶
func (r *GetListsRequest) FromURLParams(queryParams url.Values) (err error)
type GetSegmentRequest ¶
func (*GetSegmentRequest) FromURLParams ¶
func (r *GetSegmentRequest) FromURLParams(values url.Values) error
type GetSegmentsRequest ¶
type GetSegmentsRequest struct {
WorkspaceID string `json:"workspace_id"`
WithCount bool `json:"with_count"` // Whether to include contact counts (can be expensive)
}
func (*GetSegmentsRequest) FromURLParams ¶
func (r *GetSegmentsRequest) FromURLParams(values url.Values) error
type GetTaskRequest ¶
GetTaskRequest is used to extract query parameters for getting a single task
func (*GetTaskRequest) FromURLParams ¶
func (r *GetTaskRequest) FromURLParams(values url.Values) error
FromURLParams parses URL query parameters into the request
type GetTemplateBlockRequest ¶
type GetTemplateBlockRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
GetTemplateBlockRequest defines the request structure for getting a template block
func (*GetTemplateBlockRequest) FromURLParams ¶
func (r *GetTemplateBlockRequest) FromURLParams(queryParams url.Values) error
FromURLParams parses the request from URL query parameters
type GetTemplateRequest ¶
type GetTemplateRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Version int64 `json:"version,omitempty"`
}
func (*GetTemplateRequest) FromURLParams ¶
func (r *GetTemplateRequest) FromURLParams(queryParams url.Values) (err error)
type GetTemplatesRequest ¶
type GetTemplatesRequest struct {
WorkspaceID string `json:"workspace_id"`
Category string `json:"category,omitempty"`
Channel string `json:"channel,omitempty"`
}
func (*GetTemplatesRequest) FromURLParams ¶
func (r *GetTemplatesRequest) FromURLParams(queryParams url.Values) (err error)
type GetTestResultsRequest ¶
type GetTestResultsRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
GetTestResultsRequest represents the request to get A/B test results
func (*GetTestResultsRequest) FromURLParams ¶
func (r *GetTestResultsRequest) FromURLParams(values url.Values) error
FromURLParams parses URL parameters into the request
func (*GetTestResultsRequest) Validate ¶
func (r *GetTestResultsRequest) Validate() error
Validate validates the get test results request
type GetTransactionalRequest ¶
type GetTransactionalRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
GetTransactionalRequest represents a request to get a transactional notification
func (*GetTransactionalRequest) FromURLParams ¶
func (req *GetTransactionalRequest) FromURLParams(values map[string][]string) error
FromURLParams populates the request from URL query parameters
type GetWebhookStatusRequest ¶
type GetWebhookStatusRequest struct {
WorkspaceID string `json:"workspace_id"`
IntegrationID string `json:"integration_id"`
}
GetWebhookStatusRequest defines the request to get webhook status
func (*GetWebhookStatusRequest) Validate ¶
func (r *GetWebhookStatusRequest) Validate() error
Validate validates the GetWebhookStatusRequest
type GetWorkspaceRequest ¶
type GetWorkspaceRequest struct {
ID string `json:"id"`
}
type HTTPClient ¶
HTTPClient defines the interface for HTTP operations
type HttpHeader ¶
HttpHeader represents a custom HTTP header
type ImportCustomEventsRequest ¶
type ImportCustomEventsRequest struct {
WorkspaceID string `json:"workspace_id"`
Events []*CustomEvent `json:"events"`
}
ImportCustomEventsRequest for bulk import
func (*ImportCustomEventsRequest) Validate ¶
func (r *ImportCustomEventsRequest) Validate() error
type InMemoryEventBus ¶
type InMemoryEventBus struct {
// contains filtered or unexported fields
}
InMemoryEventBus is a simple in-memory implementation of the EventBus
func NewInMemoryEventBus ¶
func NewInMemoryEventBus() *InMemoryEventBus
NewInMemoryEventBus creates a new in-memory event bus
func (*InMemoryEventBus) Publish ¶
func (b *InMemoryEventBus) Publish(ctx context.Context, event EventPayload)
Publish sends an event to all subscribers
func (*InMemoryEventBus) PublishWithAck ¶
func (b *InMemoryEventBus) PublishWithAck(ctx context.Context, event EventPayload, callback EventAckCallback)
PublishWithAck sends an event to all subscribers and calls the acknowledgment callback
func (*InMemoryEventBus) Subscribe ¶
func (b *InMemoryEventBus) Subscribe(eventType EventType, handler EventHandler)
Subscribe registers a handler for a specific event type
func (*InMemoryEventBus) Unsubscribe ¶
func (b *InMemoryEventBus) Unsubscribe(eventType EventType, handler EventHandler)
Unsubscribe removes a handler for an event type
type InboundWebhookEvent ¶
type InboundWebhookEvent struct {
ID string `json:"id"`
Type EmailEventType `json:"type"`
Source WebhookSource `json:"source"`
IntegrationID string `json:"integration_id"`
RecipientEmail string `json:"recipient_email"`
MessageID *string `json:"message_id,omitempty"`
Timestamp time.Time `json:"timestamp"`
RawPayload string `json:"raw_payload"`
// Bounce specific fields
BounceType string `json:"bounce_type,omitempty"`
BounceCategory string `json:"bounce_category,omitempty"`
BounceDiagnostic string `json:"bounce_diagnostic,omitempty"`
// Complaint specific fields
ComplaintFeedbackType string `json:"complaint_feedback_type,omitempty"`
CreatedAt time.Time `json:"created_at"` // Creation timestamp in the database
}
InboundWebhookEvent represents an event received from an email provider or integration webhook
func NewInboundWebhookEvent ¶
func NewInboundWebhookEvent( id string, eventType EmailEventType, source WebhookSource, integrationID string, recipientEmail string, messageID *string, timestamp time.Time, rawPayload string, ) *InboundWebhookEvent
NewInboundWebhookEvent creates a new inbound webhook event
type InboundWebhookEventListParams ¶
type InboundWebhookEventListParams struct {
// Cursor-based pagination
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit,omitempty"`
// Workspace identification
WorkspaceID string `json:"workspace_id"`
// Filters
EventType EmailEventType `json:"event_type,omitempty"`
RecipientEmail string `json:"recipient_email,omitempty"`
MessageID string `json:"message_id,omitempty"`
// Time range filters
TimestampAfter *time.Time `json:"timestamp_after,omitempty"`
TimestampBefore *time.Time `json:"timestamp_before,omitempty"`
}
func (*InboundWebhookEventListParams) FromQuery ¶
func (p *InboundWebhookEventListParams) FromQuery(query url.Values) error
FromQuery creates InboundWebhookEventListParams from HTTP query parameters
func (*InboundWebhookEventListParams) Validate ¶
func (p *InboundWebhookEventListParams) Validate() error
type InboundWebhookEventListResult ¶
type InboundWebhookEventListResult struct {
Events []*InboundWebhookEvent `json:"events"`
NextCursor string `json:"next_cursor,omitempty"`
HasMore bool `json:"has_more"`
}
InboundWebhookEventListResult contains the result of a ListInboundWebhookEvents operation
type InboundWebhookEventRepository ¶
type InboundWebhookEventRepository interface {
// StoreEvents stores an inbound webhook event in the database
StoreEvents(ctx context.Context, workspaceID string, events []*InboundWebhookEvent) error
// ListEvents retrieves all inbound webhook events for a workspace
ListEvents(ctx context.Context, workspaceID string, params InboundWebhookEventListParams) (*InboundWebhookEventListResult, error)
// DeleteForEmail deletes all inbound webhook events for a specific email
DeleteForEmail(ctx context.Context, workspaceID, email string) error
}
InboundWebhookEventRepository is the interface for inbound webhook event operations
type InboundWebhookEventServiceInterface ¶
type InboundWebhookEventServiceInterface interface {
// ProcessWebhook processes a webhook event from an email provider
ProcessWebhook(ctx context.Context, workspaceID, integrationID string, rawPayload []byte) error
// ListEvents retrieves all inbound webhook events for a workspace
ListEvents(ctx context.Context, workspaceID string, params InboundWebhookEventListParams) (*InboundWebhookEventListResult, error)
}
InboundWebhookEventServiceInterface defines the interface for inbound webhook event service
type Integration ¶
type Integration struct {
ID string `json:"id"`
Name string `json:"name"`
Type IntegrationType `json:"type"`
EmailProvider EmailProvider `json:"email_provider,omitempty"`
SupabaseSettings *SupabaseIntegrationSettings `json:"supabase_settings,omitempty"`
LLMProvider *LLMProvider `json:"llm_provider,omitempty"`
FirecrawlSettings *FirecrawlSettings `json:"firecrawl_settings,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Integration represents a third-party service integration that's embedded in workspace settings
func (*Integration) AfterLoad ¶
func (i *Integration) AfterLoad(secretkey string) error
AfterLoad processes an Integration after loading by decrypting secrets
func (*Integration) BeforeSave ¶
func (i *Integration) BeforeSave(secretkey string) error
BeforeSave prepares an Integration for saving by encrypting secrets
func (*Integration) Scan ¶
func (b *Integration) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
func (*Integration) Validate ¶
func (i *Integration) Validate(passphrase string) error
Validate validates the integration
type IntegrationType ¶
type IntegrationType string
IntegrationType defines the type of integration
const ( IntegrationTypeEmail IntegrationType = "email" IntegrationTypeSupabase IntegrationType = "supabase" IntegrationTypeLLM IntegrationType = "llm" IntegrationTypeFirecrawl IntegrationType = "firecrawl" )
type Integrations ¶
type Integrations []Integration
Integrations is a slice of Integration with database serialization methods
func (*Integrations) Scan ¶
func (i *Integrations) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type InviteMemberRequest ¶
type InviteMemberRequest struct {
WorkspaceID string `json:"workspace_id"`
Email string `json:"email"`
Permissions UserPermissions `json:"permissions,omitempty"`
}
func (*InviteMemberRequest) Validate ¶
func (r *InviteMemberRequest) Validate() error
type JSONArray ¶
type JSONArray []interface{}
JSONArray is persisted as a JSON array in the database
type LLMChatEvent ¶
type LLMChatEvent struct {
Type string `json:"type"` // "text", "tool_use", "server_tool_start", "server_tool_result", "done", "error"
Content string `json:"content,omitempty"` // Text content for "text" events
Error string `json:"error,omitempty"` // Error message for "error" events
ToolName string `json:"tool_name,omitempty"` // Tool name for "tool_use" events
ToolInput map[string]interface{} `json:"tool_input,omitempty"` // Tool input for "tool_use" events
InputTokens *int64 `json:"input_tokens,omitempty"` // Token count (done event only)
OutputTokens *int64 `json:"output_tokens,omitempty"` // Token count (done event only)
InputCost *float64 `json:"input_cost,omitempty"` // Cost in USD (done event only)
OutputCost *float64 `json:"output_cost,omitempty"` // Cost in USD (done event only)
TotalCost *float64 `json:"total_cost,omitempty"` // Total cost in USD (done event only)
Model string `json:"model,omitempty"` // Model used (done event only)
}
LLMChatEvent represents an SSE event sent during streaming
type LLMChatRequest ¶
type LLMChatRequest struct {
WorkspaceID string `json:"workspace_id"`
IntegrationID string `json:"integration_id"`
Messages []LLMMessage `json:"messages"`
MaxTokens int `json:"max_tokens,omitempty"`
SystemPrompt string `json:"system_prompt,omitempty"`
Tools []LLMTool `json:"tools,omitempty"`
}
LLMChatRequest represents a request to the LLM chat endpoint
func (*LLMChatRequest) Validate ¶
func (r *LLMChatRequest) Validate() error
Validate validates the LLM chat request
type LLMMessage ¶
type LLMMessage struct {
Role string `json:"role"` // "user" or "assistant"
Content string `json:"content"`
}
LLMMessage represents a chat message
type LLMProvider ¶
type LLMProvider struct {
Kind LLMProviderKind `json:"kind"`
Anthropic *AnthropicSettings `json:"anthropic,omitempty"`
}
LLMProvider contains configuration for an LLM service provider
func (*LLMProvider) DecryptSecretKeys ¶
func (l *LLMProvider) DecryptSecretKeys(passphrase string) error
DecryptSecretKeys decrypts all encrypted secret keys in the LLM provider
func (*LLMProvider) EncryptSecretKeys ¶
func (l *LLMProvider) EncryptSecretKeys(passphrase string) error
EncryptSecretKeys encrypts all secret keys in the LLM provider
func (*LLMProvider) Validate ¶
func (l *LLMProvider) Validate(passphrase string) error
Validate validates the LLM provider settings
type LLMProviderKind ¶
type LLMProviderKind string
LLMProviderKind defines the type of LLM provider
const (
LLMProviderKindAnthropic LLMProviderKind = "anthropic"
)
type LLMService ¶
type LLMService interface {
// StreamChat sends a chat request and streams the response
StreamChat(ctx context.Context, req *LLMChatRequest, onEvent func(LLMChatEvent) error) error
}
LLMService defines the interface for LLM operations
type LLMTool ¶
type LLMTool struct {
Name string `json:"name"`
Description string `json:"description"`
InputSchema json.RawMessage `json:"input_schema"`
}
LLMTool represents a tool the AI can use
type List ¶
type List struct {
ID string `json:"id"`
Name string `json:"name"`
IsDoubleOptin bool `json:"is_double_optin" db:"is_double_optin"`
IsPublic bool `json:"is_public" db:"is_public"`
Description string `json:"description,omitempty"`
DoubleOptInTemplate *TemplateReference `json:"double_optin_template,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"-" db:"deleted_at"`
}
List represents a subscription list
type ListAutomationsRequest ¶
type ListAutomationsRequest struct {
WorkspaceID string `json:"workspace_id"`
Status []AutomationStatus `json:"status,omitempty"`
ListID string `json:"list_id,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
}
ListAutomationsRequest represents the request to list automations
func (*ListAutomationsRequest) FromURLParams ¶
func (r *ListAutomationsRequest) FromURLParams(params map[string][]string) error
FromURLParams parses the request from URL parameters
func (*ListAutomationsRequest) ToFilter ¶
func (r *ListAutomationsRequest) ToFilter() AutomationFilter
ToFilter converts the request to an AutomationFilter
func (*ListAutomationsRequest) Validate ¶
func (r *ListAutomationsRequest) Validate() error
Validate validates the list automations request
type ListBlogPostsRequest ¶
type ListBlogPostsRequest struct {
CategoryID string `json:"category_id,omitempty"`
Status BlogPostStatus `json:"status,omitempty"`
Page int `json:"page,omitempty"` // Page number (1-indexed)
Limit int `json:"limit,omitempty"` // Posts per page
Offset int `json:"offset,omitempty"` // Calculated from Page
}
ListBlogPostsRequest defines the request to list blog posts
func (*ListBlogPostsRequest) Validate ¶
func (r *ListBlogPostsRequest) Validate() error
Validate validates the list blog posts request
type ListBlogThemesRequest ¶
type ListBlogThemesRequest struct {
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
}
ListBlogThemesRequest defines the request to list blog themes
func (*ListBlogThemesRequest) Validate ¶
func (r *ListBlogThemesRequest) Validate() error
Validate validates the list blog themes request
type ListBroadcastsParams ¶
type ListBroadcastsParams struct {
WorkspaceID string
Status BroadcastStatus
Limit int
Offset int
WithTemplates bool // Whether to fetch and include template details for each variation
}
ListBroadcastsParams defines parameters for listing broadcasts with pagination
type ListCustomEventsRequest ¶
type ListCustomEventsRequest struct {
WorkspaceID string
Email string
EventName *string // Optional filter by event name
Limit int
Offset int
}
ListCustomEventsRequest represents query parameters for listing custom events
func (*ListCustomEventsRequest) Validate ¶
func (r *ListCustomEventsRequest) Validate() error
type ListRepository ¶
type ListRepository interface {
// CreateList creates a new list in the database
CreateList(ctx context.Context, workspaceID string, list *List) error
// GetListByID retrieves a list by its ID
GetListByID(ctx context.Context, workspaceID string, id string) (*List, error)
// GetLists retrieves all lists
GetLists(ctx context.Context, workspaceID string) ([]*List, error)
// UpdateList updates an existing list
UpdateList(ctx context.Context, workspaceID string, list *List) error
// DeleteList deletes a list
DeleteList(ctx context.Context, workspaceID string, id string) error
GetListStats(ctx context.Context, workspaceID string, id string) (*ListStats, error)
}
type ListService ¶
type ListService interface {
// SubscribeToLists subscribes a contact to a list
SubscribeToLists(ctx context.Context, payload *SubscribeToListsRequest, hasBearerToken bool) error
// UnsubscribeFromLists unsubscribes a contact from a list
UnsubscribeFromLists(ctx context.Context, payload *UnsubscribeFromListsRequest, hasBearerToken bool) error
// CreateList creates a new list
CreateList(ctx context.Context, workspaceID string, list *List) error
// GetListByID retrieves a list by ID
GetListByID(ctx context.Context, workspaceID string, id string) (*List, error)
// GetLists retrieves all lists
GetLists(ctx context.Context, workspaceID string) ([]*List, error)
// UpdateList updates an existing list
UpdateList(ctx context.Context, workspaceID string, list *List) error
// DeleteList deletes a list by ID
DeleteList(ctx context.Context, workspaceID string, id string) error
GetListStats(ctx context.Context, workspaceID string, id string) (*ListStats, error)
}
ListService provides operations for managing lists
type ListStatusBranchNodeConfig ¶
type ListStatusBranchNodeConfig struct {
ListID string `json:"list_id"` // List to check status in
NotInListNodeID string `json:"not_in_list_node_id"` // Next node when contact is not in list
ActiveNodeID string `json:"active_node_id"` // Next node when status is "active"
NonActiveNodeID string `json:"non_active_node_id"` // Next node when status is non-active (pending, unsubscribed, bounced, complained)
}
ListStatusBranchNodeConfig configures a list status branch node This node checks a contact's subscription status in a list and branches accordingly
func (ListStatusBranchNodeConfig) Validate ¶
func (c ListStatusBranchNodeConfig) Validate() error
Validate validates the list status branch node config
type ListTasksRequest ¶
type ListTasksRequest struct {
WorkspaceID string `json:"workspace_id"`
Status []string `json:"status,omitempty"`
Type []string `json:"type,omitempty"`
CreatedAfter string `json:"created_after,omitempty"`
CreatedBefore string `json:"created_before,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
}
ListTasksRequest is used to extract query parameters for listing tasks
func (*ListTasksRequest) FromURLParams ¶
func (r *ListTasksRequest) FromURLParams(values url.Values) error
FromURLParams parses URL query parameters into the request
func (*ListTasksRequest) ToFilter ¶
func (r *ListTasksRequest) ToFilter() TaskFilter
ToFilter converts the request to a TaskFilter
type ListTemplateBlocksRequest ¶
type ListTemplateBlocksRequest struct {
WorkspaceID string `json:"workspace_id"`
}
ListTemplateBlocksRequest defines the request structure for listing template blocks
func (*ListTemplateBlocksRequest) FromURLParams ¶
func (r *ListTemplateBlocksRequest) FromURLParams(queryParams url.Values) error
FromURLParams parses the request from URL query parameters
type ListTransactionalRequest ¶
type ListTransactionalRequest struct {
WorkspaceID string `json:"workspace_id"`
Search string `json:"search,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
Filter map[string]interface{} `json:"filter,omitempty"`
}
ListTransactionalRequest represents a request to list transactional notifications
func (*ListTransactionalRequest) FromURLParams ¶
func (req *ListTransactionalRequest) FromURLParams(values map[string][]string) error
FromURLParams populates the request from URL query parameters
type MailgunDelivery ¶
type MailgunDelivery struct {
Status string `json:"status,omitempty"`
Code int `json:"code,omitempty"`
Message string `json:"message,omitempty"`
AttemptNo int `json:"attempt-no,omitempty"`
Description string `json:"description,omitempty"`
SessionSeconds float64 `json:"session-seconds,omitempty"`
Certificate bool `json:"certificate,omitempty"`
TLS bool `json:"tls,omitempty"`
MXHost string `json:"mx-host,omitempty"`
DelvDataFeedback []interface{} `json:"delivery-status,omitempty"`
SMTP map[string]interface{} `json:"smtp,omitempty"`
}
MailgunDelivery contains delivery information
type MailgunEventData ¶
type MailgunEventData struct {
Event string `json:"event"`
Timestamp float64 `json:"timestamp"`
ID string `json:"id"`
Recipient string `json:"recipient"`
Tags []string `json:"tags"`
Message MailgunMessage `json:"message"`
Delivery MailgunDelivery `json:"delivery,omitempty"`
Reason string `json:"reason,omitempty"`
Severity string `json:"severity,omitempty"`
Storage map[string]interface{} `json:"storage,omitempty"`
UserVariables map[string]interface{} `json:"user-variables,omitempty"`
Flags map[string]interface{} `json:"flags,omitempty"`
}
MailgunEventData contains the main event data from Mailgun
type MailgunHeaders ¶
type MailgunHeaders struct {
To string `json:"to"`
MessageID string `json:"message-id"`
From string `json:"from"`
Subject string `json:"subject"`
}
MailgunHeaders contains email headers
type MailgunMessage ¶
type MailgunMessage struct {
Headers MailgunHeaders `json:"headers"`
Attachments []interface{} `json:"attachments"`
Size int `json:"size"`
}
MailgunMessage contains information about the email message
type MailgunServiceInterface ¶
type MailgunServiceInterface interface {
// ListWebhooks retrieves all registered webhooks for a domain
ListWebhooks(ctx context.Context, config MailgunSettings) (*MailgunWebhookListResponse, error)
// CreateWebhook creates a new webhook
CreateWebhook(ctx context.Context, config MailgunSettings, webhook MailgunWebhook) (*MailgunWebhook, error)
// GetWebhook retrieves a webhook by ID
GetWebhook(ctx context.Context, config MailgunSettings, webhookID string) (*MailgunWebhook, error)
// UpdateWebhook updates an existing webhook
UpdateWebhook(ctx context.Context, config MailgunSettings, webhookID string, webhook MailgunWebhook) (*MailgunWebhook, error)
// DeleteWebhook deletes a webhook by ID
DeleteWebhook(ctx context.Context, config MailgunSettings, webhookID string) error
// TestWebhook sends a test event to a webhook
TestWebhook(ctx context.Context, config MailgunSettings, webhookID string, eventType string) error
}
MailgunServiceInterface defines operations for managing Mailgun webhooks
type MailgunSettings ¶
type MailgunSettings struct {
EncryptedAPIKey string `json:"encrypted_api_key,omitempty"`
Domain string `json:"domain"`
Region string `json:"region,omitempty"` // "US" or "EU"
// decoded API key, not stored in the database
APIKey string `json:"api_key,omitempty"`
}
MailgunSettings contains configuration for Mailgun
func (*MailgunSettings) DecryptAPIKey ¶
func (m *MailgunSettings) DecryptAPIKey(passphrase string) error
func (*MailgunSettings) EncryptAPIKey ¶
func (m *MailgunSettings) EncryptAPIKey(passphrase string) error
func (*MailgunSettings) Validate ¶
func (m *MailgunSettings) Validate(passphrase string) error
type MailgunSignature ¶
type MailgunSignature struct {
Timestamp string `json:"timestamp"`
Token string `json:"token"`
Signature string `json:"signature"`
}
MailgunSignature contains signature information for webhook authentication
type MailgunUrls ¶
type MailgunUrls struct {
URLs []string `json:"urls"`
}
type MailgunWebhook ¶
type MailgunWebhook struct {
ID string `json:"id,omitempty"`
URL string `json:"url"`
Events []string `json:"events"`
Active bool `json:"active"`
}
MailgunWebhook represents a webhook configuration in Mailgun
type MailgunWebhookListResponse ¶
type MailgunWebhookListResponse struct {
Webhooks MailgunWebhooks `json:"webhooks"`
}
type MailgunWebhookPayload ¶
type MailgunWebhookPayload struct {
Signature MailgunSignature `json:"signature"`
EventData MailgunEventData `json:"event-data"`
}
MailgunWebhookPayload represents a Mailgun webhook payload
type MailgunWebhooks ¶
type MailgunWebhooks struct {
Delivered MailgunUrls `json:"delivered"`
PermanentFail MailgunUrls `json:"permanent_fail"`
TemporaryFail MailgunUrls `json:"temporary_fail"`
Complained MailgunUrls `json:"complained"`
}
MailgunWebhookListResponse represents the response from listing webhooks
type MailjetServiceInterface ¶
type MailjetServiceInterface interface {
// ListWebhooks retrieves all registered webhooks
ListWebhooks(ctx context.Context, config MailjetSettings) (*MailjetWebhookResponse, error)
// CreateWebhook creates a new webhook
CreateWebhook(ctx context.Context, config MailjetSettings, webhook MailjetWebhook) (*MailjetWebhook, error)
// GetWebhook retrieves a webhook by ID
GetWebhook(ctx context.Context, config MailjetSettings, webhookID int64) (*MailjetWebhook, error)
// UpdateWebhook updates an existing webhook
UpdateWebhook(ctx context.Context, config MailjetSettings, webhookID int64, webhook MailjetWebhook) (*MailjetWebhook, error)
// DeleteWebhook deletes a webhook by ID
DeleteWebhook(ctx context.Context, config MailjetSettings, webhookID int64) error
}
MailjetServiceInterface defines operations for managing Mailjet webhooks
type MailjetSettings ¶
type MailjetSettings struct {
EncryptedAPIKey string `json:"encrypted_api_key,omitempty"`
EncryptedSecretKey string `json:"encrypted_secret_key,omitempty"`
SandboxMode bool `json:"sandbox_mode"`
// decoded keys, not stored in the database
APIKey string `json:"api_key,omitempty"`
SecretKey string `json:"secret_key,omitempty"`
}
MailjetSettings contains configuration for Mailjet
func (*MailjetSettings) DecryptAPIKey ¶
func (m *MailjetSettings) DecryptAPIKey(passphrase string) error
func (*MailjetSettings) DecryptSecretKey ¶
func (m *MailjetSettings) DecryptSecretKey(passphrase string) error
func (*MailjetSettings) EncryptAPIKey ¶
func (m *MailjetSettings) EncryptAPIKey(passphrase string) error
func (*MailjetSettings) EncryptSecretKey ¶
func (m *MailjetSettings) EncryptSecretKey(passphrase string) error
func (*MailjetSettings) Validate ¶
func (m *MailjetSettings) Validate(passphrase string) error
type MailjetWebhook ¶
type MailjetWebhook struct {
ID int64 `json:"ID,omitempty"`
APIKey string `json:"APIKey,omitempty"`
Endpoint string `json:"Url"`
EventType string `json:"EventType"`
Status string `json:"Status,omitempty"`
Version int `json:"Version"`
IsBackup bool `json:"IsBackup,omitempty"`
}
MailjetWebhook represents a webhook configuration in Mailjet According to https://dev.mailjet.com/email/reference/webhook#v3_post_eventcallbackurl
type MailjetWebhookEventType ¶
type MailjetWebhookEventType string
MailjetWebhookEventType represents the available event types for webhooks
const ( // Event types as defined in Mailjet documentation MailjetEventSent MailjetWebhookEventType = "sent" MailjetEventBounce MailjetWebhookEventType = "bounce" MailjetEventBlocked MailjetWebhookEventType = "blocked" MailjetEventSpam MailjetWebhookEventType = "spam" MailjetEventUnsub MailjetWebhookEventType = "unsub" MailjetEventClick MailjetWebhookEventType = "click" MailjetEventOpen MailjetWebhookEventType = "open" )
type MailjetWebhookPayload ¶
type MailjetWebhookPayload struct {
Event string `json:"event"`
Time int64 `json:"time"`
MessageID int64 `json:"MessageID"`
Email string `json:"email"`
// Message identification
MjCampaignID int64 `json:"mj_campaign_id,omitempty"`
MjContactID int64 `json:"mj_contact_id,omitempty"`
CustomID string `json:"CustomID,omitempty"`
MessageUUID string `json:"MessageUUID,omitempty"`
// Campaign information
CustomCampaign string `json:"CustomCampaign,omitempty"`
Payload string `json:"Payload,omitempty"`
// Bounce specific fields
Blocked bool `json:"blocked,omitempty"`
HardBounce bool `json:"hard_bounce,omitempty"`
ErrorRelatedTo string `json:"error_related_to,omitempty"`
Error string `json:"error,omitempty"`
// Complaint specific fields
Source string `json:"source,omitempty"`
// Common fields
Comment string `json:"comment,omitempty"`
// Click/Open specific fields
URL string `json:"url,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
}
MailjetWebhookPayload represents the webhook payload from Mailjet According to https://dev.mailjet.com/email/guides/webhooks/
type MailjetWebhookResponse ¶
type MailjetWebhookResponse struct {
Count int `json:"Count"`
Data []MailjetWebhook `json:"Data"`
Total int `json:"Total"`
}
MailjetWebhookResponse represents a response for webhook operations
type MapOfAny ¶
MapOfAny is persisted as JSON in the database
func BuildBlogTemplateData ¶
func BuildBlogTemplateData(req BlogTemplateDataRequest) (MapOfAny, error)
BuildBlogTemplateData creates a template data map for blog Liquid templates This ensures consistent data structure across all blog pages
func BuildTemplateData ¶
func BuildTemplateData(req TemplateDataRequest) (MapOfAny, error)
BuildTemplateData creates a template data map with flexible options
type MessageData ¶
type MessageData struct {
// Custom fields used in template compilation
Data map[string]interface{} `json:"data"`
// Optional metadata for tracking
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
MessageData represents the JSON data used to compile a template
func (*MessageData) Scan ¶
func (d *MessageData) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database retrieval
type MessageEvent ¶
type MessageEvent string
MessageStatus represents the current status of a message
const ( // Message status constants MessageEventSent MessageEvent = "sent" MessageEventDelivered MessageEvent = "delivered" MessageEventFailed MessageEvent = "failed" MessageEventOpened MessageEvent = "opened" MessageEventClicked MessageEvent = "clicked" MessageEventBounced MessageEvent = "bounced" MessageEventComplained MessageEvent = "complained" MessageEventUnsubscribed MessageEvent = "unsubscribed" )
type MessageEventUpdate ¶
type MessageEventUpdate struct {
ID string `json:"id"`
Event MessageEvent `json:"event"`
Timestamp time.Time `json:"timestamp"`
StatusInfo *string `json:"status_info,omitempty"`
}
MessageEventUpdate represents a status update for a message
type MessageHistory ¶
type MessageHistory struct {
ID string `json:"id"`
ExternalID *string `json:"external_id,omitempty"` // For idempotency checks
ContactEmail string `json:"contact_email"`
BroadcastID *string `json:"broadcast_id,omitempty"`
AutomationID *string `json:"automation_id,omitempty"` // Automation this message was sent from (nullable for broadcasts/transactional)
ListID *string `json:"list_id,omitempty"` // List this message was sent to (nullable for transactional emails)
TemplateID string `json:"template_id"`
TemplateVersion int64 `json:"template_version"`
Channel string `json:"channel"` // email, sms, push, etc.
StatusInfo *string `json:"status_info,omitempty"`
MessageData MessageData `json:"message_data"`
ChannelOptions *ChannelOptions `json:"channel_options,omitempty"` // Channel-specific delivery options
Attachments []AttachmentMetadata `json:"attachments,omitempty"`
// Event timestamps
SentAt time.Time `json:"sent_at"`
DeliveredAt *time.Time `json:"delivered_at,omitempty"`
FailedAt *time.Time `json:"failed_at,omitempty"`
OpenedAt *time.Time `json:"opened_at,omitempty"`
ClickedAt *time.Time `json:"clicked_at,omitempty"`
BouncedAt *time.Time `json:"bounced_at,omitempty"`
ComplainedAt *time.Time `json:"complained_at,omitempty"`
UnsubscribedAt *time.Time `json:"unsubscribed_at,omitempty"`
// System timestamps
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
MessageHistory represents a record of a message sent to a contact
type MessageHistoryRepository ¶
type MessageHistoryRepository interface {
// Create adds a new message history record
Create(ctx context.Context, workspaceID string, secretKey string, message *MessageHistory) error
// Upsert creates or updates a message history record (for retry handling)
// On conflict, updates failed_at, status_info, and updated_at fields
Upsert(ctx context.Context, workspaceID string, secretKey string, message *MessageHistory) error
// Update updates an existing message history record
Update(ctx context.Context, workspaceID string, message *MessageHistory) error
// Get retrieves a message history by ID
Get(ctx context.Context, workspaceID string, secretKey string, id string) (*MessageHistory, error)
// GetByExternalID retrieves a message history by external ID for idempotency checks
GetByExternalID(ctx context.Context, workspaceID string, secretKey string, externalID string) (*MessageHistory, error)
// GetByContact retrieves message history for a specific contact
GetByContact(ctx context.Context, workspaceID string, secretKey string, contactEmail string, limit, offset int) ([]*MessageHistory, int, error)
// GetByBroadcast retrieves message history for a specific broadcast
GetByBroadcast(ctx context.Context, workspaceID string, secretKey string, broadcastID string, limit, offset int) ([]*MessageHistory, int, error)
// ListMessages retrieves message history with cursor-based pagination and filtering
ListMessages(ctx context.Context, workspaceID string, secretKey string, params MessageListParams) ([]*MessageHistory, string, error)
// SetStatusesIfNotSet updates multiple message statuses in a batch if they haven't been set before
SetStatusesIfNotSet(ctx context.Context, workspaceID string, updates []MessageEventUpdate) error
// SetClicked sets the clicked_at timestamp and ensures opened_at is also set
SetClicked(ctx context.Context, workspaceID, id string, timestamp time.Time) error
// SetOpened sets the opened_at timestamp if not already set
SetOpened(ctx context.Context, workspaceID, id string, timestamp time.Time) error
// GetBroadcastStats retrieves statistics for a broadcast
GetBroadcastStats(ctx context.Context, workspaceID, broadcastID string) (*MessageHistoryStatusSum, error)
// GetBroadcastVariationStats retrieves statistics for a specific variation of a broadcast
GetBroadcastVariationStats(ctx context.Context, workspaceID, broadcastID, templateID string) (*MessageHistoryStatusSum, error)
// DeleteForEmail deletes all message history records for a specific email
DeleteForEmail(ctx context.Context, workspaceID, email string) error
}
MessageHistoryRepository defines methods for message history persistence
type MessageHistoryService ¶
type MessageHistoryService interface {
// ListMessages retrieves messages for a workspace with cursor-based pagination and filters
ListMessages(ctx context.Context, workspaceID string, params MessageListParams) (*MessageListResult, error)
// GetBroadcastStats retrieves statistics for a broadcast
GetBroadcastStats(ctx context.Context, workspaceID, broadcastID string) (*MessageHistoryStatusSum, error)
// GetBroadcastVariationStats retrieves statistics for a specific variation of a broadcast
GetBroadcastVariationStats(ctx context.Context, workspaceID, broadcastID, templateID string) (*MessageHistoryStatusSum, error)
}
MessageHistoryService defines methods for interacting with message history
type MessageHistoryStatusSum ¶
type MessageHistoryStatusSum struct {
TotalSent int `json:"total_sent"`
TotalDelivered int `json:"total_delivered"`
TotalBounced int `json:"total_bounced"`
TotalComplained int `json:"total_complained"`
TotalFailed int `json:"total_failed"`
TotalOpened int `json:"total_opened"`
TotalClicked int `json:"total_clicked"`
TotalUnsubscribed int `json:"total_unsubscribed"`
}
type MessageListParams ¶
type MessageListParams struct {
// Cursor-based pagination
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit,omitempty"`
// Filters
ID string `json:"id,omitempty"` // filter by message ID
ExternalID string `json:"external_id,omitempty"` // filter by external ID
ListID string `json:"list_id,omitempty"` // filter by list ID (array contains)
Channel string `json:"channel,omitempty"` // email, sms, push, etc.
ContactEmail string `json:"contact_email,omitempty"` // filter by contact
BroadcastID string `json:"broadcast_id,omitempty"` // filter by broadcast
TemplateID string `json:"template_id,omitempty"` // filter by template
IsSent *bool `json:"is_sent,omitempty"` // filter messages that are sent
IsDelivered *bool `json:"is_delivered,omitempty"` // filter messages that are delivered
IsFailed *bool `json:"is_failed,omitempty"` // filter messages that are failed
IsOpened *bool `json:"is_opened,omitempty"` // filter messages that are opened
IsClicked *bool `json:"is_clicked,omitempty"` // filter messages that are clicked
IsBounced *bool `json:"is_bounced,omitempty"` // filter messages that are bounced
IsComplained *bool `json:"is_complained,omitempty"` // filter messages that are complained
IsUnsubscribed *bool `json:"is_unsubscribed,omitempty"` // filter messages that are unsubscribed
// Time range filters
SentAfter *time.Time `json:"sent_after,omitempty"`
SentBefore *time.Time `json:"sent_before,omitempty"`
UpdatedAfter *time.Time `json:"updated_after,omitempty"`
UpdatedBefore *time.Time `json:"updated_before,omitempty"`
}
MessageListParams contains parameters for listing messages with pagination and filtering
func (*MessageListParams) FromQuery ¶
func (p *MessageListParams) FromQuery(query url.Values) error
FromQuery creates MessageListParams from HTTP query parameters
func (*MessageListParams) Validate ¶
func (p *MessageListParams) Validate() error
type MessageListResult ¶
type MessageListResult struct {
Messages []*MessageHistory `json:"messages"`
NextCursor string `json:"next_cursor,omitempty"`
HasMore bool `json:"has_more"`
}
MessageListResult contains the result of a ListMessages operation
type NodeAction ¶
type NodeAction string
NodeAction represents an action in the automation node execution log
const ( NodeActionEntered NodeAction = "entered" NodeActionProcessing NodeAction = "processing" NodeActionCompleted NodeAction = "completed" NodeActionFailed NodeAction = "failed" NodeActionSkipped NodeAction = "skipped" )
func (NodeAction) IsValid ¶
func (a NodeAction) IsValid() bool
IsValid checks if the node action is valid
type NodeExecution ¶
type NodeExecution struct {
ID string `json:"id"`
ContactAutomationID string `json:"contact_automation_id"`
AutomationID string `json:"automation_id"`
NodeID string `json:"node_id"`
NodeType NodeType `json:"node_type"`
Action NodeAction `json:"action"`
EnteredAt time.Time `json:"entered_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
DurationMs *int64 `json:"duration_ms,omitempty"`
Output map[string]interface{} `json:"output,omitempty"`
Error *string `json:"error,omitempty"`
}
NodeExecution tracks a contact's progress through an automation node
func (*NodeExecution) Validate ¶
func (e *NodeExecution) Validate() error
Validate validates the node execution entry
type NodePosition ¶
NodePosition represents the visual position of a node in the flow editor
type NodeType ¶
type NodeType string
NodeType represents the type of automation node
const ( NodeTypeTrigger NodeType = "trigger" NodeTypeDelay NodeType = "delay" NodeTypeEmail NodeType = "email" NodeTypeBranch NodeType = "branch" NodeTypeFilter NodeType = "filter" NodeTypeAddToList NodeType = "add_to_list" NodeTypeRemoveFromList NodeType = "remove_from_list" NodeTypeABTest NodeType = "ab_test" NodeTypeWebhook NodeType = "webhook" NodeTypeListStatusBranch NodeType = "list_status_branch" )
type NotificationCenterRequest ¶
type NotificationCenterRequest struct {
Email string `json:"email"`
EmailHMAC string `json:"email_hmac"`
WorkspaceID string `json:"workspace_id"`
Action string `json:"action,omitempty"` // Optional action (e.g., "confirm", "unsubscribe")
ListID string `json:"list_id,omitempty"` // List ID for actions
MessageID string `json:"message_id,omitempty"` // Message ID for tracking
}
func (*NotificationCenterRequest) FromURLValues ¶
func (r *NotificationCenterRequest) FromURLValues(values url.Values) error
func (*NotificationCenterRequest) Validate ¶
func (r *NotificationCenterRequest) Validate() error
type NullableFloat64 ¶
NullableFloat64 represents a float64 that can be null
func (NullableFloat64) MarshalJSON ¶
func (nf NullableFloat64) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler
func (*NullableFloat64) Scan ¶
func (nf *NullableFloat64) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database/sql
func (*NullableFloat64) UnmarshalJSON ¶
func (nf *NullableFloat64) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler
type NullableJSON ¶
type NullableJSON struct {
Data interface{}
IsNull bool
}
NullableJSON represents a JSON object that can be null. It implements database/sql.Scanner and driver.Valuer interfaces for proper database handling, as well as json.Marshaler and json.Unmarshaler for JSON encoding/decoding.
func (NullableJSON) MarshalJSON ¶
func (nj NullableJSON) MarshalJSON() ([]byte, error)
MarshalJSON implements the json.Marshaler interface. It handles the JSON encoding of the NullableJSON value.
func (*NullableJSON) Scan ¶
func (nj *NullableJSON) Scan(value interface{}) error
Scan implements the sql.Scanner interface. It scans a value from the database into the NullableJSON struct.
func (*NullableJSON) UnmarshalJSON ¶
func (nj *NullableJSON) UnmarshalJSON(data []byte) error
UnmarshalJSON implements the json.Unmarshaler interface. It handles the JSON decoding into a NullableJSON value.
type NullableString ¶
NullableString represents a string that can be null
func (NullableString) MarshalJSON ¶
func (ns NullableString) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler
func (*NullableString) Scan ¶
func (ns *NullableString) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database/sql
func (*NullableString) UnmarshalJSON ¶
func (ns *NullableString) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler
type NullableTime ¶
NullableTime represents a time.Time that can be null
func (NullableTime) MarshalJSON ¶
func (nt NullableTime) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler
func (*NullableTime) Scan ¶
func (nt *NullableTime) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database/sql
func (*NullableTime) UnmarshalJSON ¶
func (nt *NullableTime) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler
type PauseAutomationRequest ¶
type PauseAutomationRequest struct {
WorkspaceID string `json:"workspace_id"`
AutomationID string `json:"automation_id"`
}
PauseAutomationRequest represents the request to pause an automation
func (*PauseAutomationRequest) Validate ¶
func (r *PauseAutomationRequest) Validate() error
Validate validates the pause automation request
type PauseBroadcastRequest ¶
type PauseBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
PauseBroadcastRequest defines the request to pause a sending broadcast
func (*PauseBroadcastRequest) Validate ¶
func (r *PauseBroadcastRequest) Validate() error
Validate validates the pause broadcast request
type PermissionError ¶
type PermissionError struct {
Resource PermissionResource `json:"resource"`
Permission PermissionType `json:"permission"`
Message string `json:"message"`
}
PermissionError represents insufficient permissions for an operation
func NewPermissionError ¶
func NewPermissionError(resource PermissionResource, permission PermissionType, message string) *PermissionError
NewPermissionError creates a new permission error
func (*PermissionError) Error ¶
func (e *PermissionError) Error() string
Error implements the error interface
type PermissionResource ¶
type PermissionResource string
PermissionResource defines the different resources that can have permissions
const ( PermissionResourceContacts PermissionResource = "contacts" PermissionResourceLists PermissionResource = "lists" PermissionResourceTemplates PermissionResource = "templates" PermissionResourceBroadcasts PermissionResource = "broadcasts" PermissionResourceTransactional PermissionResource = "transactional" PermissionResourceWorkspace PermissionResource = "workspace" PermissionResourceMessageHistory PermissionResource = "message_history" PermissionResourceBlog PermissionResource = "blog" PermissionResourceAutomations PermissionResource = "automations" PermissionResourceLLM PermissionResource = "llm" )
type PermissionType ¶
type PermissionType string
PermissionType defines the types of permissions (read/write)
const ( PermissionTypeRead PermissionType = "read" PermissionTypeWrite PermissionType = "write" )
type PostmarkBounceFields ¶
type PostmarkBounceFields struct {
RecipientEmail string `json:"Email"`
BouncedAt string `json:"BouncedAt"`
Type string `json:"Type"`
TypeCode int `json:"TypeCode"`
Name string `json:"Name"`
Description string `json:"Description,omitempty"`
Details string `json:"Details,omitempty"`
DumpAvailable bool `json:"DumpAvailable"`
CanActivate bool `json:"CanActivate"`
Subject string `json:"Subject"`
Content string `json:"Content,omitempty"`
}
PostmarkBounceFields contains fields specific to bounce events
type PostmarkBounceTrigger ¶
type PostmarkBounceTrigger struct {
Enabled bool `json:"Enabled"`
IncludeContent bool `json:"IncludeContent,omitempty"`
}
PostmarkBounceTrigger represents the bounce trigger configuration
type PostmarkClickTrigger ¶
type PostmarkClickTrigger struct {
Enabled bool `json:"Enabled"`
}
PostmarkClickTrigger represents the click trigger configuration
type PostmarkComplaintFields ¶
type PostmarkComplaintFields struct {
RecipientEmail string `json:"Email"`
ComplainedAt string `json:"ComplainedAt"`
Type string `json:"Type"`
UserAgent string `json:"UserAgent,omitempty"`
Subject string `json:"Subject"`
}
PostmarkComplaintFields contains fields specific to complaint events
type PostmarkDeliveredFields ¶
type PostmarkDeliveredFields struct {
RecipientEmail string `json:"Recipient"`
DeliveredAt string `json:"DeliveredAt"`
Details string `json:"Details"`
}
PostmarkDeliveredFields contains fields specific to delivery events
type PostmarkDeliveryTrigger ¶
type PostmarkDeliveryTrigger struct {
Enabled bool `json:"Enabled"`
}
PostmarkDeliveryTrigger represents the delivery trigger configuration
type PostmarkListWebhooksResponse ¶
type PostmarkListWebhooksResponse struct {
TotalCount int `json:"TotalCount"`
Webhooks []PostmarkWebhookResponse `json:"Webhooks"`
}
PostmarkListWebhooksResponse represents the response for listing webhooks
type PostmarkOpenTrigger ¶
type PostmarkOpenTrigger struct {
Enabled bool `json:"Enabled"`
PostFirstOpenOnly bool `json:"PostFirstOpenOnly,omitempty"`
}
PostmarkOpenTrigger represents the open trigger configuration
type PostmarkServiceInterface ¶
type PostmarkServiceInterface interface {
// ListWebhooks retrieves all registered webhooks
ListWebhooks(ctx context.Context, config PostmarkSettings) (*PostmarkListWebhooksResponse, error)
// RegisterWebhook registers a new webhook
RegisterWebhook(ctx context.Context, config PostmarkSettings, webhook PostmarkWebhookConfig) (*PostmarkWebhookResponse, error)
// UnregisterWebhook removes a webhook by ID
UnregisterWebhook(ctx context.Context, config PostmarkSettings, webhookID int) error
// GetWebhook retrieves a specific webhook by ID
GetWebhook(ctx context.Context, config PostmarkSettings, webhookID int) (*PostmarkWebhookResponse, error)
// UpdateWebhook updates an existing webhook
UpdateWebhook(ctx context.Context, config PostmarkSettings, webhookID int, webhook PostmarkWebhookConfig) (*PostmarkWebhookResponse, error)
// TestWebhook sends a test event to the webhook
TestWebhook(ctx context.Context, config PostmarkSettings, webhookID int, eventType EmailEventType) error
}
PostmarkServiceInterface defines operations for managing Postmark webhooks
type PostmarkSettings ¶
type PostmarkSettings struct {
EncryptedServerToken string `json:"encrypted_server_token,omitempty"`
ServerToken string `json:"server_token,omitempty"`
}
func (*PostmarkSettings) DecryptServerToken ¶
func (p *PostmarkSettings) DecryptServerToken(passphrase string) error
func (*PostmarkSettings) EncryptServerToken ¶
func (p *PostmarkSettings) EncryptServerToken(passphrase string) error
func (*PostmarkSettings) Validate ¶
func (p *PostmarkSettings) Validate(passphrase string) error
type PostmarkSpamComplaintTrigger ¶
type PostmarkSpamComplaintTrigger struct {
Enabled bool `json:"Enabled"`
IncludeContent bool `json:"IncludeContent,omitempty"`
}
PostmarkSpamComplaintTrigger represents the spam complaint trigger configuration
type PostmarkSubscriptionChangeTrigger ¶
type PostmarkSubscriptionChangeTrigger struct {
Enabled bool `json:"Enabled"`
}
PostmarkSubscriptionChangeTrigger represents the subscription change trigger configuration
type PostmarkTriggerRule ¶
type PostmarkTriggerRule struct {
Key string `json:"Key"`
Match string `json:"Match"`
Value string `json:"Value"`
}
PostmarkTriggerRule represents a trigger for webhooks Note: This is kept for compatibility with existing code
type PostmarkTriggers ¶
type PostmarkTriggers struct {
Open *PostmarkOpenTrigger `json:"Open,omitempty"`
Click *PostmarkClickTrigger `json:"Click,omitempty"`
Delivery *PostmarkDeliveryTrigger `json:"Delivery,omitempty"`
Bounce *PostmarkBounceTrigger `json:"Bounce,omitempty"`
SpamComplaint *PostmarkSpamComplaintTrigger `json:"SpamComplaint,omitempty"`
SubscriptionChange *PostmarkSubscriptionChangeTrigger `json:"SubscriptionChange,omitempty"`
}
PostmarkTriggers represents the webhook triggers configuration
type PostmarkWebhookConfig ¶
type PostmarkWebhookConfig struct {
ID int `json:"ID,omitempty"`
URL string `json:"Url"`
MessageStream string `json:"MessageStream"`
HttpAuth *HttpAuth `json:"HttpAuth,omitempty"`
HttpHeaders []HttpHeader `json:"HttpHeaders,omitempty"`
Triggers *PostmarkTriggers `json:"Triggers"`
}
PostmarkWebhookConfig represents a webhook configuration in Postmark
type PostmarkWebhookPayload ¶
type PostmarkWebhookPayload struct {
RecordType string `json:"RecordType"`
MessageStream string `json:"MessageStream"`
ID string `json:"ID"`
MessageID string `json:"MessageID"`
ServerID int `json:"ServerID"`
Metadata map[string]string `json:"Metadata,omitempty"`
Tag string `json:"Tag,omitempty"`
// Delivered event specific fields
DeliveredFields *PostmarkDeliveredFields `json:"-"`
// Bounce event specific fields
BounceFields *PostmarkBounceFields `json:"-"`
// Complaint event specific fields
ComplaintFields *PostmarkComplaintFields `json:"-"`
}
PostmarkWebhookPayload represents the base webhook payload from Postmark
type PostmarkWebhookResponse ¶
type PostmarkWebhookResponse struct {
ID int `json:"ID"`
URL string `json:"Url"`
MessageStream string `json:"MessageStream"`
HttpAuth *HttpAuth `json:"HttpAuth,omitempty"`
HttpHeaders []HttpHeader `json:"HttpHeaders,omitempty"`
Triggers *PostmarkTriggers `json:"Triggers"`
}
PostmarkWebhookResponse represents the response from Postmark API for webhook operations
type PreviewSegmentResponse ¶
type PublishBlogPostRequest ¶
type PublishBlogPostRequest struct {
ID string `json:"id"`
PublishedAt *time.Time `json:"published_at,omitempty"` // Optional custom timestamp
Timezone string `json:"timezone,omitempty"` // Optional IANA timezone
}
PublishBlogPostRequest defines the request to publish a blog post
func (*PublishBlogPostRequest) Validate ¶
func (r *PublishBlogPostRequest) Validate() error
Validate validates the publish blog post request
type PublishBlogThemeRequest ¶
type PublishBlogThemeRequest struct {
Version int `json:"version"`
}
PublishBlogThemeRequest defines the request to publish a blog theme
func (*PublishBlogThemeRequest) Validate ¶
func (r *PublishBlogThemeRequest) Validate() error
Validate validates the publish blog theme request
type RegisterWebhookRequest ¶
type RegisterWebhookRequest struct {
WorkspaceID string `json:"workspace_id"`
IntegrationID string `json:"integration_id"`
EventTypes []EmailEventType `json:"event_types"`
}
RegisterWebhookRequest defines the request to register webhooks
func (*RegisterWebhookRequest) Validate ¶
func (r *RegisterWebhookRequest) Validate() error
Validate validates the RegisterWebhookRequest
type RemoveContactFromListRequest ¶
type RemoveContactFromListRequest struct {
WorkspaceID string `json:"workspace_id"`
Email string `json:"email"`
ListID string `json:"list_id"`
}
func (*RemoveContactFromListRequest) Validate ¶
func (r *RemoveContactFromListRequest) Validate() (err error)
type RemoveFromListNodeConfig ¶
type RemoveFromListNodeConfig struct {
ListID string `json:"list_id"`
}
RemoveFromListNodeConfig configures a remove-from-list node
func (RemoveFromListNodeConfig) Validate ¶
func (c RemoveFromListNodeConfig) Validate() error
Validate validates the remove-from-list node config
type ResourcePermissions ¶
ResourcePermissions defines read/write permissions for a specific resource
type ResumeBroadcastRequest ¶
type ResumeBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
}
ResumeBroadcastRequest defines the request to resume a paused broadcast
func (*ResumeBroadcastRequest) Validate ¶
func (r *ResumeBroadcastRequest) Validate() error
Validate validates the resume broadcast request
type RootSigninInput ¶
type RootSigninInput struct {
Email string `json:"email"`
Timestamp int64 `json:"timestamp"`
Signature string `json:"signature"`
}
RootSigninInput represents the request for root user programmatic signin
type SEOSettings ¶
type SEOSettings struct {
MetaTitle string `json:"meta_title,omitempty"` // SEO meta title
MetaDescription string `json:"meta_description,omitempty"` // SEO meta description
OGTitle string `json:"og_title,omitempty"` // Open Graph title
OGDescription string `json:"og_description,omitempty"` // Open Graph description
OGImage string `json:"og_image,omitempty"` // Open Graph image URL
CanonicalURL string `json:"canonical_url,omitempty"` // Canonical URL
Keywords []string `json:"keywords,omitempty"` // SEO keywords
MetaRobots string `json:"meta_robots,omitempty"` // Robots meta tag content (e.g., "index,follow", "noindex,nofollow")
}
SEOSettings contains web page SEO configuration (without slug) Reusable across workspace (homepage), blog categories, and blog posts
func (*SEOSettings) MergeWithDefaults ¶
func (s *SEOSettings) MergeWithDefaults(defaults *SEOSettings) *SEOSettings
MergeWithDefaults merges the current SEO settings with defaults, preferring non-empty values
func (*SEOSettings) Scan ¶
func (s *SEOSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type SESBounce ¶
type SESBounce struct {
BounceType string `json:"bounceType"`
BounceSubType string `json:"bounceSubType"`
BouncedRecipients []SESBouncedRecipient `json:"bouncedRecipients"`
Timestamp string `json:"timestamp"`
FeedbackID string `json:"feedbackId"`
ReportingMTA string `json:"reportingMTA"`
}
SESBounce represents a bounce in an SES notification
type SESBounceNotification ¶
type SESBounceNotification struct {
EventType string `json:"eventType"`
Bounce SESBounce `json:"bounce"`
Mail SESMail `json:"mail"`
}
SESBounceNotification represents an SES bounce notification
type SESBouncedRecipient ¶
type SESBouncedRecipient struct {
EmailAddress string `json:"emailAddress"`
Action string `json:"action"`
Status string `json:"status"`
DiagnosticCode string `json:"diagnosticCode"`
}
SESBouncedRecipient represents a bounced recipient in an SES notification
type SESClient ¶
type SESClient interface {
ListConfigurationSetsWithContext(ctx context.Context, input *ses.ListConfigurationSetsInput, opts ...request.Option) (*ses.ListConfigurationSetsOutput, error)
CreateConfigurationSetWithContext(ctx context.Context, input *ses.CreateConfigurationSetInput, opts ...request.Option) (*ses.CreateConfigurationSetOutput, error)
DeleteConfigurationSetWithContext(ctx context.Context, input *ses.DeleteConfigurationSetInput, opts ...request.Option) (*ses.DeleteConfigurationSetOutput, error)
DescribeConfigurationSetWithContext(ctx context.Context, input *ses.DescribeConfigurationSetInput, opts ...request.Option) (*ses.DescribeConfigurationSetOutput, error)
CreateConfigurationSetEventDestinationWithContext(ctx context.Context, input *ses.CreateConfigurationSetEventDestinationInput, opts ...request.Option) (*ses.CreateConfigurationSetEventDestinationOutput, error)
UpdateConfigurationSetEventDestinationWithContext(ctx context.Context, input *ses.UpdateConfigurationSetEventDestinationInput, opts ...request.Option) (*ses.UpdateConfigurationSetEventDestinationOutput, error)
DeleteConfigurationSetEventDestinationWithContext(ctx context.Context, input *ses.DeleteConfigurationSetEventDestinationInput, opts ...request.Option) (*ses.DeleteConfigurationSetEventDestinationOutput, error)
SendEmailWithContext(ctx context.Context, input *ses.SendEmailInput, opts ...request.Option) (*ses.SendEmailOutput, error)
SendRawEmailWithContext(ctx context.Context, input *ses.SendRawEmailInput, opts ...request.Option) (*ses.SendRawEmailOutput, error)
}
SESWebhookClient defines the interface for SES client operations related to webhook management
type SESCommonHeaders ¶
type SESCommonHeaders struct {
From []string `json:"from"`
To []string `json:"to"`
MessageID string `json:"messageId"`
Subject string `json:"subject"`
}
SESCommonHeaders represents common headers in an SES notification
type SESComplainedRecipient ¶
type SESComplainedRecipient struct {
EmailAddress string `json:"emailAddress"`
}
SESComplainedRecipient represents a complained recipient in an SES notification
type SESComplaint ¶
type SESComplaint struct {
ComplainedRecipients []SESComplainedRecipient `json:"complainedRecipients"`
Timestamp string `json:"timestamp"`
FeedbackID string `json:"feedbackId"`
ComplaintFeedbackType string `json:"complaintFeedbackType"`
}
SESComplaint represents a complaint in an SES notification
type SESComplaintNotification ¶
type SESComplaintNotification struct {
EventType string `json:"eventType"`
Complaint SESComplaint `json:"complaint"`
Mail SESMail `json:"mail"`
}
SESComplaintNotification represents an SES complaint notification
type SESConfigurationSetEventDestination ¶
type SESConfigurationSetEventDestination struct {
Name string `json:"name"`
ConfigurationSetName string `json:"configuration_set_name"`
Enabled bool `json:"enabled"`
MatchingEventTypes []string `json:"matching_event_types"`
SNSDestination *SESTopicConfig `json:"sns_destination,omitempty"`
}
SESConfigurationSetEventDestination represents SES event destination configuration
type SESDelivery ¶
type SESDelivery struct {
Timestamp string `json:"timestamp"`
ProcessingTimeMillis int `json:"processingTimeMillis"`
Recipients []string `json:"recipients"`
SMTPResponse string `json:"smtpResponse"`
RemoteMtaIP string `json:"remoteMtaIp"`
ReportingMTA string `json:"reportingMTA"`
}
SESDelivery represents a delivery in an SES notification
type SESDeliveryNotification ¶
type SESDeliveryNotification struct {
EventType string `json:"eventType"`
Delivery SESDelivery `json:"delivery"`
Mail SESMail `json:"mail"`
}
SESDeliveryNotification represents an SES delivery notification
type SESMail ¶
type SESMail struct {
Timestamp string `json:"timestamp"`
MessageID string `json:"messageId"`
Source string `json:"source"`
Destination []string `json:"destination"`
HeadersTruncated bool `json:"headersTruncated"`
Headers []SESHeader `json:"headers"`
CommonHeaders SESCommonHeaders `json:"commonHeaders"`
Tags map[string][]string `json:"tags"`
}
SESMail represents the mail part of an SES notification
type SESMessageAttribute ¶
SESMessageAttribute represents a message attribute in SES webhook
type SESServiceInterface ¶
type SESServiceInterface interface {
// ListConfigurationSets lists all configuration sets
ListConfigurationSets(ctx context.Context, config AmazonSESSettings) ([]string, error)
// CreateConfigurationSet creates a new configuration set
CreateConfigurationSet(ctx context.Context, config AmazonSESSettings, name string) error
// DeleteConfigurationSet deletes a configuration set
DeleteConfigurationSet(ctx context.Context, config AmazonSESSettings, name string) error
// CreateSNSTopic creates a new SNS topic for notifications
CreateSNSTopic(ctx context.Context, config AmazonSESSettings, topicConfig SESTopicConfig) (string, error)
// DeleteSNSTopic deletes an SNS topic
DeleteSNSTopic(ctx context.Context, config AmazonSESSettings, topicARN string) error
// CreateEventDestination creates an event destination in a configuration set
CreateEventDestination(ctx context.Context, config AmazonSESSettings, destination SESConfigurationSetEventDestination) error
// UpdateEventDestination updates an event destination
UpdateEventDestination(ctx context.Context, config AmazonSESSettings, destination SESConfigurationSetEventDestination) error
// DeleteEventDestination deletes an event destination
DeleteEventDestination(ctx context.Context, config AmazonSESSettings, configSetName, destinationName string) error
// ListEventDestinations lists all event destinations for a configuration set
ListEventDestinations(ctx context.Context, config AmazonSESSettings, configSetName string) ([]SESConfigurationSetEventDestination, error)
}
SESServiceInterface defines operations for managing Amazon SES webhooks via SNS
type SESTopicConfig ¶
type SESTopicConfig struct {
TopicARN string `json:"topic_arn"`
TopicName string `json:"topic_name,omitempty"`
NotificationEndpoint string `json:"notification_endpoint"`
Protocol string `json:"protocol"` // Usually "https"
}
SESTopicConfig represents AWS SNS topic configuration
type SESWebhookClient ¶
type SESWebhookClient interface {
CreateConfigurationSetWithContext(ctx aws.Context, input *ses.CreateConfigurationSetInput, opts ...request.Option) (*ses.CreateConfigurationSetOutput, error)
DeleteConfigurationSetWithContext(ctx aws.Context, input *ses.DeleteConfigurationSetInput, opts ...request.Option) (*ses.DeleteConfigurationSetOutput, error)
ListConfigurationSetsWithContext(ctx aws.Context, input *ses.ListConfigurationSetsInput, opts ...request.Option) (*ses.ListConfigurationSetsOutput, error)
DescribeConfigurationSetWithContext(ctx aws.Context, input *ses.DescribeConfigurationSetInput, opts ...request.Option) (*ses.DescribeConfigurationSetOutput, error)
CreateConfigurationSetEventDestinationWithContext(ctx aws.Context, input *ses.CreateConfigurationSetEventDestinationInput, opts ...request.Option) (*ses.CreateConfigurationSetEventDestinationOutput, error)
UpdateConfigurationSetEventDestinationWithContext(ctx aws.Context, input *ses.UpdateConfigurationSetEventDestinationInput, opts ...request.Option) (*ses.UpdateConfigurationSetEventDestinationOutput, error)
DeleteConfigurationSetEventDestinationWithContext(ctx aws.Context, input *ses.DeleteConfigurationSetEventDestinationInput, opts ...request.Option) (*ses.DeleteConfigurationSetEventDestinationOutput, error)
}
SESWebhookClient defines the interface for interacting with AWS SES service
type SESWebhookPayload ¶
type SESWebhookPayload struct {
Type string `json:"Type"`
MessageID string `json:"MessageId"`
TopicARN string `json:"TopicArn"`
Message string `json:"Message"`
Timestamp string `json:"Timestamp"`
SignatureVersion string `json:"SignatureVersion"`
Signature string `json:"Signature"`
SigningCertURL string `json:"SigningCertURL"`
UnsubscribeURL string `json:"UnsubscribeURL"`
SubscribeURL string `json:"SubscribeURL,omitempty"`
Token string `json:"Token,omitempty"`
MessageAttributes map[string]SESMessageAttribute `json:"MessageAttributes"`
}
SESWebhookPayload represents an Amazon SES webhook payload
type SMTPSettings ¶
type SMTPSettings struct {
Host string `json:"host"`
Port int `json:"port"`
EncryptedUsername string `json:"encrypted_username,omitempty"`
EncryptedPassword string `json:"encrypted_password,omitempty"`
UseTLS bool `json:"use_tls"`
// decoded username, not stored in the database
// decoded password , not stored in the database
Username string `json:"username"`
Password string `json:"password,omitempty"`
}
SMTPSettings contains configuration for SMTP email server
func (*SMTPSettings) DecryptPassword ¶
func (s *SMTPSettings) DecryptPassword(passphrase string) error
func (*SMTPSettings) DecryptUsername ¶
func (s *SMTPSettings) DecryptUsername(passphrase string) error
func (*SMTPSettings) EncryptPassword ¶
func (s *SMTPSettings) EncryptPassword(passphrase string) error
func (*SMTPSettings) EncryptUsername ¶
func (s *SMTPSettings) EncryptUsername(passphrase string) error
func (*SMTPSettings) Validate ¶
func (s *SMTPSettings) Validate(passphrase string) error
type SMTPWebhookPayload ¶
type SMTPWebhookPayload struct {
Event string `json:"event"`
Timestamp string `json:"timestamp"`
MessageID string `json:"message_id"`
Recipient string `json:"recipient"`
Metadata map[string]string `json:"metadata,omitempty"`
Tags []string `json:"tags,omitempty"`
Reason string `json:"reason,omitempty"`
Description string `json:"description,omitempty"`
BounceCategory string `json:"bounce_category,omitempty"`
DiagnosticCode string `json:"diagnostic_code,omitempty"`
ComplaintType string `json:"complaint_type,omitempty"`
}
SMTPWebhookPayload represents an SMTP webhook payload SMTP doesn't typically have a built-in webhook system, so this is a generic structure that could be used with a third-party SMTP provider that offers webhooks
type SNSClient ¶
type SNSClient interface {
CreateTopicWithContext(ctx context.Context, input *sns.CreateTopicInput, opts ...request.Option) (*sns.CreateTopicOutput, error)
DeleteTopicWithContext(ctx context.Context, input *sns.DeleteTopicInput, opts ...request.Option) (*sns.DeleteTopicOutput, error)
SubscribeWithContext(ctx context.Context, input *sns.SubscribeInput, opts ...request.Option) (*sns.SubscribeOutput, error)
GetTopicAttributesWithContext(ctx context.Context, input *sns.GetTopicAttributesInput, opts ...request.Option) (*sns.GetTopicAttributesOutput, error)
}
SNSWebhookClient defines the interface for SNS client operations related to webhook management
type SNSWebhookClient ¶
type SNSWebhookClient interface {
CreateTopicWithContext(ctx aws.Context, input *sns.CreateTopicInput, opts ...request.Option) (*sns.CreateTopicOutput, error)
DeleteTopicWithContext(ctx aws.Context, input *sns.DeleteTopicInput, opts ...request.Option) (*sns.DeleteTopicOutput, error)
SubscribeWithContext(ctx aws.Context, input *sns.SubscribeInput, opts ...request.Option) (*sns.SubscribeOutput, error)
GetTopicAttributesWithContext(ctx aws.Context, input *sns.GetTopicAttributesInput, opts ...request.Option) (*sns.GetTopicAttributesOutput, error)
}
SNSWebhookClient defines the interface for interacting with AWS SNS service
type ScheduleBroadcastRequest ¶
type ScheduleBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
SendNow bool `json:"send_now"`
ScheduledDate string `json:"scheduled_date,omitempty"`
ScheduledTime string `json:"scheduled_time,omitempty"`
Timezone string `json:"timezone,omitempty"`
UseRecipientTimezone bool `json:"use_recipient_timezone"`
}
ScheduleBroadcastRequest defines the request to schedule a broadcast
func (*ScheduleBroadcastRequest) Validate ¶
func (r *ScheduleBroadcastRequest) Validate() error
Validate validates the schedule broadcast request
type ScheduleSettings ¶
type ScheduleSettings struct {
IsScheduled bool `json:"is_scheduled"`
ScheduledDate string `json:"scheduled_date,omitempty"` // Format: YYYY-MM-dd
ScheduledTime string `json:"scheduled_time,omitempty"` // Format: HH:mm
Timezone string `json:"timezone,omitempty"` // IANA timezone format, e.g. "America/New_York"
UseRecipientTimezone bool `json:"use_recipient_timezone"`
}
ScheduleSettings defines when a broadcast will be sent
func (*ScheduleSettings) ParseScheduledDateTime ¶
func (s *ScheduleSettings) ParseScheduledDateTime() (time.Time, error)
ParseScheduledDateTime parses the ScheduledDate and ScheduledTime fields and returns a time.Time
func (*ScheduleSettings) Scan ¶
func (s *ScheduleSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
func (*ScheduleSettings) SetScheduledDateTime ¶
func (s *ScheduleSettings) SetScheduledDateTime(t time.Time, timezone string) error
SetScheduledDateTime formats a time.Time as ScheduledDate and ScheduledTime strings
type Segment ¶
type Segment struct {
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
Tree *TreeNode `json:"tree"`
Timezone string `json:"timezone"`
Version int64 `json:"version"`
Status string `json:"status"`
GeneratedSQL *string `json:"generated_sql,omitempty"`
GeneratedArgs JSONArray `json:"generated_args,omitempty"` // Array of query arguments in order
RecomputeAfter *time.Time `json:"recompute_after,omitempty"` // When segment should be recomputed (for relative date filters)
DBCreatedAt time.Time `json:"db_created_at"`
DBUpdatedAt time.Time `json:"db_updated_at"`
UsersCount int `json:"users_count"` // joined server-side
}
Segment represents a user segment for filtering contacts
func ScanSegment ¶
ScanSegment scans a segment from the database
type SegmentRepository ¶
type SegmentRepository interface {
// CreateSegment creates a new segment in the database
CreateSegment(ctx context.Context, workspaceID string, segment *Segment) error
// GetSegmentByID retrieves a segment by its ID
GetSegmentByID(ctx context.Context, workspaceID string, id string) (*Segment, error)
// GetSegments retrieves all segments, optionally with contact counts
GetSegments(ctx context.Context, workspaceID string, withCount bool) ([]*Segment, error)
// UpdateSegment updates an existing segment
UpdateSegment(ctx context.Context, workspaceID string, segment *Segment) error
// DeleteSegment deletes a segment
DeleteSegment(ctx context.Context, workspaceID string, id string) error
// AddContactToSegment adds a contact to a segment membership
AddContactToSegment(ctx context.Context, workspaceID string, email string, segmentID string, version int64) error
// RemoveContactFromSegment removes a contact from a segment
RemoveContactFromSegment(ctx context.Context, workspaceID string, email string, segmentID string) error
// RemoveOldMemberships removes contact_segment records with old versions
RemoveOldMemberships(ctx context.Context, workspaceID string, segmentID string, currentVersion int64) error
// GetContactSegments retrieves all segments a contact belongs to
GetContactSegments(ctx context.Context, workspaceID string, email string) ([]*Segment, error)
// GetSegmentContactCount gets the count of contacts in a segment
GetSegmentContactCount(ctx context.Context, workspaceID string, segmentID string) (int, error)
// PreviewSegment executes a segment query and returns the count of matching contacts
PreviewSegment(ctx context.Context, workspaceID string, sqlQuery string, args []interface{}, limit int) (int, error)
// GetSegmentsDueForRecompute retrieves segments that need recomputation (recompute_after <= now)
GetSegmentsDueForRecompute(ctx context.Context, workspaceID string, limit int) ([]*Segment, error)
// UpdateRecomputeAfter updates only the recompute_after field for a segment
UpdateRecomputeAfter(ctx context.Context, workspaceID string, segmentID string, recomputeAfter *time.Time) error
}
type SegmentService ¶
type SegmentService interface {
// CreateSegment creates a new segment
CreateSegment(ctx context.Context, req *CreateSegmentRequest) (*Segment, error)
// GetSegment retrieves a segment by ID
GetSegment(ctx context.Context, req *GetSegmentRequest) (*Segment, error)
// ListSegments retrieves all segments
ListSegments(ctx context.Context, req *GetSegmentsRequest) ([]*Segment, error)
// UpdateSegment updates an existing segment
UpdateSegment(ctx context.Context, req *UpdateSegmentRequest) (*Segment, error)
// DeleteSegment deletes a segment by ID
DeleteSegment(ctx context.Context, req *DeleteSegmentRequest) error
// RebuildSegment triggers a rebuild of a segment
RebuildSegment(ctx context.Context, workspaceID, segmentID string) error
// PreviewSegment previews the contacts that would match a segment tree
PreviewSegment(ctx context.Context, workspaceID string, tree *TreeNode, limit int) (*PreviewSegmentResponse, error)
// GetSegmentContacts retrieves the contacts belonging to a segment
GetSegmentContacts(ctx context.Context, workspaceID, segmentID string, limit, offset int) ([]string, error)
}
SegmentService provides operations for managing segments
type SegmentStatus ¶
type SegmentStatus string
SegmentStatus represents the status of a segment
const ( SegmentStatusActive SegmentStatus = "active" SegmentStatusDeleted SegmentStatus = "deleted" SegmentStatusBuilding SegmentStatus = "building" )
func (SegmentStatus) Validate ¶
func (s SegmentStatus) Validate() error
Validate checks if the segment status is valid
type SelectWinnerRequest ¶
type SelectWinnerRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
TemplateID string `json:"template_id"`
}
SelectWinnerRequest represents the request to select a winning variation
func (*SelectWinnerRequest) Validate ¶
func (r *SelectWinnerRequest) Validate() error
Validate validates the select winner request
type SendBroadcastState ¶
type SendBroadcastState struct {
BroadcastID string `json:"broadcast_id"`
TotalRecipients int `json:"total_recipients"`
EnqueuedCount int `json:"enqueued_count"` // Emails added to queue (was SentCount)
FailedCount int `json:"failed_count"` // Template/build failures during enqueueing
ChannelType string `json:"channel_type"`
RecipientOffset int64 `json:"recipient_offset"`
// LastProcessedEmail is the cursor for keyset pagination - stores the last email processed
// to enable deterministic pagination across task executions (fixes Issue #157)
LastProcessedEmail string `json:"last_processed_email,omitempty"`
// New fields for A/B testing phases
Phase string `json:"phase"` // "test", "winner", or "single"
TestPhaseCompleted bool `json:"test_phase_completed"`
TestPhaseRecipientCount int `json:"test_phase_recipient_count"`
WinnerPhaseRecipientCount int `json:"winner_phase_recipient_count"`
}
SendBroadcastState contains state specific to broadcast enqueueing tasks
type SendEmailProviderRequest ¶
type SendEmailProviderRequest struct {
WorkspaceID string `validate:"required"`
IntegrationID string `validate:"required"`
MessageID string `validate:"required"`
FromAddress string `validate:"required"`
FromName string `validate:"required"`
To string `validate:"required"`
Subject string `validate:"required"`
Content string `validate:"required"`
Provider *EmailProvider `validate:"required"`
EmailOptions EmailOptions
}
SendEmailProviderRequest encapsulates all parameters needed to send an email via a provider
func (*SendEmailProviderRequest) Validate ¶
func (r *SendEmailProviderRequest) Validate() error
Validate ensures all required fields are present and valid
type SendEmailRequest ¶
type SendEmailRequest struct {
// Core identification
WorkspaceID string `validate:"required"`
IntegrationID string `validate:"required"`
MessageID string `validate:"required"`
ExternalID *string
AutomationID *string // Automation this email is sent from (nullable for broadcasts/transactional)
// Target and content
Contact *Contact `validate:"required"`
TemplateConfig ChannelTemplate `validate:"required"`
MessageData MessageData
// Configuration
TrackingSettings notifuse_mjml.TrackingSettings
EmailProvider *EmailProvider `validate:"required"`
EmailOptions EmailOptions
}
SendEmailRequest encapsulates all parameters needed to send an email using a template
func (*SendEmailRequest) Validate ¶
func (r *SendEmailRequest) Validate() error
Validate ensures all required fields are present and valid
type SendToIndividualRequest ¶
type SendToIndividualRequest struct {
WorkspaceID string `json:"workspace_id"`
BroadcastID string `json:"broadcast_id"`
RecipientEmail string `json:"recipient_email"`
TemplateID string `json:"template_id,omitempty"`
}
SendToIndividualRequest defines the request to send a broadcast to an individual
func (*SendToIndividualRequest) Validate ¶
func (r *SendToIndividualRequest) Validate() error
Validate validates the send to individual request
type SendTransactionalRequest ¶
type SendTransactionalRequest struct {
WorkspaceID string `json:"workspace_id"`
Notification TransactionalNotificationSendParams `json:"notification"`
}
SendTransactionalRequest represents a request to send a transactional notification
func (*SendTransactionalRequest) Validate ¶
func (req *SendTransactionalRequest) Validate() error
Validate validates the send request
type Session ¶
type Session struct {
ID string `json:"id" db:"id"`
UserID string `json:"user_id" db:"user_id"`
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
MagicCode *string `json:"magic_code,omitempty" db:"magic_code"`
MagicCodeExpires *time.Time `json:"magic_code_expires,omitempty" db:"magic_code_expires_at"`
}
Session represents a user session
type SetUserPermissionsRequest ¶
type SetUserPermissionsRequest struct {
WorkspaceID string `json:"workspace_id"`
UserID string `json:"user_id"`
Permissions UserPermissions `json:"permissions"`
}
SetUserPermissionsRequest defines the request structure for setting user permissions
func (*SetUserPermissionsRequest) Validate ¶
func (r *SetUserPermissionsRequest) Validate() error
Validate validates the set user permissions request
type Setting ¶
type Setting struct {
Key string `json:"key"`
Value string `json:"value"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Setting represents a system setting
type SettingRepository ¶
type SettingRepository interface {
// Get retrieves a setting by key
Get(ctx context.Context, key string) (*Setting, error)
// Set creates or updates a setting
Set(ctx context.Context, key, value string) error
// Delete removes a setting by key
Delete(ctx context.Context, key string) error
// List retrieves all settings
List(ctx context.Context) ([]*Setting, error)
// SetLastCronRun updates the last cron execution timestamp
SetLastCronRun(ctx context.Context) error
// GetLastCronRun retrieves the last cron execution timestamp
GetLastCronRun(ctx context.Context) (*time.Time, error)
}
SettingRepository defines the interface for setting-related database operations
type SignInInput ¶
type SignInInput struct {
Email string `json:"email"`
}
type SparkPostMSys ¶
type SparkPostMSys struct {
MessageEvent *SparkPostMessageEvent `json:"message_event,omitempty"`
}
SparkPostMSys contains the event data from SparkPost
type SparkPostMessageEvent ¶
type SparkPostMessageEvent struct {
Type string `json:"type"`
CampaignID string `json:"campaign_id"`
MessageID string `json:"message_id"`
Timestamp string `json:"timestamp"`
RecipientTo string `json:"rcpt_to"`
RecipientMeta map[string]interface{} `json:"rcpt_meta,omitempty"`
Tags []string `json:"tags,omitempty"`
Transmission string `json:"transmission_id,omitempty"`
IPAddress string `json:"ip_address,omitempty"`
MessageFrom string `json:"msg_from,omitempty"`
QueueTime string `json:"queue_time,omitempty"`
// bounce fields
BounceClass string `json:"bounce_class,omitempty"`
Reason string `json:"reason,omitempty"`
RawReason string `json:"raw_reason,omitempty"`
Error string `json:"error_code,omitempty"`
// delivery fields
DeliveryMethod string `json:"delv_method,omitempty"`
MailboxProvider string `json:"mailbox_provider,omitempty"`
MailboxProviderRegion string `json:"mailbox_provider_region,omitempty"`
// spam fields
FeedbackType string `json:"fbtype,omitempty"`
}
type SparkPostServiceInterface ¶
type SparkPostServiceInterface interface {
// ListWebhooks retrieves all registered webhooks
ListWebhooks(ctx context.Context, config SparkPostSettings) (*SparkPostWebhookListResponse, error)
// CreateWebhook creates a new webhook
CreateWebhook(ctx context.Context, config SparkPostSettings, webhook SparkPostWebhook) (*SparkPostWebhookResponse, error)
// GetWebhook retrieves a webhook by ID
GetWebhook(ctx context.Context, config SparkPostSettings, webhookID string) (*SparkPostWebhookResponse, error)
// UpdateWebhook updates an existing webhook
UpdateWebhook(ctx context.Context, config SparkPostSettings, webhookID string, webhook SparkPostWebhook) (*SparkPostWebhookResponse, error)
// DeleteWebhook deletes a webhook by ID
DeleteWebhook(ctx context.Context, config SparkPostSettings, webhookID string) error
// TestWebhook sends a test event to a webhook
TestWebhook(ctx context.Context, config SparkPostSettings, webhookID string) error
// ValidateWebhook validates a webhook's configuration
ValidateWebhook(ctx context.Context, config SparkPostSettings, webhook SparkPostWebhook) (bool, error)
}
SparkPostServiceInterface defines operations for managing SparkPost webhooks
type SparkPostSettings ¶
type SparkPostSettings struct {
EncryptedAPIKey string `json:"encrypted_api_key,omitempty"`
SandboxMode bool `json:"sandbox_mode"`
Endpoint string `json:"endpoint"`
// decoded API key, not stored in the database
APIKey string `json:"api_key,omitempty"`
}
SparkPostSettings contains configuration for SparkPost email provider
func (*SparkPostSettings) DecryptAPIKey ¶
func (s *SparkPostSettings) DecryptAPIKey(passphrase string) error
func (*SparkPostSettings) EncryptAPIKey ¶
func (s *SparkPostSettings) EncryptAPIKey(passphrase string) error
func (*SparkPostSettings) Validate ¶
func (s *SparkPostSettings) Validate(passphrase string) error
type SparkPostWebhook ¶
type SparkPostWebhook struct {
ID string `json:"id,omitempty"`
Name string `json:"name"`
Target string `json:"target"`
Events []string `json:"events"`
Active bool `json:"active"`
AuthType string `json:"auth_type,omitempty"` // "none", "basic", "oauth2"
AuthToken string `json:"auth_token,omitempty"`
AuthRequest map[string]interface{} `json:"auth_request,omitempty"`
CustomHeaders map[string]string `json:"custom_headers,omitempty"`
}
SparkPostWebhook represents a webhook configuration in SparkPost
type SparkPostWebhookListResponse ¶
type SparkPostWebhookListResponse struct {
Results []SparkPostWebhook `json:"results"`
}
SparkPostWebhookListResponse represents the response for listing webhooks
type SparkPostWebhookPayload ¶
type SparkPostWebhookPayload struct {
MSys SparkPostMSys `json:"msys"`
}
SparkPostWebhookPayload represents the webhook payload from SparkPost
type SparkPostWebhookResponse ¶
type SparkPostWebhookResponse struct {
Results SparkPostWebhook `json:"results"`
}
SparkPostWebhookResponse represents a response for webhook operations
type SubscribeToListsRequest ¶
type SubscribeToListsRequest struct {
WorkspaceID string `json:"workspace_id"`
Contact Contact `json:"contact"`
ListIDs []string `json:"list_ids"`
}
func (*SubscribeToListsRequest) Validate ¶
func (r *SubscribeToListsRequest) Validate() (err error)
type SupabaseAuthEmailHookSettings ¶
type SupabaseAuthEmailHookSettings struct {
SignatureKey string `json:"signature_key,omitempty"` // Accepts plaintext key in requests (cleared before API responses)
EncryptedSignatureKey string `json:"encrypted_signature_key,omitempty"` // Encrypted key (stored and returned in API responses)
}
SupabaseAuthEmailHookSettings configures the Send Email Hook Hook activation is controlled in Supabase, not here
func (*SupabaseAuthEmailHookSettings) DecryptSignatureKey ¶
func (s *SupabaseAuthEmailHookSettings) DecryptSignatureKey(passphrase string) error
DecryptSignatureKey decrypts the signature key for auth email hook
func (*SupabaseAuthEmailHookSettings) EncryptSignatureKey ¶
func (s *SupabaseAuthEmailHookSettings) EncryptSignatureKey(passphrase string) error
EncryptSignatureKey encrypts the signature key for auth email hook
func (*SupabaseAuthEmailHookSettings) Validate ¶
func (s *SupabaseAuthEmailHookSettings) Validate() error
Validate validates the auth email hook settings
type SupabaseAuthEmailWebhook ¶
type SupabaseAuthEmailWebhook struct {
User SupabaseUser `json:"user"`
EmailData SupabaseEmailData `json:"email_data"`
}
SupabaseAuthEmailWebhook represents the webhook payload for Send Email Hook
type SupabaseBeforeUserCreatedWebhook ¶
type SupabaseBeforeUserCreatedWebhook struct {
Metadata SupabaseWebhookMetadata `json:"metadata"`
User SupabaseUser `json:"user"`
}
SupabaseBeforeUserCreatedWebhook represents the webhook payload for Before User Created Hook
type SupabaseEmailActionType ¶
type SupabaseEmailActionType string
const ( SupabaseEmailActionSignup SupabaseEmailActionType = "signup" SupabaseEmailActionInvite SupabaseEmailActionType = "invite" SupabaseEmailActionMagicLink SupabaseEmailActionType = "magiclink" SupabaseEmailActionRecovery SupabaseEmailActionType = "recovery" SupabaseEmailActionEmailChange SupabaseEmailActionType = "email_change" // SupabaseEmailActionEmail SupabaseEmailActionType = "email" SupabaseEmailActionReauthentication SupabaseEmailActionType = "reauthentication" )
type SupabaseEmailData ¶
type SupabaseEmailData struct {
Token string `json:"token"`
TokenHash string `json:"token_hash"`
RedirectTo string `json:"redirect_to"`
EmailActionType string `json:"email_action_type"`
SiteURL string `json:"site_url"`
TokenNew string `json:"token_new,omitempty"` // For email_change in secure mode
TokenHashNew string `json:"token_hash_new,omitempty"` // For email_change in secure mode
}
SupabaseEmailData contains email-specific data for auth hooks
type SupabaseIntegrationSettings ¶
type SupabaseIntegrationSettings struct {
AuthEmailHook SupabaseAuthEmailHookSettings `json:"auth_email_hook"`
BeforeUserCreatedHook SupabaseUserCreatedHookSettings `json:"before_user_created_hook"`
}
SupabaseIntegrationSettings contains all Supabase integration configuration
func (*SupabaseIntegrationSettings) DecryptSignatureKeys ¶
func (s *SupabaseIntegrationSettings) DecryptSignatureKeys(passphrase string) error
DecryptSignatureKeys decrypts both signature keys
func (*SupabaseIntegrationSettings) EncryptSignatureKeys ¶
func (s *SupabaseIntegrationSettings) EncryptSignatureKeys(passphrase string) error
EncryptSignatureKeys encrypts both signature keys
func (*SupabaseIntegrationSettings) Validate ¶
func (s *SupabaseIntegrationSettings) Validate(passphrase string) error
Validate validates the Supabase integration settings
type SupabaseTemplateMappings ¶
type SupabaseTemplateMappings struct {
Signup string `json:"signup"`
MagicLink string `json:"magiclink"`
Recovery string `json:"recovery"`
EmailChange string `json:"email_change"` // Single template used for both current and new email addresses
Invite string `json:"invite"`
Reauthentication string `json:"reauthentication"`
}
SupabaseTemplateMappings maps each email action type to a Notifuse template ID
func (*SupabaseTemplateMappings) GetTemplateID ¶
func (m *SupabaseTemplateMappings) GetTemplateID(actionType SupabaseEmailActionType) (string, error)
GetTemplateID returns the template ID for a given email action type For email_change, the same template is used for both current and new email addresses (matching Supabase's behavior where there's only one customizable email_change template)
type SupabaseUser ¶
type SupabaseUser struct {
ID string `json:"id"`
Aud string `json:"aud"`
Role string `json:"role"`
Email string `json:"email"`
EmailNew string `json:"new_email,omitempty"` // Present in email_change webhooks
Phone string `json:"phone"`
AppMetadata map[string]interface{} `json:"app_metadata"`
UserMetadata map[string]interface{} `json:"user_metadata"`
Identities []interface{} `json:"identities"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
IsAnonymous bool `json:"is_anonymous"`
}
SupabaseUser represents a Supabase user object
func (*SupabaseUser) ToContact ¶
func (u *SupabaseUser) ToContact(customJSONField string) (*Contact, error)
ToContact converts a Supabase user to a Notifuse Contact customJSONField specifies which custom_json field to use (e.g., "custom_json_1", "custom_json_2", etc.) If empty, user_metadata will not be mapped
type SupabaseUserCreatedHookSettings ¶
type SupabaseUserCreatedHookSettings struct {
SignatureKey string `json:"signature_key,omitempty"` // Accepts plaintext key in requests (cleared before API responses)
EncryptedSignatureKey string `json:"encrypted_signature_key,omitempty"` // Encrypted key (stored and returned in API responses)
AddUserToLists []string `json:"add_user_to_lists,omitempty"` // Optional lists to add contacts to
CustomJSONField string `json:"custom_json_field,omitempty"` // Which custom_json field to use (default: custom_json_1)
RejectDisposableEmail bool `json:"reject_disposable_email,omitempty"` // Reject user creation if email is disposable
}
SupabaseUserCreatedHookSettings configures the Before User Created Hook Hook activation is controlled in Supabase, not here
func (*SupabaseUserCreatedHookSettings) DecryptSignatureKey ¶
func (s *SupabaseUserCreatedHookSettings) DecryptSignatureKey(passphrase string) error
DecryptSignatureKey decrypts the signature key for user created hook
func (*SupabaseUserCreatedHookSettings) EncryptSignatureKey ¶
func (s *SupabaseUserCreatedHookSettings) EncryptSignatureKey(passphrase string) error
EncryptSignatureKey encrypts the signature key for user created hook
func (*SupabaseUserCreatedHookSettings) Validate ¶
func (s *SupabaseUserCreatedHookSettings) Validate() error
Validate validates the user created hook settings
type SupabaseWebhookMetadata ¶
type SupabaseWebhookMetadata struct {
UUID string `json:"uuid"` // Request ID
Time string `json:"time"` // ISO 8601 timestamp
Name string `json:"name"` // Hook name
IPAddress string `json:"ip_address"` // User's IP address
}
SupabaseWebhookMetadata contains metadata about the webhook request
type TOCItem ¶
type TOCItem struct {
ID string `json:"id"` // Anchor ID for linking (e.g., "introduction")
Level int `json:"level"` // Heading level (2-6)
Text string `json:"text"` // Heading text content
}
TOCItem represents a single item in the table of contents
type Task ¶
type Task struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
Type string `json:"type"`
Status TaskStatus `json:"status"`
Progress float64 `json:"progress"`
State *TaskState `json:"state,omitempty"` // Typed state struct
ErrorMessage *string `json:"error_message,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastRunAt *time.Time `json:"last_run_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
NextRunAfter *time.Time `json:"next_run_after,omitempty"`
TimeoutAfter *time.Time `json:"timeout_after,omitempty"`
MaxRuntime int `json:"max_runtime"` // Maximum runtime in seconds
MaxRetries int `json:"max_retries"`
RetryCount int `json:"retry_count"`
RetryInterval int `json:"retry_interval"` // Retry interval in seconds
BroadcastID *string `json:"broadcast_id,omitempty"` // Optional reference to a broadcast
}
Task represents a background task that can be executed in multiple steps
type TaskExecutor ¶
type TaskExecutor interface {
// ExecutePendingTasks finds and executes pending tasks
ExecutePendingTasks(ctx context.Context, maxTasks int) error
// ExecuteTask executes a specific task
ExecuteTask(ctx context.Context, workspaceID, taskID string, timeoutAt time.Time) error
// RegisterProcessor registers a task processor for a specific task type
RegisterProcessor(processor TaskProcessor)
}
TaskExecutor is responsible for executing tasks
type TaskFilter ¶
type TaskFilter struct {
Status []TaskStatus
Type []string
CreatedAfter *time.Time
CreatedBefore *time.Time
Limit int
Offset int
}
TaskFilter defines the filtering criteria for task listing
type TaskListResponse ¶
type TaskListResponse struct {
Tasks []*Task `json:"tasks"`
TotalCount int `json:"total_count"`
Limit int `json:"limit"`
Offset int `json:"offset"`
HasMore bool `json:"has_more"`
}
TaskListResponse defines the response for listing tasks
type TaskProcessor ¶
type TaskProcessor interface {
// Process executes or continues a task, returns whether the task has been completed
Process(ctx context.Context, task *Task, timeoutAt time.Time) (completed bool, err error)
// CanProcess returns whether this processor can handle the given task type
CanProcess(taskType string) bool
}
TaskProcessor defines the interface for task execution
type TaskRepository ¶
type TaskRepository interface {
// Transaction support
WithTransaction(ctx context.Context, fn func(*sql.Tx) error) error
// Create adds a new task
Create(ctx context.Context, workspace string, task *Task) error
CreateTx(ctx context.Context, tx *sql.Tx, workspace string, task *Task) error
// Get retrieves a task by ID
Get(ctx context.Context, workspace, id string) (*Task, error)
GetTx(ctx context.Context, tx *sql.Tx, workspace, id string) (*Task, error)
// Get a task by broadcast ID
GetTaskByBroadcastID(ctx context.Context, workspace, broadcastID string) (*Task, error)
GetTaskByBroadcastIDTx(ctx context.Context, tx *sql.Tx, workspace, broadcastID string) (*Task, error)
// Update updates an existing task
Update(ctx context.Context, workspace string, task *Task) error
UpdateTx(ctx context.Context, tx *sql.Tx, workspace string, task *Task) error
// Delete removes a task
Delete(ctx context.Context, workspace, id string) error
DeleteAll(ctx context.Context, workspace string) error
// List retrieves tasks with optional filtering
List(ctx context.Context, workspace string, filter TaskFilter) ([]*Task, int, error)
// GetNextBatch retrieves tasks that are ready to be processed
GetNextBatch(ctx context.Context, limit int) ([]*Task, error)
// MarkAsRunning marks a task as running and sets timeout
MarkAsRunning(ctx context.Context, workspace, id string, timeoutAfter time.Time) error
MarkAsRunningTx(ctx context.Context, tx *sql.Tx, workspace, id string, timeoutAfter time.Time) error
// SaveState saves the current state of a running task
SaveState(ctx context.Context, workspace, id string, progress float64, state *TaskState) error
SaveStateTx(ctx context.Context, tx *sql.Tx, workspace, id string, progress float64, state *TaskState) error
// MarkAsCompleted marks a task as completed and saves the final state
MarkAsCompleted(ctx context.Context, workspace, id string, state *TaskState) error
MarkAsCompletedTx(ctx context.Context, tx *sql.Tx, workspace, id string, state *TaskState) error
// MarkAsFailed marks a task as failed
MarkAsFailed(ctx context.Context, workspace, id string, errorMsg string) error
MarkAsFailedTx(ctx context.Context, tx *sql.Tx, workspace, id string, errorMsg string) error
// MarkAsPaused marks a task as paused (e.g., due to timeout)
MarkAsPaused(ctx context.Context, workspace, id string, nextRunAfter time.Time, progress float64, state *TaskState) error
MarkAsPausedTx(ctx context.Context, tx *sql.Tx, workspace, id string, nextRunAfter time.Time, progress float64, state *TaskState) error
// MarkAsPending marks a task as pending (e.g., for recurring tasks)
MarkAsPending(ctx context.Context, workspace, id string, nextRunAfter time.Time, progress float64, state *TaskState) error
MarkAsPendingTx(ctx context.Context, tx *sql.Tx, workspace, id string, nextRunAfter time.Time, progress float64, state *TaskState) error
}
TaskRepository defines methods for task persistence
type TaskService ¶
type TaskService interface {
RegisterProcessor(processor TaskProcessor)
GetProcessor(taskType string) (TaskProcessor, error)
CreateTask(ctx context.Context, workspace string, task *Task) error
GetTask(ctx context.Context, workspace, id string) (*Task, error)
ListTasks(ctx context.Context, workspace string, filter TaskFilter) (*TaskListResponse, error)
DeleteTask(ctx context.Context, workspace, id string) error
ExecutePendingTasks(ctx context.Context, maxTasks int) error
ExecuteTask(ctx context.Context, workspace, taskID string, timeoutAt time.Time) error
GetLastCronRun(ctx context.Context) (*time.Time, error)
SubscribeToBroadcastEvents(eventBus EventBus)
IsAutoExecuteEnabled() bool
}
type TaskState ¶
type TaskState struct {
// Common fields for all task types
Progress float64 `json:"progress,omitempty"`
Message string `json:"message,omitempty"`
// Specialized states for different task types - only one will be used based on task type
SendBroadcast *SendBroadcastState `json:"send_broadcast,omitempty"`
BuildSegment *BuildSegmentState `json:"build_segment,omitempty"`
}
TaskState represents the state of a task, with specialized fields for different task types
type TaskStatus ¶
type TaskStatus string
TaskStatus represents the current state of a task
const ( // TaskStatusPending is for tasks that haven't started yet TaskStatusPending TaskStatus = "pending" // TaskStatusRunning is for tasks that are currently running TaskStatusRunning TaskStatus = "running" // TaskStatusCompleted is for tasks that have completed successfully TaskStatusCompleted TaskStatus = "completed" // TaskStatusFailed is for tasks that have failed TaskStatusFailed TaskStatus = "failed" // TaskStatusPaused is for tasks that were paused due to timeout TaskStatusPaused TaskStatus = "paused" )
type TelemetryMetrics ¶
type TelemetryMetrics struct {
ContactsCount int `json:"contacts_count"`
BroadcastsCount int `json:"broadcasts_count"`
TransactionalCount int `json:"transactional_count"`
MessagesCount int `json:"messages_count"`
ListsCount int `json:"lists_count"`
SegmentsCount int `json:"segments_count"`
UsersCount int `json:"users_count"`
BlogPostsCount int `json:"blog_posts_count"`
LastMessageAt string `json:"last_message_at"`
}
TelemetryMetrics represents aggregated metrics for a workspace
type TelemetryRepository ¶
type TelemetryRepository interface {
// GetWorkspaceMetrics retrieves aggregated metrics for a specific workspace
GetWorkspaceMetrics(ctx context.Context, workspaceID string) (*TelemetryMetrics, error)
// CountContacts counts the total number of contacts in a workspace
CountContacts(ctx context.Context, db *sql.DB) (int, error)
// CountBroadcasts counts the total number of broadcasts in a workspace
CountBroadcasts(ctx context.Context, db *sql.DB) (int, error)
// CountTransactional counts the total number of transactional notifications in a workspace
CountTransactional(ctx context.Context, db *sql.DB) (int, error)
// CountMessages counts the total number of messages in a workspace
CountMessages(ctx context.Context, db *sql.DB) (int, error)
// CountLists counts the total number of lists in a workspace
CountLists(ctx context.Context, db *sql.DB) (int, error)
// CountSegments counts the total number of segments in a workspace
CountSegments(ctx context.Context, db *sql.DB) (int, error)
// CountUsers counts the total number of users in a workspace from the system database
CountUsers(ctx context.Context, systemDB *sql.DB, workspaceID string) (int, error)
// CountBlogPosts counts the total number of blog posts in a workspace
CountBlogPosts(ctx context.Context, db *sql.DB) (int, error)
// GetLastMessageAt gets the timestamp of the last message sent from the workspace
GetLastMessageAt(ctx context.Context, db *sql.DB) (string, error)
}
TelemetryRepository defines the interface for telemetry data operations
type Template ¶
type Template struct {
ID string `json:"id"`
Name string `json:"name"`
Version int64 `json:"version"`
Channel string `json:"channel"` // email or web
Email *EmailTemplate `json:"email,omitempty"`
Web *WebTemplate `json:"web,omitempty"`
Category string `json:"category"`
TemplateMacroID *string `json:"template_macro_id,omitempty"`
IntegrationID *string `json:"integration_id,omitempty"` // Set if template is managed by an integration (e.g., Supabase)
TestData MapOfAny `json:"test_data,omitempty"`
Settings MapOfAny `json:"settings,omitempty"` // Channels specific 3rd-party settings
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
type TemplateBlock ¶
type TemplateBlock struct {
ID string `json:"id"`
Name string `json:"name"`
Block notifuse_mjml.EmailBlock `json:"block"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
TemplateBlock represents a reusable email block template
func (TemplateBlock) MarshalJSON ¶
func (tb TemplateBlock) MarshalJSON() ([]byte, error)
MarshalJSON implements custom JSON marshaling for TemplateBlock
func (*TemplateBlock) UnmarshalJSON ¶
func (tb *TemplateBlock) UnmarshalJSON(data []byte) error
UnmarshalJSON implements custom JSON unmarshaling for TemplateBlock
type TemplateBlockService ¶
type TemplateBlockService interface {
// CreateTemplateBlock creates a new template block
CreateTemplateBlock(ctx context.Context, workspaceID string, block *TemplateBlock) error
// GetTemplateBlock retrieves a template block by ID
GetTemplateBlock(ctx context.Context, workspaceID string, id string) (*TemplateBlock, error)
// ListTemplateBlocks retrieves all template blocks for a workspace
ListTemplateBlocks(ctx context.Context, workspaceID string) ([]*TemplateBlock, error)
// UpdateTemplateBlock updates an existing template block
UpdateTemplateBlock(ctx context.Context, workspaceID string, block *TemplateBlock) error
// DeleteTemplateBlock deletes a template block by ID
DeleteTemplateBlock(ctx context.Context, workspaceID string, id string) error
}
TemplateBlockService provides operations for managing template blocks
type TemplateCategory ¶
type TemplateCategory string
const ( TemplateCategoryMarketing TemplateCategory = "marketing" TemplateCategoryTransactional TemplateCategory = "transactional" TemplateCategoryWelcome TemplateCategory = "welcome" TemplateCategoryOptIn TemplateCategory = "opt_in" TemplateCategoryUnsubscribe TemplateCategory = "unsubscribe" TemplateCategoryBounce TemplateCategory = "bounce" TemplateCategoryBlocklist TemplateCategory = "blocklist" TemplateCategoryBlog TemplateCategory = "blog" TemplateCategoryOther TemplateCategory = "other" )
func (TemplateCategory) Validate ¶
func (t TemplateCategory) Validate() error
type TemplateDataRequest ¶
type TemplateDataRequest struct {
WorkspaceID string `json:"workspace_id"`
WorkspaceSecretKey string `json:"workspace_secret_key"`
ContactWithList ContactWithList `json:"contact_with_list"`
MessageID string `json:"message_id"`
ProvidedData MapOfAny `json:"provided_data,omitempty"`
TrackingSettings notifuse_mjml.TrackingSettings `json:"tracking_settings"`
Broadcast *Broadcast `json:"broadcast,omitempty"`
}
TemplateDataRequest groups parameters for building template data
func (*TemplateDataRequest) Validate ¶
func (r *TemplateDataRequest) Validate() error
Validate ensures that the template data request has all required fields
type TemplateReference ¶
func (*TemplateReference) Scan ¶
func (t *TemplateReference) Scan(val interface{}) error
scan implements the sql.Scanner interface
func (*TemplateReference) Validate ¶
func (t *TemplateReference) Validate() error
type TemplateRepository ¶
type TemplateRepository interface {
// CreateTemplate creates a new template in the database
CreateTemplate(ctx context.Context, workspaceID string, template *Template) error
// GetTemplateByID retrieves a template by its ID and optional version
GetTemplateByID(ctx context.Context, workspaceID string, id string, version int64) (*Template, error)
// GetTemplateLatestVersion retrieves the latest version of a template
GetTemplateLatestVersion(ctx context.Context, workspaceID string, id string) (int64, error)
// GetTemplates retrieves all templates
GetTemplates(ctx context.Context, workspaceID string, category string, channel string) ([]*Template, error)
// UpdateTemplate updates an existing template, creating a new version
UpdateTemplate(ctx context.Context, workspaceID string, template *Template) error
// DeleteTemplate deletes a template
DeleteTemplate(ctx context.Context, workspaceID string, id string) error
}
TemplateRepository provides database operations for templates
type TemplateService ¶
type TemplateService interface {
// CreateTemplate creates a new template
CreateTemplate(ctx context.Context, workspaceID string, template *Template) error
// GetTemplateByID retrieves a template by ID and optional version
GetTemplateByID(ctx context.Context, workspaceID string, id string, version int64) (*Template, error)
// GetTemplates retrieves all templates
GetTemplates(ctx context.Context, workspaceID string, category string, channel string) ([]*Template, error)
// UpdateTemplate updates an existing template
UpdateTemplate(ctx context.Context, workspaceID string, template *Template) error
// DeleteTemplate deletes a template by ID
DeleteTemplate(ctx context.Context, workspaceID string, id string) error
// CompileTemplate compiles a visual editor tree to MJML and HTML
CompileTemplate(ctx context.Context, payload CompileTemplateRequest) (*CompileTemplateResponse, error) // Use notifuse_mjml.EmailBlock
}
TemplateService provides operations for managing templates
type TestEmailProviderRequest ¶
type TestEmailProviderRequest struct {
Provider EmailProvider `json:"provider"`
To string `json:"to"`
WorkspaceID string `json:"workspace_id"`
}
TestEmailProviderRequest is the request for testing an email provider It includes the provider config, a recipient email, and the workspace ID
type TestEmailProviderResponse ¶
type TestEmailProviderResponse struct {
Success bool `json:"success"`
Error string `json:"error,omitempty"`
}
TestEmailProviderResponse is the response for testing an email provider It can be extended to include more details if needed
type TestResultsResponse ¶
type TestResultsResponse struct {
BroadcastID string `json:"broadcast_id"`
Status string `json:"status"`
TestStartedAt *time.Time `json:"test_started_at,omitempty"`
TestCompletedAt *time.Time `json:"test_completed_at,omitempty"`
VariationResults map[string]*VariationResult `json:"variation_results"`
RecommendedWinner string `json:"recommended_winner,omitempty"`
WinningTemplate string `json:"winning_template,omitempty"`
IsAutoSendWinner bool `json:"is_auto_send_winner"`
}
TestResultsResponse represents the response for A/B test results
type TestTemplateRequest ¶
type TestTemplateRequest struct {
WorkspaceID string `json:"workspace_id"`
TemplateID string `json:"template_id"`
IntegrationID string `json:"integration_id"`
SenderID string `json:"sender_id"`
RecipientEmail string `json:"recipient_email"`
EmailOptions EmailOptions `json:"email_options,omitempty"`
}
TestTemplateRequest represents a request to test a template
func (*TestTemplateRequest) Validate ¶
func (r *TestTemplateRequest) Validate() error
type TestTemplateResponse ¶
type TestTemplateResponse struct {
Success bool `json:"success"`
Error string `json:"error,omitempty"`
}
TestTemplateResponse represents the response from testing a template
type TestWinnerMetric ¶
type TestWinnerMetric string
TestWinnerMetric defines the metric used to determine the winning A/B test variation
const ( TestWinnerMetricOpenRate TestWinnerMetric = "open_rate" TestWinnerMetricClickRate TestWinnerMetric = "click_rate" )
type TimelineListRequest ¶
TimelineListRequest represents the request parameters for listing timeline entries
func (*TimelineListRequest) FromQuery ¶
func (r *TimelineListRequest) FromQuery(query url.Values) error
FromQuery parses query parameters into a TimelineListRequest
func (*TimelineListRequest) Validate ¶
func (r *TimelineListRequest) Validate() error
Validate validates the timeline list request
type TimelineListResponse ¶
type TimelineListResponse struct {
Timeline []*ContactTimelineEntry `json:"timeline"`
NextCursor *string `json:"next_cursor,omitempty"`
}
TimelineListResponse represents the response for listing timeline entries
type TimelineTriggerConfig ¶
type TimelineTriggerConfig struct {
EventKind string `json:"event_kind"` // Timeline event type to listen for
ListID *string `json:"list_id,omitempty"` // Required for list.* events
SegmentID *string `json:"segment_id,omitempty"` // Required for segment.* events
CustomEventName *string `json:"custom_event_name,omitempty"` // Required for custom_event
UpdatedFields []string `json:"updated_fields,omitempty"` // For contact.updated: only trigger on these field changes
Conditions *TreeNode `json:"conditions"` // Reuse segments condition system
Frequency TriggerFrequency `json:"frequency"`
}
TimelineTriggerConfig defines the trigger configuration for an automation
func (*TimelineTriggerConfig) Validate ¶
func (c *TimelineTriggerConfig) Validate() error
Validate validates the trigger configuration
type TransactionalChannel ¶
type TransactionalChannel string
TransactionalChannel represents supported notification channels
const ( // TransactionalChannelEmail for email notifications TransactionalChannelEmail TransactionalChannel = "email" )
type TransactionalNotification ¶
type TransactionalNotification struct {
ID string `json:"id"` // Unique identifier for the notification, also used for API triggering
Name string `json:"name"`
Description string `json:"description"`
Channels ChannelTemplates `json:"channels"`
TrackingSettings notifuse_mjml.TrackingSettings `json:"tracking_settings"`
Metadata MapOfAny `json:"metadata,omitempty"`
IntegrationID *string `json:"integration_id,omitempty"` // Set if notification is managed by an integration (e.g., Supabase)
// System timestamps
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
TransactionalNotification represents a transactional notification configuration
type TransactionalNotificationCreateParams ¶
type TransactionalNotificationCreateParams struct {
ID string `json:"id" validate:"required"` // Unique identifier for API triggering
Name string `json:"name" validate:"required"`
Description string `json:"description"`
Channels ChannelTemplates `json:"channels" validate:"required,min=1"`
TrackingSettings notifuse_mjml.TrackingSettings `json:"tracking_settings"`
Metadata MapOfAny `json:"metadata,omitempty"`
}
TransactionalNotificationCreateParams contains the parameters for creating a new transactional notification
type TransactionalNotificationRepository ¶
type TransactionalNotificationRepository interface {
// Create adds a new transactional notification
Create(ctx context.Context, workspace string, notification *TransactionalNotification) error
// Update updates an existing transactional notification
Update(ctx context.Context, workspace string, notification *TransactionalNotification) error
// Get retrieves a transactional notification by ID
Get(ctx context.Context, workspace, id string) (*TransactionalNotification, error)
// List retrieves all transactional notifications with optional filtering
List(ctx context.Context, workspace string, filter map[string]interface{}, limit, offset int) ([]*TransactionalNotification, int, error)
// Delete soft-deletes a transactional notification
Delete(ctx context.Context, workspace, id string) error
}
TransactionalNotificationRepository defines methods for transactional notification persistence
type TransactionalNotificationSendParams ¶
type TransactionalNotificationSendParams struct {
ID string `json:"id" validate:"required"` // ID of the notification to send
ExternalID *string `json:"external_id,omitempty"` // External ID for idempotency checks
Contact *Contact `json:"contact" validate:"required"` // Contact to send the notification to
Channels []TransactionalChannel `json:"channels,omitempty"` // Specific channels to send through (if empty, use all configured channels)
Data MapOfAny `json:"data,omitempty"` // Data to populate the template with
Metadata MapOfAny `json:"metadata,omitempty"` // Additional metadata for tracking
EmailOptions EmailOptions `json:"email_options,omitempty"` // Email options for the notification
}
TransactionalNotificationSendParams contains the parameters for sending a transactional notification
type TransactionalNotificationService ¶
type TransactionalNotificationService interface {
// CreateNotification creates a new transactional notification
CreateNotification(ctx context.Context, workspaceID string, params TransactionalNotificationCreateParams) (*TransactionalNotification, error)
// UpdateNotification updates an existing transactional notification
UpdateNotification(ctx context.Context, workspaceID, id string, params TransactionalNotificationUpdateParams) (*TransactionalNotification, error)
// GetNotification retrieves a transactional notification by ID
GetNotification(ctx context.Context, workspaceID, id string) (*TransactionalNotification, error)
// ListNotifications retrieves all transactional notifications with optional filtering
ListNotifications(ctx context.Context, workspaceID string, filter map[string]interface{}, limit, offset int) ([]*TransactionalNotification, int, error)
// DeleteNotification soft-deletes a transactional notification
DeleteNotification(ctx context.Context, workspaceID, id string) error
// SendNotification sends a transactional notification to a contact
SendNotification(ctx context.Context, workspaceID string, params TransactionalNotificationSendParams) (string, error)
TestTemplate(ctx context.Context, workspaceID string, templateID string, integrationID string, senderID string, recipientEmail string, options EmailOptions) error
}
TransactionalNotificationService defines the interface for transactional notification operations
type TransactionalNotificationUpdateParams ¶
type TransactionalNotificationUpdateParams struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Channels ChannelTemplates `json:"channels,omitempty"`
TrackingSettings notifuse_mjml.TrackingSettings `json:"tracking_settings,omitempty"`
Metadata MapOfAny `json:"metadata,omitempty"`
}
TransactionalNotificationUpdateParams contains the parameters for updating an existing transactional notification
type TreeNode ¶
type TreeNode struct {
Kind string `json:"kind"` // "branch" or "leaf"
Branch *TreeNodeBranch `json:"branch,omitempty"`
Leaf *TreeNodeLeaf `json:"leaf,omitempty"`
}
TreeNode represents a node in the segment tree structure It can be either a branch (AND/OR operator) or a leaf (actual condition)
func TreeNodeFromJSON ¶
TreeNodeFromJSON parses a JSON string into a TreeNode
func TreeNodeFromMapOfAny ¶
TreeNodeFromMapOfAny converts a MapOfAny to a TreeNode
func (*TreeNode) HasRelativeDates ¶
HasRelativeDates checks if the tree contains any relative date filters that require daily recomputation (e.g., "in_the_last_days")
func (*TreeNode) ToMapOfAny ¶
ToMapOfAny converts a TreeNode to MapOfAny (for backwards compatibility)
type TreeNodeBranch ¶
type TreeNodeBranch struct {
Operator string `json:"operator"` // "and" or "or"
Leaves []*TreeNode `json:"leaves"`
}
TreeNodeBranch represents a logical operator (AND/OR) with child nodes
func (*TreeNodeBranch) Validate ¶
func (b *TreeNodeBranch) Validate() error
Validate validates a branch node
type TreeNodeLeaf ¶
type TreeNodeLeaf struct {
Source string `json:"source"` // "contacts", "contact_lists", "contact_timeline", "custom_events_goals"
Contact *ContactCondition `json:"contact,omitempty"`
ContactList *ContactListCondition `json:"contact_list,omitempty"`
ContactTimeline *ContactTimelineCondition `json:"contact_timeline,omitempty"`
CustomEventsGoal *CustomEventsGoalCondition `json:"custom_events_goal,omitempty"`
}
TreeNodeLeaf represents an actual condition on a data source
func (*TreeNodeLeaf) Validate ¶
func (l *TreeNodeLeaf) Validate() error
Validate validates a leaf node
type TriggerFrequency ¶
type TriggerFrequency string
TriggerFrequency defines how often an automation should trigger for a contact
const ( TriggerFrequencyOnce TriggerFrequency = "once" // Only trigger on first occurrence TriggerFrequencyEveryTime TriggerFrequency = "every_time" // Trigger on each occurrence )
func (TriggerFrequency) IsValid ¶
func (f TriggerFrequency) IsValid() bool
IsValid checks if the trigger frequency is valid
type UTMParameters ¶
type UTMParameters struct {
Source string `json:"source,omitempty"`
Medium string `json:"medium,omitempty"`
Campaign string `json:"campaign,omitempty"`
Term string `json:"term,omitempty"`
Content string `json:"content,omitempty"`
}
UTMParameters contains UTM tracking parameters for the broadcast
func (*UTMParameters) Scan ¶
func (u *UTMParameters) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type UnpublishBlogPostRequest ¶
type UnpublishBlogPostRequest struct {
ID string `json:"id"`
}
UnpublishBlogPostRequest defines the request to unpublish a blog post
func (*UnpublishBlogPostRequest) Validate ¶
func (r *UnpublishBlogPostRequest) Validate() error
Validate validates the unpublish blog post request
type UnsubscribeFromListsRequest ¶
type UnsubscribeFromListsRequest struct {
WorkspaceID string `json:"wid"`
Email string `json:"email"`
EmailHMAC string `json:"email_hmac"`
ListIDs []string `json:"lids"`
MessageID string `json:"mid"`
}
func (*UnsubscribeFromListsRequest) FromURLParams ¶
func (r *UnsubscribeFromListsRequest) FromURLParams(queryParams url.Values) (err error)
from url params
type UpdateAutomationRequest ¶
type UpdateAutomationRequest struct {
WorkspaceID string `json:"workspace_id"`
Automation *Automation `json:"automation"`
}
UpdateAutomationRequest represents the request to update an automation
func (*UpdateAutomationRequest) Validate ¶
func (r *UpdateAutomationRequest) Validate() error
Validate validates the update automation request
type UpdateBlogCategoryRequest ¶
type UpdateBlogCategoryRequest struct {
ID string `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description,omitempty"`
SEO *SEOSettings `json:"seo,omitempty"`
}
UpdateBlogCategoryRequest defines the request to update a blog category
func (*UpdateBlogCategoryRequest) Validate ¶
func (r *UpdateBlogCategoryRequest) Validate() error
Validate validates the update blog category request
type UpdateBlogPostRequest ¶
type UpdateBlogPostRequest struct {
ID string `json:"id"`
CategoryID string `json:"category_id"`
Slug string `json:"slug"`
Title string `json:"title"`
TemplateID string `json:"template_id"`
TemplateVersion int `json:"template_version"`
Excerpt string `json:"excerpt,omitempty"`
FeaturedImageURL string `json:"featured_image_url,omitempty"`
Authors []BlogAuthor `json:"authors"`
ReadingTimeMinutes int `json:"reading_time_minutes"`
SEO *SEOSettings `json:"seo,omitempty"`
}
UpdateBlogPostRequest defines the request to update a blog post
func (*UpdateBlogPostRequest) Validate ¶
func (r *UpdateBlogPostRequest) Validate() error
Validate validates the update blog post request
type UpdateBlogThemeRequest ¶
type UpdateBlogThemeRequest struct {
Version int `json:"version"`
Files BlogThemeFiles `json:"files"`
Notes *string `json:"notes,omitempty"`
}
UpdateBlogThemeRequest defines the request to update a blog theme
func (*UpdateBlogThemeRequest) Validate ¶
func (r *UpdateBlogThemeRequest) Validate() error
Validate validates the update blog theme request
type UpdateBroadcastRequest ¶
type UpdateBroadcastRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
Audience AudienceSettings `json:"audience"`
Schedule ScheduleSettings `json:"schedule"`
TestSettings BroadcastTestSettings `json:"test_settings"`
TrackingEnabled bool `json:"tracking_enabled"`
UTMParameters *UTMParameters `json:"utm_parameters,omitempty"`
Metadata MapOfAny `json:"metadata,omitempty"`
}
UpdateBroadcastRequest defines the request to update an existing broadcast
type UpdateContactListStatusRequest ¶
type UpdateContactListStatusRequest struct {
WorkspaceID string `json:"workspace_id"`
Email string `json:"email"`
ListID string `json:"list_id"`
Status string `json:"status"`
}
func (*UpdateContactListStatusRequest) Validate ¶
func (r *UpdateContactListStatusRequest) Validate() (workspaceID string, list *ContactList, err error)
type UpdateContactListStatusResult ¶
type UpdateContactListStatusResult struct {
Success bool `json:"success"`
Message string `json:"message"`
Found bool `json:"found"` // Whether the contact was found in the list
}
UpdateContactListStatusResult represents the result of updating a contact list status
type UpdateIntegrationRequest ¶
type UpdateIntegrationRequest struct {
WorkspaceID string `json:"workspace_id"`
IntegrationID string `json:"integration_id"`
Name string `json:"name"`
Provider EmailProvider `json:"provider,omitempty"` // For email integrations
SupabaseSettings *SupabaseIntegrationSettings `json:"supabase_settings,omitempty"` // For Supabase integrations
LLMProvider *LLMProvider `json:"llm_provider,omitempty"` // For LLM integrations
FirecrawlSettings *FirecrawlSettings `json:"firecrawl_settings,omitempty"` // For Firecrawl integrations
}
UpdateIntegrationRequest defines the request structure for updating an integration
func (*UpdateIntegrationRequest) Validate ¶
func (r *UpdateIntegrationRequest) Validate(passphrase string) error
type UpdateListRequest ¶
type UpdateListRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
IsDoubleOptin bool `json:"is_double_optin"`
IsPublic bool `json:"is_public"`
Description string `json:"description,omitempty"`
DoubleOptInTemplate *TemplateReference `json:"double_optin_template,omitempty"`
}
type UpdateSegmentRequest ¶
type UpdateTemplateBlockRequest ¶
type UpdateTemplateBlockRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
Block notifuse_mjml.EmailBlock `json:"block"`
}
UpdateTemplateBlockRequest defines the request structure for updating a template block
func (*UpdateTemplateBlockRequest) UnmarshalJSON ¶
func (r *UpdateTemplateBlockRequest) UnmarshalJSON(data []byte) error
UnmarshalJSON implements custom JSON unmarshaling for UpdateTemplateBlockRequest
func (*UpdateTemplateBlockRequest) Validate ¶
func (r *UpdateTemplateBlockRequest) Validate() (block *TemplateBlock, workspaceID string, err error)
Validate validates the update template block request
type UpdateTemplateRequest ¶
type UpdateTemplateRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Name string `json:"name"`
Channel string `json:"channel"`
Email *EmailTemplate `json:"email,omitempty"`
Web *WebTemplate `json:"web,omitempty"`
Category string `json:"category"`
TemplateMacroID *string `json:"template_macro_id,omitempty"`
TestData MapOfAny `json:"test_data,omitempty"`
Settings MapOfAny `json:"settings,omitempty"`
}
type UpdateTransactionalRequest ¶
type UpdateTransactionalRequest struct {
WorkspaceID string `json:"workspace_id"`
ID string `json:"id"`
Updates TransactionalNotificationUpdateParams `json:"updates"`
}
UpdateTransactionalRequest represents a request to update a transactional notification
func (*UpdateTransactionalRequest) Validate ¶
func (req *UpdateTransactionalRequest) Validate() error
Validate validates the update request
type UpdateWorkspaceRequest ¶
type UpdateWorkspaceRequest struct {
ID string `json:"id"`
Name string `json:"name"`
Settings WorkspaceSettings `json:"settings"`
}
func (*UpdateWorkspaceRequest) Validate ¶
func (r *UpdateWorkspaceRequest) Validate(passphrase string) error
type UpsertContactOperation ¶
type UpsertContactRequest ¶
type UpsertContactRequest struct {
WorkspaceID string `json:"workspace_id" valid:"required"`
Contact json.RawMessage `json:"contact" valid:"required"`
}
type UpsertCustomEventRequest ¶
type UpsertCustomEventRequest struct {
WorkspaceID string `json:"workspace_id"`
Email string `json:"email"`
EventName string `json:"event_name"`
ExternalID string `json:"external_id"` // Required: unique external resource ID
Properties map[string]interface{} `json:"properties"`
OccurredAt *time.Time `json:"occurred_at,omitempty"` // Optional, defaults to now
IntegrationID *string `json:"integration_id,omitempty"` // Optional integration ID
// Goal tracking fields
GoalName *string `json:"goal_name,omitempty"` // Optional goal name
GoalType *string `json:"goal_type,omitempty"` // purchase, subscription, lead, signup, booking, trial, other
GoalValue *float64 `json:"goal_value,omitempty"` // Required for purchase/subscription, can be negative for refunds
// Soft delete - set to a timestamp to delete, null to restore
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
UpsertCustomEventRequest represents the API request to create or update a custom event Soft-delete by setting deleted_at, restore by setting deleted_at to null
func (*UpsertCustomEventRequest) Validate ¶
func (r *UpsertCustomEventRequest) Validate() error
type User ¶
type User struct {
ID string `json:"id" db:"id"`
Type UserType `json:"type" db:"type"`
Email string `json:"email" db:"email"`
Name string `json:"name,omitempty" db:"name"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
User represents a user in the system
type UserPermissions ¶
type UserPermissions map[PermissionResource]ResourcePermissions
UserPermissions maps resources to their permission settings
func (*UserPermissions) Scan ¶
func (up *UserPermissions) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type UserRepository ¶
type UserRepository interface {
// CreateUser creates a new user in the database
CreateUser(ctx context.Context, user *User) error
// GetUserByEmail retrieves a user by their email address
GetUserByEmail(ctx context.Context, email string) (*User, error)
// GetUserByID retrieves a user by their ID
GetUserByID(ctx context.Context, id string) (*User, error)
// CreateSession creates a new session for a user
CreateSession(ctx context.Context, session *Session) error
// GetSessionByID retrieves a session by its ID
GetSessionByID(ctx context.Context, id string) (*Session, error)
// GetSessionsByUserID retrieves all sessions for a user
GetSessionsByUserID(ctx context.Context, userID string) ([]*Session, error)
// UpdateSession updates an existing session
UpdateSession(ctx context.Context, session *Session) error
// DeleteSession deletes a session by its ID
DeleteSession(ctx context.Context, id string) error
// DeleteAllSessionsByUserID deletes all sessions for a user
DeleteAllSessionsByUserID(ctx context.Context, userID string) error
// Delete removes a user by their ID
Delete(ctx context.Context, id string) error
}
type UserServiceInterface ¶
type UserServiceInterface interface {
SignIn(ctx context.Context, input SignInInput) (string, error)
VerifyCode(ctx context.Context, input VerifyCodeInput) (*AuthResponse, error)
RootSignin(ctx context.Context, input RootSigninInput) (*AuthResponse, error)
VerifyUserSession(ctx context.Context, userID string, sessionID string) (*User, error)
GetUserByID(ctx context.Context, userID string) (*User, error)
GetUserByEmail(ctx context.Context, email string) (*User, error)
Logout(ctx context.Context, userID string) error
}
UserServiceInterface defines the interface for user operations
type UserWorkspace ¶
type UserWorkspace struct {
UserID string `json:"user_id" db:"user_id"`
WorkspaceID string `json:"workspace_id" db:"workspace_id"`
Role string `json:"role" db:"role"`
Permissions UserPermissions `json:"permissions,omitempty" db:"permissions"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
UserWorkspace represents the relationship between a user and a workspace
func (*UserWorkspace) HasPermission ¶
func (uw *UserWorkspace) HasPermission(resource PermissionResource, permissionType PermissionType) bool
HasPermission checks if the user has a specific permission for a resource
func (*UserWorkspace) SetPermissions ¶
func (uw *UserWorkspace) SetPermissions(permissions UserPermissions)
SetPermissions replaces all permissions for the user
func (*UserWorkspace) Validate ¶
func (uw *UserWorkspace) Validate() error
Validate performs validation on the user workspace fields
type UserWorkspaceWithEmail ¶
type UserWorkspaceWithEmail struct {
UserWorkspace
Email string `json:"email" db:"email"`
Type UserType `json:"type" db:"type"`
InvitationExpiresAt *time.Time `json:"invitation_expires_at" db:"invitation_expires_at"`
InvitationID string `json:"invitation_id,omitempty" db:"invitation_id"`
}
UserWorkspaceWithEmail extends UserWorkspace to include user email
type ValidationError ¶
type ValidationError struct {
Message string
}
ValidationError represents an error that occurs due to invalid input or parameters
func (ValidationError) Error ¶
func (e ValidationError) Error() string
Error implements the error interface
type VariationMetrics ¶
type VariationMetrics struct {
Recipients int `json:"recipients"`
Delivered int `json:"delivered"`
Opens int `json:"opens"`
Clicks int `json:"clicks"`
Bounced int `json:"bounced"`
Complained int `json:"complained"`
Unsubscribed int `json:"unsubscribed"`
}
VariationMetrics contains performance metrics for a variation
func (*VariationMetrics) Scan ¶
func (m *VariationMetrics) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
type VariationResult ¶
type VariationResult struct {
TemplateID string `json:"template_id"`
TemplateName string `json:"template_name"`
Recipients int `json:"recipients"` // Total sent emails (used as denominator for rate calculations)
Delivered int `json:"delivered"` // Total delivered emails (ESP-dependent, may not be available)
Opens int `json:"opens"`
Clicks int `json:"clicks"`
OpenRate float64 `json:"open_rate"` // Opens / Recipients
ClickRate float64 `json:"click_rate"` // Clicks / Recipients
}
VariationResult represents the results for a single A/B test variation
type VerifyCodeInput ¶
type WebTemplate ¶
type WebTemplate struct {
Content MapOfAny `json:"content,omitempty"` // Tiptap JSON (source of truth)
HTML string `json:"html,omitempty"` // Pre-rendered HTML for display
PlainText string `json:"plain_text,omitempty"` // Extracted text for search indexing
}
func (WebTemplate) MarshalJSON ¶
func (w WebTemplate) MarshalJSON() ([]byte, error)
MarshalJSON implements custom JSON marshaling for WebTemplate
func (*WebTemplate) Scan ¶
func (w *WebTemplate) Scan(val interface{}) error
func (*WebTemplate) UnmarshalJSON ¶
func (w *WebTemplate) UnmarshalJSON(data []byte) error
UnmarshalJSON implements custom JSON unmarshaling for WebTemplate
func (*WebTemplate) Validate ¶
func (w *WebTemplate) Validate(testData MapOfAny) error
type WebhookDelivery ¶
type WebhookDelivery struct {
ID string `json:"id"`
SubscriptionID string `json:"subscription_id"`
EventType string `json:"event_type"`
Payload map[string]interface{} `json:"payload"`
Status string `json:"status"` // pending, delivering, delivered, failed
Attempts int `json:"attempts"`
MaxAttempts int `json:"max_attempts"`
NextAttemptAt time.Time `json:"next_attempt_at"`
LastAttemptAt *time.Time `json:"last_attempt_at,omitempty"`
DeliveredAt *time.Time `json:"delivered_at,omitempty"`
LastResponseStatus *int `json:"last_response_status,omitempty"`
LastResponseBody *string `json:"last_response_body,omitempty"`
LastError *string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
WebhookDelivery represents a pending or completed webhook delivery
type WebhookDeliveryRepository ¶
type WebhookDeliveryRepository interface {
GetPendingForWorkspace(ctx context.Context, workspaceID string, limit int) ([]*WebhookDelivery, error)
ListAll(ctx context.Context, workspaceID string, subscriptionID *string, limit, offset int) ([]*WebhookDelivery, int, error)
UpdateStatus(ctx context.Context, workspaceID, id string, status string, attempts int, responseStatus *int, responseBody, lastError *string) error
MarkDelivered(ctx context.Context, workspaceID, id string, responseStatus int, responseBody string) error
ScheduleRetry(ctx context.Context, workspaceID, id string, nextAttempt time.Time, attempts int, responseStatus *int, responseBody, lastError *string) error
MarkFailed(ctx context.Context, workspaceID, id string, attempts int, lastError string, responseStatus *int, responseBody *string) error
Create(ctx context.Context, workspaceID string, delivery *WebhookDelivery) error
CleanupOldDeliveries(ctx context.Context, workspaceID string, retentionDays int) (int64, error)
}
WebhookDeliveryRepository defines the interface for webhook delivery data access
type WebhookDeliveryWithSubscription ¶
type WebhookDeliveryWithSubscription struct {
Delivery *WebhookDelivery
Subscription *WebhookSubscription
WorkspaceID string
}
WebhookDeliveryWithSubscription contains a delivery with its associated subscription
type WebhookEndpointStatus ¶
type WebhookEndpointStatus struct {
WebhookID string `json:"webhook_id,omitempty"`
URL string `json:"url"`
EventType EmailEventType `json:"event_type"`
Active bool `json:"active"`
}
WebhookEndpointStatus represents the status of a single webhook endpoint
type WebhookNodeConfig ¶
type WebhookNodeConfig struct {
URL string `json:"url"`
Secret *string `json:"secret,omitempty"` // Optional: becomes Authorization: Bearer <secret>
}
WebhookNodeConfig configures a webhook node
func (WebhookNodeConfig) Validate ¶
func (c WebhookNodeConfig) Validate() error
Validate validates the webhook node config
type WebhookProvider ¶
type WebhookProvider interface {
// RegisterWebhooks registers webhooks for the specified events
RegisterWebhooks(ctx context.Context, workspaceID, integrationID string, baseURL string, eventTypes []EmailEventType, providerConfig *EmailProvider) (*WebhookRegistrationStatus, error)
// GetWebhookStatus checks the current status of webhooks
GetWebhookStatus(ctx context.Context, workspaceID, integrationID string, providerConfig *EmailProvider) (*WebhookRegistrationStatus, error)
// UnregisterWebhooks removes all webhooks for this integration
UnregisterWebhooks(ctx context.Context, workspaceID, integrationID string, providerConfig *EmailProvider) error
}
WebhookProvider defines a common interface for all email providers that support webhooks
type WebhookRegistrationConfig ¶
type WebhookRegistrationConfig struct {
IntegrationID string `json:"integration_id"`
EventTypes []EmailEventType `json:"event_types"`
}
WebhookRegistrationConfig defines the configuration for registering webhooks
type WebhookRegistrationService ¶
type WebhookRegistrationService interface {
// RegisterWebhooks registers the webhook URLs with the email provider
RegisterWebhooks(ctx context.Context, workspaceID string, config *WebhookRegistrationConfig) (*WebhookRegistrationStatus, error)
// UnregisterWebhooks removes all webhook URLs associated with the integration
UnregisterWebhooks(ctx context.Context, workspaceID string, integrationID string) error
// GetWebhookStatus gets the current status of webhooks for the email provider
GetWebhookStatus(ctx context.Context, workspaceID string, integrationID string) (*WebhookRegistrationStatus, error)
}
WebhookRegistrationService defines the interface for registering webhooks with email providers
type WebhookRegistrationStatus ¶
type WebhookRegistrationStatus struct {
EmailProviderKind EmailProviderKind `json:"email_provider_kind"`
IsRegistered bool `json:"is_registered"`
Endpoints []WebhookEndpointStatus `json:"endpoints,omitempty"`
Error string `json:"error,omitempty"`
ProviderDetails map[string]interface{} `json:"provider_details,omitempty"`
}
WebhookRegistrationStatus represents the current status of webhooks for a provider
type WebhookSource ¶
type WebhookSource string
WebhookSource defines the source of the webhook event
const ( // WebhookSourceSES indicates webhook from Amazon SES WebhookSourceSES WebhookSource = "ses" // WebhookSourcePostmark indicates webhook from Postmark WebhookSourcePostmark WebhookSource = "postmark" // WebhookSourceMailgun indicates webhook from Mailgun WebhookSourceMailgun WebhookSource = "mailgun" // WebhookSourceSparkPost indicates webhook from SparkPost WebhookSourceSparkPost WebhookSource = "sparkpost" // WebhookSourceMailjet indicates webhook from Mailjet WebhookSourceMailjet WebhookSource = "mailjet" // WebhookSourceSMTP indicates webhook from SMTP WebhookSourceSMTP WebhookSource = "smtp" // WebhookSourceSupabase indicates webhook from Supabase WebhookSourceSupabase WebhookSource = "supabase" )
type WebhookSubscription ¶
type WebhookSubscription struct {
ID string `json:"id"`
Name string `json:"name"`
URL string `json:"url"`
Secret string `json:"secret"`
Settings WebhookSubscriptionSettings `json:"settings"`
Enabled bool `json:"enabled"`
LastDeliveryAt *time.Time `json:"last_delivery_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
WebhookSubscription represents an outgoing webhook subscription configuration
func (WebhookSubscription) MarshalJSON ¶
func (w WebhookSubscription) MarshalJSON() ([]byte, error)
MarshalJSON implements custom JSON marshaling to flatten settings into top-level fields This maintains backward-compatible API responses while using nested internal structure
type WebhookSubscriptionRepository ¶
type WebhookSubscriptionRepository interface {
Create(ctx context.Context, workspaceID string, sub *WebhookSubscription) error
GetByID(ctx context.Context, workspaceID, id string) (*WebhookSubscription, error)
List(ctx context.Context, workspaceID string) ([]*WebhookSubscription, error)
Update(ctx context.Context, workspaceID string, sub *WebhookSubscription) error
Delete(ctx context.Context, workspaceID, id string) error
UpdateLastDeliveryAt(ctx context.Context, workspaceID, id string, deliveredAt time.Time) error
}
WebhookSubscriptionRepository defines the interface for webhook subscription data access
type WebhookSubscriptionSettings ¶
type WebhookSubscriptionSettings struct {
EventTypes []string `json:"event_types"`
CustomEventFilters *CustomEventFilters `json:"custom_event_filters,omitempty"`
}
WebhookSubscriptionSettings contains event subscription configuration
type Workspace ¶
type Workspace struct {
ID string `json:"id"`
Name string `json:"name"`
Settings WorkspaceSettings `json:"settings"`
Integrations Integrations `json:"integrations"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func ScanWorkspace ¶
ScanWorkspace scans a workspace from the database
func (*Workspace) AddIntegration ¶
func (w *Workspace) AddIntegration(integration Integration)
AddIntegration adds a new integration to the workspace
func (*Workspace) BeforeSave ¶
func (*Workspace) GetEmailProvider ¶
func (w *Workspace) GetEmailProvider(isMarketing bool) (*EmailProvider, error)
GetEmailProvider returns the email provider based on provider type
func (*Workspace) GetEmailProviderWithIntegrationID ¶
func (w *Workspace) GetEmailProviderWithIntegrationID(isMarketing bool) (*EmailProvider, string, error)
GetEmailProviderWithIntegrationID returns both the email provider and integration ID based on provider type
func (*Workspace) GetIntegrationByID ¶
func (w *Workspace) GetIntegrationByID(id string) *Integration
GetIntegrationByID finds an integration by ID in the workspace
func (*Workspace) GetIntegrationsByType ¶
func (w *Workspace) GetIntegrationsByType(integrationType IntegrationType) []*Integration
GetIntegrationsByType returns all integrations of a specific type
func (*Workspace) MarshalJSON ¶
func (*Workspace) RemoveIntegration ¶
RemoveIntegration removes an integration by ID
type WorkspaceInvitation ¶
type WorkspaceInvitation struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
InviterID string `json:"inviter_id"`
Email string `json:"email"`
Permissions UserPermissions `json:"permissions,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
WorkspaceInvitation represents an invitation to a workspace
type WorkspaceRepository ¶
type WorkspaceRepository interface {
Create(ctx context.Context, workspace *Workspace) error
GetByID(ctx context.Context, id string) (*Workspace, error)
GetWorkspaceByCustomDomain(ctx context.Context, hostname string) (*Workspace, error)
List(ctx context.Context) ([]*Workspace, error)
Update(ctx context.Context, workspace *Workspace) error
Delete(ctx context.Context, id string) error
// User workspace management
AddUserToWorkspace(ctx context.Context, userWorkspace *UserWorkspace) error
RemoveUserFromWorkspace(ctx context.Context, userID string, workspaceID string) error
GetUserWorkspaces(ctx context.Context, userID string) ([]*UserWorkspace, error)
GetWorkspaceUsersWithEmail(ctx context.Context, workspaceID string) ([]*UserWorkspaceWithEmail, error)
GetUserWorkspace(ctx context.Context, userID string, workspaceID string) (*UserWorkspace, error)
// User permission management
UpdateUserWorkspacePermissions(ctx context.Context, userWorkspace *UserWorkspace) error
// Workspace invitation management
CreateInvitation(ctx context.Context, invitation *WorkspaceInvitation) error
GetInvitationByID(ctx context.Context, id string) (*WorkspaceInvitation, error)
GetInvitationByEmail(ctx context.Context, workspaceID, email string) (*WorkspaceInvitation, error)
GetWorkspaceInvitations(ctx context.Context, workspaceID string) ([]*WorkspaceInvitation, error)
DeleteInvitation(ctx context.Context, id string) error
IsUserWorkspaceMember(ctx context.Context, userID, workspaceID string) (bool, error)
// Database management
GetConnection(ctx context.Context, workspaceID string) (*sql.DB, error)
GetSystemConnection(ctx context.Context) (*sql.DB, error)
CreateDatabase(ctx context.Context, workspaceID string) error
DeleteDatabase(ctx context.Context, workspaceID string) error
// Transaction management
WithWorkspaceTransaction(ctx context.Context, workspaceID string, fn func(*sql.Tx) error) error
}
type WorkspaceServiceInterface ¶
type WorkspaceServiceInterface interface {
CreateWorkspace(ctx context.Context, id, name, websiteURL, logoURL, coverURL, timezone string, fileManager FileManagerSettings) (*Workspace, error)
GetWorkspace(ctx context.Context, id string) (*Workspace, error)
ListWorkspaces(ctx context.Context) ([]*Workspace, error)
UpdateWorkspace(ctx context.Context, id, name string, settings WorkspaceSettings) (*Workspace, error)
DeleteWorkspace(ctx context.Context, id string) error
GetWorkspaceMembersWithEmail(ctx context.Context, id string) ([]*UserWorkspaceWithEmail, error)
InviteMember(ctx context.Context, workspaceID, email string, permissions UserPermissions) (*WorkspaceInvitation, string, error)
AddUserToWorkspace(ctx context.Context, workspaceID string, userID string, role string, permissions UserPermissions) error
RemoveUserFromWorkspace(ctx context.Context, workspaceID string, userID string) error
TransferOwnership(ctx context.Context, workspaceID string, newOwnerID string, currentOwnerID string) error
CreateAPIKey(ctx context.Context, workspaceID string, emailPrefix string) (string, string, error)
RemoveMember(ctx context.Context, workspaceID string, userIDToRemove string) error
// Invitation management
GetInvitationByID(ctx context.Context, invitationID string) (*WorkspaceInvitation, error)
AcceptInvitation(ctx context.Context, invitationID, workspaceID, email string) (*AuthResponse, error)
DeleteInvitation(ctx context.Context, invitationID string) error
// Integration management
CreateIntegration(ctx context.Context, req CreateIntegrationRequest) (string, error)
UpdateIntegration(ctx context.Context, req UpdateIntegrationRequest) error
DeleteIntegration(ctx context.Context, workspaceID, integrationID string) error
// Permission management
SetUserPermissions(ctx context.Context, workspaceID, userID string, permissions UserPermissions) error
}
WorkspaceServiceInterface defines the interface for workspace operations
type WorkspaceSettings ¶
type WorkspaceSettings struct {
WebsiteURL string `json:"website_url,omitempty"`
LogoURL string `json:"logo_url,omitempty"`
CoverURL string `json:"cover_url,omitempty"`
Timezone string `json:"timezone"`
FileManager FileManagerSettings `json:"file_manager,omitempty"`
TransactionalEmailProviderID string `json:"transactional_email_provider_id,omitempty"`
MarketingEmailProviderID string `json:"marketing_email_provider_id,omitempty"`
EncryptedSecretKey string `json:"encrypted_secret_key,omitempty"`
EmailTrackingEnabled bool `json:"email_tracking_enabled"`
TemplateBlocks []TemplateBlock `json:"template_blocks,omitempty"`
CustomEndpointURL *string `json:"custom_endpoint_url,omitempty"`
CustomFieldLabels map[string]string `json:"custom_field_labels,omitempty"`
BlogEnabled bool `json:"blog_enabled"` // Enable blog feature at workspace level
BlogSettings *BlogSettings `json:"blog_settings,omitempty"` // Blog styling and SEO settings
// decoded secret key, not stored in the database
SecretKey string `json:"-"`
}
WorkspaceSettings contains configurable workspace settings
func (*WorkspaceSettings) Scan ¶
func (b *WorkspaceSettings) Scan(value interface{}) error
Scan implements the sql.Scanner interface for database deserialization
func (*WorkspaceSettings) Validate ¶
func (ws *WorkspaceSettings) Validate(passphrase string) error
Validate validates workspace settings
func (*WorkspaceSettings) ValidateCustomFieldLabels ¶
func (ws *WorkspaceSettings) ValidateCustomFieldLabels() error
ValidateCustomFieldLabels validates custom field label mappings
Source Files
¶
- analytics.go
- attachment.go
- auth.go
- automation.go
- blog.go
- broadcast.go
- contact.go
- contact_list.go
- contact_segment_queue.go
- contact_timeline.go
- custom_event.go
- email_provider.go
- email_provider_mailgun.go
- email_provider_mailjet.go
- email_provider_postmark.go
- email_provider_ses.go
- email_provider_smtp.go
- email_provider_sparkpost.go
- email_queue.go
- errors.go
- event.go
- firecrawl_integration.go
- inbound_webhook_event.go
- list.go
- llm.go
- llm_provider.go
- llm_provider_anthropic.go
- message_history.go
- notification_center.go
- nullable_json.go
- nullables.go
- segment.go
- ses_client.go
- setting.go
- supabase_integration.go
- task.go
- telemetry.go
- template.go
- template_block.go
- timezones.go
- transactional.go
- tree.go
- types.go
- user.go
- webhook_provider.go
- webhook_registration.go
- webhook_subscription.go
- workspace.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package mocks is a generated GoMock package.
|
Package mocks is a generated GoMock package. |