mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-13 20:11:43 -05:00
Replace the single `isAIEnabled` boolean on the Organization model with two independent toggles: `isAISmartToolsEnabled` (for features like survey translation that never touch collected data) and `isAIDataAnalysisEnabled` (for features like dashboards and charts that operate on experience data). This gives organization owners and managers granular control over which categories of AI features are enabled, preparing Formbricks for the first optional AI features in v4.9.
1028 lines
39 KiB
Plaintext
1028 lines
39 KiB
Plaintext
// This is your Prisma schema file,
|
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
extensions = [pgvector(map: "vector")]
|
|
}
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
previewFeatures = ["postgresqlExtensions"]
|
|
}
|
|
|
|
generator json {
|
|
provider = "prisma-json-types-generator"
|
|
}
|
|
|
|
enum PipelineTriggers {
|
|
responseCreated
|
|
responseUpdated
|
|
responseFinished
|
|
}
|
|
|
|
enum WebhookSource {
|
|
user
|
|
zapier
|
|
make
|
|
n8n
|
|
activepieces
|
|
}
|
|
|
|
/// Represents a webhook endpoint for receiving survey-related events.
|
|
/// Webhooks can be configured to receive notifications about response creation, updates, and completion.
|
|
///
|
|
/// @property id - Unique identifier for the webhook
|
|
/// @property name - Optional display name for the webhook
|
|
/// @property url - The endpoint URL where events will be sent
|
|
/// @property source - Origin of the webhook (user, zapier, make, etc.)
|
|
/// @property environment - Associated environment
|
|
/// @property triggers - Types of events that trigger this webhook
|
|
/// @property surveyIds - List of surveys this webhook is monitoring
|
|
model Webhook {
|
|
id String @id @default(cuid())
|
|
name String?
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
|
|
url String
|
|
source WebhookSource @default(user)
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
environmentId String
|
|
triggers PipelineTriggers[]
|
|
surveyIds String[]
|
|
secret String?
|
|
|
|
@@index([environmentId])
|
|
}
|
|
|
|
/// Represents an attribute value associated with a contact.
|
|
/// Used to store custom properties and characteristics of contacts.
|
|
///
|
|
/// @property id - Unique identifier for the attribute
|
|
/// @property attributeKey - Reference to the attribute definition
|
|
/// @property contact - The contact this attribute belongs to
|
|
/// @property value - The string value of the attribute (used for string type + backwards compatibility)
|
|
/// @property valueNumber - Native numeric storage for number type attributes
|
|
/// @property valueDate - Native date storage for date type attributes
|
|
model ContactAttribute {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
attributeKey ContactAttributeKey @relation(fields: [attributeKeyId], references: [id], onDelete: Cascade)
|
|
attributeKeyId String
|
|
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
|
|
contactId String
|
|
value String
|
|
valueNumber Float?
|
|
valueDate DateTime?
|
|
|
|
@@unique([contactId, attributeKeyId])
|
|
@@index([attributeKeyId, value])
|
|
@@index([attributeKeyId, valueNumber])
|
|
@@index([attributeKeyId, valueDate])
|
|
}
|
|
|
|
enum ContactAttributeType {
|
|
default
|
|
custom
|
|
}
|
|
|
|
enum ContactAttributeDataType {
|
|
string
|
|
number
|
|
date
|
|
}
|
|
|
|
/// Defines the possible attributes that can be assigned to contacts.
|
|
/// Acts as a schema for contact attributes within an environment.
|
|
///
|
|
/// @property id - Unique identifier for the attribute key
|
|
/// @property isUnique - Whether the attribute must have unique values across contacts
|
|
/// @property key - The attribute identifier used in the system
|
|
/// @property name - Display name for the attribute
|
|
/// @property type - Whether this is a default or custom attribute
|
|
/// @property dataType - The data type of the attribute (string, number, date)
|
|
/// @property environment - The environment this attribute belongs to
|
|
model ContactAttributeKey {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
isUnique Boolean @default(false)
|
|
key String
|
|
name String?
|
|
description String?
|
|
type ContactAttributeType @default(custom)
|
|
dataType ContactAttributeDataType @default(string)
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
environmentId String
|
|
attributes ContactAttribute[]
|
|
attributeFilters SurveyAttributeFilter[]
|
|
|
|
@@unique([key, environmentId])
|
|
@@index([environmentId, createdAt])
|
|
}
|
|
|
|
/// Represents a person or user who can receive and respond to surveys.
|
|
/// Contacts are environment-specific and can have multiple attributes and responses.
|
|
///
|
|
/// @property id - Unique identifier for the contact
|
|
/// @property environment - The environment this contact belongs to
|
|
/// @property responses - Survey responses from this contact
|
|
/// @property attributes - Custom attributes associated with this contact
|
|
/// @property displays - Record of surveys shown to this contact
|
|
model Contact {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
environmentId String
|
|
responses Response[]
|
|
attributes ContactAttribute[]
|
|
displays Display[]
|
|
|
|
@@index([environmentId])
|
|
}
|
|
|
|
/// Stores a user's response to a survey, including their answers and metadata.
|
|
/// Each response is linked to a specific survey and optionally to a contact.
|
|
///
|
|
/// @property id - Unique identifier for the response
|
|
/// @property finished - Whether the survey was completed
|
|
/// @property survey - The associated survey
|
|
/// @property contact - The optional contact who provided the response
|
|
/// @property data - JSON object containing the actual response data
|
|
/// @property variables - Custom variables used in the response
|
|
/// @property ttc - Time to completion metrics
|
|
/// @property meta - Additional metadata about the response
|
|
model Response {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @default(now()) @updatedAt @map(name: "updated_at")
|
|
finished Boolean @default(false)
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
surveyId String
|
|
contact Contact? @relation(fields: [contactId], references: [id], onDelete: Cascade)
|
|
contactId String?
|
|
endingId String?
|
|
/// [ResponseData]
|
|
data Json @default("{}")
|
|
/// [ResponseVariables]
|
|
variables Json @default("{}")
|
|
/// [ResponseTtc]
|
|
ttc Json @default("{}")
|
|
/// [ResponseMeta]
|
|
meta Json @default("{}")
|
|
tags TagsOnResponses[]
|
|
quotaLinks ResponseQuotaLink[]
|
|
/// [ResponseContactAttributes]
|
|
contactAttributes Json?
|
|
// singleUseId, used to prevent multiple responses
|
|
singleUseId String?
|
|
language String?
|
|
displayId String? @unique
|
|
display Display? @relation(fields: [displayId], references: [id])
|
|
|
|
@@unique([surveyId, singleUseId])
|
|
@@index([createdAt])
|
|
@@index([surveyId, createdAt]) // to determine monthly response count
|
|
@@index([contactId, createdAt]) // to determine monthly identified users (persons)
|
|
}
|
|
|
|
/// Represents a label that can be applied to survey responses.
|
|
/// Used for categorizing and organizing responses within an environment.
|
|
///
|
|
/// @property id - Unique identifier for the tag
|
|
/// @property name - Display name of the tag
|
|
/// @property responses - Survey responses tagged with this label
|
|
/// @property environment - The environment this tag belongs to
|
|
model Tag {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
responses TagsOnResponses[]
|
|
environmentId String
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([environmentId, name])
|
|
}
|
|
|
|
/// Junction table linking tags to responses.
|
|
/// Enables many-to-many relationship between tags and responses.
|
|
///
|
|
/// @property response - The tagged response
|
|
/// @property tag - The tag applied to the response
|
|
model TagsOnResponses {
|
|
responseId String
|
|
response Response @relation(fields: [responseId], references: [id], onDelete: Cascade)
|
|
tagId String
|
|
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([responseId, tagId])
|
|
}
|
|
|
|
enum SurveyStatus {
|
|
draft
|
|
inProgress
|
|
paused
|
|
completed
|
|
}
|
|
|
|
/// Records when a survey is shown to a user.
|
|
/// Tracks survey display history and response status.
|
|
///
|
|
/// @property id - Unique identifier for the display event
|
|
/// @property survey - The survey that was displayed
|
|
/// @property contact - The contact who saw the survey
|
|
/// @property response - The associated response if one exists
|
|
model Display {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
surveyId String
|
|
contact Contact? @relation(fields: [contactId], references: [id], onDelete: Cascade)
|
|
contactId String?
|
|
response Response?
|
|
|
|
@@index([surveyId])
|
|
@@index([contactId, createdAt])
|
|
}
|
|
|
|
/// Links surveys to specific trigger actions.
|
|
/// Defines which user actions should cause a survey to be displayed.
|
|
/// This is the connection table between Surveys and ActionClasses that determines
|
|
/// when and under what conditions a survey should be triggered.
|
|
///
|
|
/// @property id - Unique identifier for the trigger
|
|
/// @property survey - The survey to be triggered
|
|
/// @property actionClass - The action that triggers the survey
|
|
/// @property createdAt - When the trigger was created
|
|
/// @property updatedAt - When the trigger was last modified
|
|
model SurveyTrigger {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
surveyId String
|
|
actionClass ActionClass @relation(fields: [actionClassId], references: [id], onDelete: Cascade)
|
|
actionClassId String
|
|
|
|
@@unique([surveyId, actionClassId])
|
|
}
|
|
|
|
enum SurveyAttributeFilterCondition {
|
|
equals
|
|
notEquals
|
|
}
|
|
|
|
enum SurveyQuotaAction {
|
|
endSurvey
|
|
continueSurvey
|
|
}
|
|
|
|
enum ResponseQuotaLinkStatus {
|
|
screenedIn
|
|
screenedOut
|
|
}
|
|
|
|
/// Defines targeting rules for surveys based on contact attributes.
|
|
/// Used to show surveys only to contacts matching specific criteria.
|
|
///
|
|
/// @property id - Unique identifier for the filter
|
|
/// @property attributeKey - The contact attribute to filter on
|
|
/// @property survey - The survey being filtered
|
|
/// @property condition - The comparison operator to use
|
|
/// @property value - The value to compare against
|
|
model SurveyAttributeFilter {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
attributeKey ContactAttributeKey @relation(fields: [attributeKeyId], references: [id], onDelete: Cascade)
|
|
attributeKeyId String
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
surveyId String
|
|
condition SurveyAttributeFilterCondition
|
|
value String
|
|
|
|
@@unique([surveyId, attributeKeyId])
|
|
@@index([attributeKeyId])
|
|
}
|
|
|
|
enum SurveyType {
|
|
link
|
|
app
|
|
}
|
|
|
|
enum displayOptions {
|
|
displayOnce
|
|
displayMultiple
|
|
displaySome
|
|
respondMultiple
|
|
}
|
|
|
|
enum SurveyScriptMode {
|
|
add
|
|
replace
|
|
}
|
|
|
|
/// Represents a complete survey configuration including questions, styling, and display rules.
|
|
/// Core model for the survey functionality in Formbricks.
|
|
///
|
|
/// @property id - Unique identifier for the survey
|
|
/// @property name - Display name of the survey
|
|
/// @property type - Survey delivery method (link, web, website, app)
|
|
/// @property status - Current state of the survey (draft, active, completed, etc)
|
|
/// @property environment - The environment this survey belongs to
|
|
/// @property questions - JSON array containing survey questions configuration
|
|
/// @property displayOption - Rules for how often the survey can be shown
|
|
/// @property triggers - Actions that can trigger this survey
|
|
/// @property attributeFilters - Rules for targeting specific contacts
|
|
/// @property customHeadScripts - Survey-specific custom HTML scripts (self-hosted only)
|
|
/// @property customHeadScriptsMode - "add" (merge with project) or "replace" (override project)
|
|
model Survey {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
redirectUrl String?
|
|
type SurveyType @default(app)
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
environmentId String
|
|
creator User? @relation(fields: [createdBy], references: [id])
|
|
createdBy String?
|
|
status SurveyStatus @default(draft)
|
|
/// [SurveyWelcomeCard]
|
|
welcomeCard Json @default("{\"enabled\": false}")
|
|
/// [SurveyQuestions]
|
|
questions Json @default("[]")
|
|
/// [SurveyBlocks]
|
|
blocks Json[] @default([])
|
|
/// [SurveyEnding]
|
|
endings Json[] @default([])
|
|
/// [SurveyHiddenFields]
|
|
hiddenFields Json @default("{\"enabled\": false}")
|
|
/// [SurveyVariables]
|
|
variables Json @default("[]")
|
|
responses Response[]
|
|
quotas SurveyQuota[]
|
|
displayOption displayOptions @default(displayOnce)
|
|
recontactDays Int?
|
|
displayLimit Int?
|
|
triggers SurveyTrigger[]
|
|
/// [SurveyInlineTriggers]
|
|
inlineTriggers Json?
|
|
attributeFilters SurveyAttributeFilter[]
|
|
displays Display[]
|
|
autoClose Int?
|
|
autoComplete Int?
|
|
delay Int @default(0)
|
|
/// [SurveyClosedMessage]
|
|
surveyClosedMessage Json?
|
|
segmentId String?
|
|
segment Segment? @relation(fields: [segmentId], references: [id])
|
|
|
|
/// [SurveyProjectOverwrites]
|
|
projectOverwrites Json?
|
|
|
|
/// [SurveyStyling]
|
|
styling Json?
|
|
|
|
/// [SurveySingleUse]
|
|
singleUse Json? @default("{\"enabled\": false, \"isEncrypted\": true}")
|
|
|
|
isVerifyEmailEnabled Boolean @default(false)
|
|
isSingleResponsePerEmailEnabled Boolean @default(false)
|
|
isBackButtonHidden Boolean @default(false)
|
|
isCaptureIpEnabled Boolean @default(false)
|
|
pin String?
|
|
displayPercentage Decimal?
|
|
languages SurveyLanguage[]
|
|
showLanguageSwitch Boolean?
|
|
followUps SurveyFollowUp[]
|
|
/// [SurveyRecaptcha]
|
|
recaptcha Json? @default("{\"enabled\": false, \"threshold\":0.1}")
|
|
/// [SurveyLinkMetadata]
|
|
metadata Json @default("{}")
|
|
|
|
slug String? @unique
|
|
|
|
customHeadScripts String?
|
|
customHeadScriptsMode SurveyScriptMode? @default(add)
|
|
|
|
@@index([environmentId, updatedAt])
|
|
@@index([segmentId])
|
|
}
|
|
|
|
/// Represents a quota configuration for a survey.
|
|
/// Defines response limits and conditions for quota management.
|
|
///
|
|
/// @property id - Unique identifier for the quota
|
|
/// @property survey - The survey this quota belongs to
|
|
/// @property name - Display name for the quota
|
|
/// @property limit - Maximum number of responses allowed
|
|
/// @property conditions - JSON object containing quota conditions
|
|
/// @property action - Action to take when quota is reached
|
|
/// @property endingCardId - Optional ending card to show when quota is reached
|
|
model SurveyQuota {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
surveyId String
|
|
name String
|
|
limit Int
|
|
/// [SurveyQuotaLogic]
|
|
logic Json @default("{}")
|
|
action SurveyQuotaAction
|
|
endingCardId String?
|
|
quotaLinks ResponseQuotaLink[]
|
|
countPartialSubmissions Boolean @default(false)
|
|
|
|
@@unique([surveyId, name])
|
|
}
|
|
|
|
/// Junction table linking responses to quotas.
|
|
/// Tracks which responses counted towards specific quotas and their status.
|
|
///
|
|
/// @property response - The response that counted towards the quota
|
|
/// @property quota - The quota this response counted towards
|
|
/// @property status - Whether the response was screened in or out
|
|
model ResponseQuotaLink {
|
|
response Response @relation(fields: [responseId], references: [id], onDelete: Cascade)
|
|
responseId String
|
|
quota SurveyQuota @relation(fields: [quotaId], references: [id], onDelete: Cascade)
|
|
quotaId String
|
|
status ResponseQuotaLinkStatus
|
|
|
|
@@id([responseId, quotaId])
|
|
@@index([quotaId, status])
|
|
}
|
|
|
|
/// Defines follow-up actions for survey responses.
|
|
/// Enables automated actions based on specific survey response conditions.
|
|
///
|
|
/// @property id - Unique identifier for the follow-up
|
|
/// @property survey - The associated survey
|
|
/// @property name - Display name for the follow-up
|
|
/// @property trigger - Conditions that activate the follow-up
|
|
/// @property action - Actions to take when triggered
|
|
model SurveyFollowUp {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
surveyId String
|
|
name String
|
|
/// [SurveyFollowUpTrigger]
|
|
trigger Json
|
|
/// [SurveyFollowUpAction]
|
|
action Json
|
|
}
|
|
|
|
enum ActionType {
|
|
code
|
|
noCode
|
|
}
|
|
|
|
/// Represents a user action that can trigger surveys.
|
|
/// Used to define points in the user journey where surveys can be shown.
|
|
///
|
|
/// @property id - Unique identifier for the action
|
|
/// @property name - Display name of the action
|
|
/// @property type - Whether this is a code or no-code action
|
|
/// @property key - Unique identifier used in code implementation
|
|
/// @property noCodeConfig - Configuration for no-code setup
|
|
/// @property environment - The environment this action belongs to
|
|
model ActionClass {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
description String?
|
|
type ActionType
|
|
key String?
|
|
/// [ActionClassNoCodeConfig]
|
|
noCodeConfig Json?
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
environmentId String
|
|
surveyTriggers SurveyTrigger[]
|
|
|
|
@@unique([key, environmentId])
|
|
@@unique([name, environmentId])
|
|
@@index([environmentId, createdAt])
|
|
}
|
|
|
|
enum EnvironmentType {
|
|
production
|
|
development
|
|
}
|
|
|
|
enum IntegrationType {
|
|
googleSheets
|
|
notion
|
|
airtable
|
|
slack
|
|
}
|
|
|
|
/// Represents third-party service integrations.
|
|
/// Enables data flow between Formbricks and external services.
|
|
///
|
|
/// @property id - Unique identifier for the integration
|
|
/// @property type - The service being integrated (Google Sheets, Notion, etc.)
|
|
/// @property environment - The environment this integration belongs to
|
|
/// @property config - Service-specific configuration details
|
|
model Integration {
|
|
id String @id @default(cuid())
|
|
type IntegrationType
|
|
environmentId String
|
|
/// [IntegrationConfig]
|
|
config Json
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([type, environmentId])
|
|
@@index([environmentId])
|
|
}
|
|
|
|
enum DataMigrationStatus {
|
|
pending
|
|
applied
|
|
failed
|
|
}
|
|
|
|
/// Tracks database schema migrations.
|
|
/// Used to manage and track the state of data structure changes.
|
|
///
|
|
/// @property id - Unique identifier for the migration
|
|
/// @property name - Name of the migration
|
|
/// @property status - Current state of the migration (pending, applied, failed)
|
|
/// @property startedAt - When the migration began
|
|
/// @property finishedAt - When the migration completed
|
|
model DataMigration {
|
|
id String @id @default(cuid())
|
|
startedAt DateTime @default(now()) @map(name: "started_at")
|
|
finishedAt DateTime? @map(name: "finished_at")
|
|
name String @unique
|
|
status DataMigrationStatus
|
|
}
|
|
|
|
/// Represents either a production or development environment within a project.
|
|
/// Each project has exactly two environments, serving as the main reference point
|
|
/// for most Formbricks resources including surveys and actions.
|
|
///
|
|
/// @property id - Unique identifier for the environment
|
|
/// @property type - Either 'production' or 'development'
|
|
/// @property project - Reference to parent project
|
|
/// @property surveys - Collection of surveys in this environment
|
|
/// @property contacts - Collection of contacts/users tracked
|
|
/// @property actionClasses - Defined actions that can trigger surveys
|
|
/// @property attributeKeys - Custom attributes configuration
|
|
model Environment {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
type EnvironmentType
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
projectId String
|
|
appSetupCompleted Boolean @default(false)
|
|
surveys Survey[]
|
|
contacts Contact[]
|
|
actionClasses ActionClass[]
|
|
attributeKeys ContactAttributeKey[]
|
|
webhooks Webhook[]
|
|
tags Tag[]
|
|
segments Segment[]
|
|
integration Integration[]
|
|
ApiKeyEnvironment ApiKeyEnvironment[]
|
|
|
|
@@index([projectId])
|
|
}
|
|
|
|
enum WidgetPlacement {
|
|
bottomLeft
|
|
bottomRight
|
|
topLeft
|
|
topRight
|
|
center
|
|
}
|
|
|
|
enum SurveyOverlay {
|
|
none
|
|
light
|
|
dark
|
|
}
|
|
|
|
/// Main grouping mechanism for resources in Formbricks.
|
|
/// Each organization can have multiple projects to separate different applications or products.
|
|
///
|
|
/// @property id - Unique identifier for the project
|
|
/// @property name - Display name of the project
|
|
/// @property organization - Reference to parent organization
|
|
/// @property environments - Development and production environments
|
|
/// @property styling - Project-wide styling configuration
|
|
/// @property config - Project-specific configuration
|
|
/// @property recontactDays - Default recontact delay for surveys
|
|
/// @property placement - Default widget placement for in-app surveys
|
|
model Project {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
organizationId String
|
|
environments Environment[]
|
|
/// [Styling]
|
|
styling Json @default("{\"allowStyleOverwrite\":true}")
|
|
/// [ProjectConfig]
|
|
config Json @default("{}")
|
|
recontactDays Int @default(7)
|
|
linkSurveyBranding Boolean @default(true) // Determines if the survey branding should be displayed in link surveys
|
|
inAppSurveyBranding Boolean @default(true) // Determines if the survey branding should be displayed in in-app surveys
|
|
placement WidgetPlacement @default(bottomRight)
|
|
clickOutsideClose Boolean @default(true)
|
|
overlay SurveyOverlay @default(none)
|
|
languages Language[]
|
|
/// [Logo]
|
|
logo Json?
|
|
projectTeams ProjectTeam[]
|
|
customHeadScripts String? // Custom HTML scripts for link surveys (self-hosted only)
|
|
|
|
@@unique([organizationId, name])
|
|
}
|
|
|
|
/// Represents the top-level organizational hierarchy in Formbricks.
|
|
/// Self-hosting instances typically have a single organization, while Formbricks Cloud
|
|
/// supports multiple organizations with multi-tenancy.
|
|
///
|
|
/// @property id - Unique identifier for the organization
|
|
/// @property name - Display name of the organization
|
|
/// @property memberships - User memberships within the organization
|
|
/// @property projects - Collection of projects owned by the organization
|
|
/// @property billing - JSON field containing billing information
|
|
/// @property whitelabel - Whitelabel configuration for the organization
|
|
/// @property isAISmartToolsEnabled - Controls access to AI smart tools (e.g. translations) that never touch collected data
|
|
/// @property isAIDataAnalysisEnabled - Controls access to AI data analysis features that touch experience data
|
|
model Organization {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
memberships Membership[]
|
|
projects Project[]
|
|
billing OrganizationBilling?
|
|
/// [OrganizationWhitelabel]
|
|
whitelabel Json @default("{}")
|
|
invites Invite[]
|
|
isAISmartToolsEnabled Boolean @default(false)
|
|
isAIDataAnalysisEnabled Boolean @default(false)
|
|
teams Team[]
|
|
apiKeys ApiKey[]
|
|
}
|
|
|
|
/// Stores billing and Stripe synchronization data for an organization.
|
|
///
|
|
/// @property organizationId - Reference to the organization
|
|
/// @property stripeCustomerId - Stripe customer ID for cloud billing
|
|
/// @property limits - Plan limits used by feature and quota checks
|
|
/// @property usageCycleAnchor - Stable anchor used to derive the current monthly usage cycle
|
|
/// @property stripe - Stripe synchronization snapshot data
|
|
model OrganizationBilling {
|
|
organizationId String @id @map(name: "organization_id")
|
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
stripeCustomerId String? @unique @map(name: "stripe_customer_id")
|
|
/// [OrganizationBillingPlanLimits]
|
|
limits Json
|
|
usageCycleAnchor DateTime? @map(name: "usage_cycle_anchor")
|
|
/// [OrganizationStripeBilling]
|
|
stripe Json?
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
}
|
|
|
|
enum OrganizationRole {
|
|
owner
|
|
manager
|
|
member
|
|
billing
|
|
}
|
|
|
|
/// Links users to organizations with specific roles.
|
|
/// Manages organization membership and permissions.
|
|
/// Core model for managing user access within organizations.
|
|
///
|
|
/// @property organization - The organization the user belongs to
|
|
/// @property user - The member user
|
|
/// @property accepted - Whether the user has accepted the membership
|
|
/// @property role - User's role within the organization (owner, manager, member, billing)
|
|
model Membership {
|
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
organizationId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
userId String
|
|
accepted Boolean @default(false)
|
|
role OrganizationRole @default(member)
|
|
|
|
@@id([userId, organizationId])
|
|
@@index([organizationId])
|
|
}
|
|
|
|
/// Represents pending invitations to join an organization.
|
|
/// Used to manage the process of adding new users to an organization.
|
|
/// Once accepted, invites are converted into memberships.
|
|
///
|
|
/// @property id - Unique identifier for the invite
|
|
/// @property email - Email address of the invited user
|
|
/// @property name - Optional display name for the invited user
|
|
/// @property organization - The organization sending the invite
|
|
/// @property creator - The user who created the invite
|
|
/// @property acceptor - The user who accepted the invite (if accepted)
|
|
/// @property expiresAt - When the invite becomes invalid
|
|
/// @property role - Intended role for the invited user
|
|
/// @property teamIds - Teams the user will be added to upon acceptance
|
|
model Invite {
|
|
id String @id @default(uuid())
|
|
email String
|
|
name String?
|
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
organizationId String
|
|
creator User @relation("inviteCreatedBy", fields: [creatorId], references: [id])
|
|
creatorId String
|
|
acceptor User? @relation("inviteAcceptedBy", fields: [acceptorId], references: [id], onDelete: Cascade)
|
|
acceptorId String?
|
|
createdAt DateTime @default(now())
|
|
expiresAt DateTime
|
|
role OrganizationRole @default(member)
|
|
teamIds String[] @default([])
|
|
|
|
@@index([email, organizationId])
|
|
@@index([organizationId])
|
|
}
|
|
|
|
/// Represents enhanced API authentication keys with organization-level ownership.
|
|
/// Used for authenticating API requests to Formbricks with more granular permissions.
|
|
///
|
|
/// @property id - Unique identifier for the API key
|
|
/// @property label - Optional descriptive name for the key
|
|
/// @property hashedKey - Securely stored API key
|
|
/// @property organization - The organization this key belongs to
|
|
/// @property createdBy - User ID who created this key
|
|
/// @property lastUsedAt - Timestamp of last usage
|
|
/// @property apiKeyEnvironments - Environments this key has access to
|
|
model ApiKey {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
createdBy String?
|
|
lastUsedAt DateTime?
|
|
label String
|
|
hashedKey String
|
|
lookupHash String? @unique
|
|
organizationId String
|
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
apiKeyEnvironments ApiKeyEnvironment[]
|
|
/// [OrganizationAccess]
|
|
organizationAccess Json @default("{}")
|
|
|
|
@@index([organizationId])
|
|
}
|
|
|
|
/// Defines permission levels for API keys.
|
|
/// Controls what operations an API key can perform.
|
|
enum ApiKeyPermission {
|
|
read
|
|
write
|
|
manage
|
|
}
|
|
|
|
/// Links API keys to environments with specific permissions.
|
|
/// Enables granular access control for API keys across environments.
|
|
///
|
|
/// @property id - Unique identifier for the environment access entry
|
|
/// @property apiKey - The associated API key
|
|
/// @property environment - The environment being accessed
|
|
/// @property permission - Level of access granted
|
|
model ApiKeyEnvironment {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
apiKeyId String
|
|
apiKey ApiKey @relation(fields: [apiKeyId], references: [id], onDelete: Cascade)
|
|
environmentId String
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
permission ApiKeyPermission
|
|
|
|
@@unique([apiKeyId, environmentId])
|
|
@@index([environmentId])
|
|
}
|
|
|
|
enum IdentityProvider {
|
|
email
|
|
github
|
|
google
|
|
azuread
|
|
openid
|
|
saml
|
|
}
|
|
|
|
/// Stores third-party authentication account information.
|
|
/// Enables OAuth and other external authentication methods.
|
|
///
|
|
/// @property id - Unique identifier for the account
|
|
/// @property user - The Formbricks user who owns this account
|
|
/// @property provider - The authentication provider (GitHub, Google, etc.)
|
|
/// @property providerAccountId - User ID from the provider
|
|
/// @property access_token - OAuth access token
|
|
/// @property refresh_token - OAuth refresh token
|
|
model Account {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
userId String
|
|
type String
|
|
provider String
|
|
providerAccountId String
|
|
access_token String? @db.Text
|
|
refresh_token String? @db.Text
|
|
expires_at Int?
|
|
ext_expires_in Int?
|
|
token_type String?
|
|
scope String?
|
|
id_token String? @db.Text
|
|
session_state String?
|
|
|
|
@@unique([provider, providerAccountId])
|
|
@@index([userId])
|
|
}
|
|
|
|
/// Represents a user in the Formbricks system.
|
|
/// Central model for user authentication and profile management.
|
|
///
|
|
/// @property id - Unique identifier for the user
|
|
/// @property name - Display name of the user
|
|
/// @property email - User's email address
|
|
/// @property twoFactorEnabled - Whether 2FA is active
|
|
/// @property memberships - Organizations the user belongs to
|
|
/// @property notificationSettings - User's notification preferences
|
|
model User {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
email String @unique
|
|
emailVerified DateTime? @map(name: "email_verified")
|
|
|
|
twoFactorSecret String?
|
|
twoFactorEnabled Boolean @default(false)
|
|
backupCodes String?
|
|
password String?
|
|
identityProvider IdentityProvider @default(email)
|
|
identityProviderAccountId String?
|
|
memberships Membership[]
|
|
accounts Account[]
|
|
groupId String?
|
|
invitesCreated Invite[] @relation("inviteCreatedBy")
|
|
invitesAccepted Invite[] @relation("inviteAcceptedBy")
|
|
/// [UserNotificationSettings]
|
|
notificationSettings Json @default("{}")
|
|
/// [Locale]
|
|
locale String @default("en-US")
|
|
surveys Survey[]
|
|
teamUsers TeamUser[]
|
|
lastLoginAt DateTime?
|
|
isActive Boolean @default(true)
|
|
}
|
|
|
|
/// Defines a segment of contacts based on attributes.
|
|
/// Used for targeting surveys to specific user groups.
|
|
///
|
|
/// @property id - Unique identifier for the segment
|
|
/// @property title - Display name of the segment
|
|
/// @property filters - Rules defining the segment
|
|
/// @property isPrivate - Whether the segment is private
|
|
/// @property environment - The environment this segment belongs to
|
|
model Segment {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
title String
|
|
description String?
|
|
isPrivate Boolean @default(true)
|
|
/// [SegmentFilter]
|
|
filters Json @default("[]")
|
|
environmentId String
|
|
environment Environment @relation(fields: [environmentId], references: [id], onDelete: Cascade)
|
|
surveys Survey[]
|
|
|
|
@@unique([environmentId, title])
|
|
}
|
|
|
|
/// Represents a supported language in the system.
|
|
/// Used for multilingual survey support.
|
|
///
|
|
/// @property id - Unique identifier for the language
|
|
/// @property code - Language code (e.g., 'en-US')
|
|
/// @property alias - Optional friendly name
|
|
/// @property project - The project this language is enabled for
|
|
model Language {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
code String
|
|
alias String?
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
projectId String
|
|
surveyLanguages SurveyLanguage[]
|
|
|
|
@@unique([projectId, code])
|
|
}
|
|
|
|
/// Links surveys to their supported languages.
|
|
/// Manages which languages are available for each survey.
|
|
///
|
|
/// @property language - The supported language
|
|
/// @property survey - The associated survey
|
|
/// @property default - Whether this is the default language
|
|
/// @property enabled - Whether this language is currently active
|
|
model SurveyLanguage {
|
|
language Language @relation(fields: [languageId], references: [id], onDelete: Cascade)
|
|
languageId String
|
|
surveyId String
|
|
survey Survey @relation(fields: [surveyId], references: [id], onDelete: Cascade)
|
|
default Boolean @default(false)
|
|
enabled Boolean @default(true)
|
|
|
|
@@id([languageId, surveyId])
|
|
@@index([surveyId])
|
|
}
|
|
|
|
/// Represents a team within an organization.
|
|
/// Enables group-based access control and collaboration.
|
|
///
|
|
/// @property id - Unique identifier for the team
|
|
/// @property name - Display name of the team
|
|
/// @property organization - The parent organization
|
|
/// @property teamUsers - Users who are part of this team
|
|
/// @property projectTeams - Projects this team has access to
|
|
model Team {
|
|
id String @id @default(cuid())
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
name String
|
|
organizationId String
|
|
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
teamUsers TeamUser[]
|
|
projectTeams ProjectTeam[]
|
|
|
|
@@unique([organizationId, name])
|
|
}
|
|
|
|
enum TeamUserRole {
|
|
admin
|
|
contributor
|
|
}
|
|
|
|
/// Links users to teams with specific roles.
|
|
/// Manages team membership and permissions.
|
|
///
|
|
/// @property team - The associated team
|
|
/// @property user - The team member
|
|
/// @property role - User's role within the team
|
|
model TeamUser {
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
teamId String
|
|
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
role TeamUserRole
|
|
|
|
@@id([teamId, userId])
|
|
@@index([userId])
|
|
}
|
|
|
|
enum ProjectTeamPermission {
|
|
read
|
|
readWrite
|
|
manage
|
|
}
|
|
|
|
/// Defines team access to specific projects.
|
|
/// Manages project-level permissions for teams.
|
|
///
|
|
/// @property project - The accessed project
|
|
/// @property team - The team receiving access
|
|
/// @property permission - Level of access granted
|
|
model ProjectTeam {
|
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
|
projectId String
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
teamId String
|
|
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
permission ProjectTeamPermission @default(read)
|
|
|
|
@@id([projectId, teamId])
|
|
@@index([teamId])
|
|
}
|