mirror of
https://github.com/hanzoai/insights.git
synced 2026-11-03 00:52:32 +00:00
The tree was a debranded snapshot of upstream taken around 2026-02-20, and upstream has moved about five months since. This replaces it with upstream master, mechanically re-derived: bin/debrand does the rename, and the pipeline and squashed migrations are restored from the shipped tree. Not a merge. The previous import replaced the tree wholesale in a single commit, so there is no shared content history to merge against. Reproducing the rename on the new tree is what actually converges. What survives: .hanzo/workflows, the Dockerfiles and bin/docker* entrypoints, compose files, LLM.md, and insights/migrations. The squashed initial migration is load-bearing — the live database records it by name, so upstream's ~918 individual migrations cannot come back. Nine products are dropped as unreferenced. Twenty-one more that we do not run are kept anyway because the core app still imports them; unpicking those is a refactor and does not belong in a rebase. This base does not build yet, and the reasons are not in the rename: upstream now wants Python 3.13.13 against our 3.12.12 and Django 5.2 against our 4.2, and the dependency manifests still name upstream packages that we republish under our own names. Those are decisions, not renames.
1230 lines
76 KiB
JSON
1230 lines
76 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"properties": {
|
|
"appearance": {
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"allowGoBack": {
|
|
"description": "Whether to show a 'Back' button on web surveys after the first question, letting respondents return to a previously visited question. Defaults to false.",
|
|
"type": "boolean"
|
|
},
|
|
"autoDisappear": {
|
|
"type": "boolean"
|
|
},
|
|
"backButtonText": {
|
|
"description": "Optional override for the back button label. Defaults to 'Back'.",
|
|
"type": "string"
|
|
},
|
|
"backgroundColor": {
|
|
"type": "string"
|
|
},
|
|
"borderColor": {
|
|
"type": "string"
|
|
},
|
|
"boxPadding": {
|
|
"type": "string"
|
|
},
|
|
"descriptionTextColor": {
|
|
"type": "string"
|
|
},
|
|
"disabledButtonOpacity": {
|
|
"type": "string"
|
|
},
|
|
"displayThankYouMessage": {
|
|
"type": "boolean"
|
|
},
|
|
"fontFamily": {
|
|
"type": "string"
|
|
},
|
|
"maxWidth": {
|
|
"type": "string"
|
|
},
|
|
"placeholder": {
|
|
"type": "string"
|
|
},
|
|
"ratingButtonActiveColor": {
|
|
"type": "string"
|
|
},
|
|
"ratingButtonColor": {
|
|
"type": "string"
|
|
},
|
|
"ratingButtonHoverColor": {
|
|
"type": "string"
|
|
},
|
|
"shuffleQuestions": {
|
|
"type": "boolean"
|
|
},
|
|
"submitButtonColor": {
|
|
"type": "string"
|
|
},
|
|
"submitButtonText": {
|
|
"type": "string"
|
|
},
|
|
"submitButtonTextColor": {
|
|
"type": "string"
|
|
},
|
|
"surveyPopupDelaySeconds": {
|
|
"type": "number"
|
|
},
|
|
"textColor": {
|
|
"type": "string"
|
|
},
|
|
"thankYouMessageCloseButtonText": {
|
|
"type": "string"
|
|
},
|
|
"thankYouMessageDescription": {
|
|
"type": "string"
|
|
},
|
|
"thankYouMessageDescriptionContentType": {
|
|
"description": "* `html` - html\n* `text` - text",
|
|
"enum": ["html", "text"],
|
|
"type": "string"
|
|
},
|
|
"thankYouMessageHeader": {
|
|
"type": "string"
|
|
},
|
|
"whiteLabel": {
|
|
"type": "boolean"
|
|
},
|
|
"widgetColor": {
|
|
"type": "string"
|
|
},
|
|
"widgetLabel": {
|
|
"type": "string"
|
|
},
|
|
"widgetSelector": {
|
|
"type": "string"
|
|
},
|
|
"widgetType": {
|
|
"description": "* `button` - button\n* `tab` - tab\n* `selector` - selector",
|
|
"enum": ["button", "tab", "selector"],
|
|
"type": "string"
|
|
},
|
|
"zIndex": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Survey appearance customization."
|
|
},
|
|
"archived": {
|
|
"description": "Archive state for the survey.",
|
|
"type": "boolean"
|
|
},
|
|
"conditions": {
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"deviceTypes": {
|
|
"description": "Device types that should match for this survey to be shown.",
|
|
"items": {
|
|
"description": "* `Desktop` - Desktop\n* `Mobile` - Mobile\n* `Tablet` - Tablet",
|
|
"enum": ["Desktop", "Mobile", "Tablet"],
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"deviceTypesMatchType": {
|
|
"description": "URL/device matching types: 'regex' (matches regex pattern), 'not_regex' (does not match regex pattern), 'exact' (exact string match), 'is_not' (not exact match), 'icontains' (case-insensitive contains), 'not_icontains' (case-insensitive does not contain).\n\n* `regex` - regex\n* `not_regex` - not_regex\n* `exact` - exact\n* `is_not` - is_not\n* `icontains` - icontains\n* `not_icontains` - not_icontains",
|
|
"enum": ["regex", "not_regex", "exact", "is_not", "icontains", "not_icontains"],
|
|
"type": "string"
|
|
},
|
|
"events": {
|
|
"properties": {
|
|
"repeatedActivation": {
|
|
"description": "Whether to show the survey every time one of the events is triggered (true), or just once (false).",
|
|
"type": "boolean"
|
|
},
|
|
"values": {
|
|
"description": "Array of event names that trigger the survey.",
|
|
"items": {
|
|
"properties": {
|
|
"name": {
|
|
"description": "Event name that triggers the survey.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["name"],
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"linkedFlagVariant": {
|
|
"description": "The variant of the feature flag linked to this survey.",
|
|
"type": "string"
|
|
},
|
|
"seenSurveyWaitPeriodInDays": {
|
|
"description": "Don't show this survey to users who saw any survey in the last x days.",
|
|
"minimum": 0,
|
|
"type": "number"
|
|
},
|
|
"selector": {
|
|
"type": "string"
|
|
},
|
|
"url": {
|
|
"type": "string"
|
|
},
|
|
"urlMatchType": {
|
|
"description": "URL/device matching types: 'regex' (matches regex pattern), 'not_regex' (does not match regex pattern), 'exact' (exact string match), 'is_not' (not exact match), 'icontains' (case-insensitive contains), 'not_icontains' (case-insensitive does not contain).\n\n* `regex` - regex\n* `not_regex` - not_regex\n* `exact` - exact\n* `is_not` - is_not\n* `icontains` - icontains\n* `not_icontains` - not_icontains",
|
|
"enum": ["regex", "not_regex", "exact", "is_not", "icontains", "not_icontains"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Complete replacement display and targeting conditions object. Do not provide this field unless changing display targeting. Preserve existing URL, selector, event, device, wait-period, and linked flag variant conditions unless explicitly changing them."
|
|
},
|
|
"description": {
|
|
"description": "Survey description.",
|
|
"type": "string"
|
|
},
|
|
"enable_iframe_embedding": {
|
|
"anyOf": [
|
|
{
|
|
"type": "boolean"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"enable_partial_responses": {
|
|
"anyOf": [
|
|
{
|
|
"type": "boolean"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "When at least one question is answered, the response is stored (true). The response is stored when all questions are answered (false)."
|
|
},
|
|
"end_date": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "When the survey stopped being shown to users. Setting this will complete the survey."
|
|
},
|
|
"form_content": {
|
|
"description": "Hosted-form content configuration for external_survey forms. Do not provide this field unless editing hosted-form content. Preserve existing content fields that should remain."
|
|
},
|
|
"id": {
|
|
"description": "A UUID string identifying this survey.",
|
|
"type": "string"
|
|
},
|
|
"iteration_count": {
|
|
"anyOf": [
|
|
{
|
|
"maximum": 500,
|
|
"minimum": 1,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "For a recurring schedule, this field specifies the number of times the survey should be shown to the user. Use 1 for 'once every X days', higher numbers for multiple repetitions. Works together with iteration_frequency_days to determine the overall survey schedule."
|
|
},
|
|
"iteration_frequency_days": {
|
|
"anyOf": [
|
|
{
|
|
"maximum": 365,
|
|
"minimum": 1,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "For a recurring schedule, this field specifies the interval in days between each survey instance shown to the user, used alongside iteration_count for precise scheduling."
|
|
},
|
|
"linked_flag_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "The feature flag linked to this survey."
|
|
},
|
|
"name": {
|
|
"description": "Survey name.",
|
|
"maxLength": 400,
|
|
"minLength": 1,
|
|
"type": "string"
|
|
},
|
|
"questions": {
|
|
"anyOf": [
|
|
{
|
|
"items": {
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"buttonText": {
|
|
"description": "Custom button label.",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"description": "Optional helper text.",
|
|
"type": "string"
|
|
},
|
|
"descriptionContentType": {
|
|
"description": "Format for the description field.\n\n* `text` - text\n* `html` - html",
|
|
"enum": ["html", "text"],
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"description": "Stable question identifier (UUID). When editing an existing question, send back its current id so its responses (keyed by $survey_response_<id>) stay attached; omit it for new questions and the server generates one.",
|
|
"type": "string"
|
|
},
|
|
"optional": {
|
|
"description": "Whether respondents may skip this question.",
|
|
"type": "boolean"
|
|
},
|
|
"question": {
|
|
"description": "Question text shown to respondents.",
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "* `open` - open",
|
|
"enum": ["open"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "question"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"buttonText": {
|
|
"description": "Custom button label.",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"description": "Optional helper text.",
|
|
"type": "string"
|
|
},
|
|
"descriptionContentType": {
|
|
"description": "Format for the description field.\n\n* `text` - text\n* `html` - html",
|
|
"enum": ["html", "text"],
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"description": "Stable question identifier (UUID). When editing an existing question, send back its current id so its responses (keyed by $survey_response_<id>) stay attached; omit it for new questions and the server generates one.",
|
|
"type": "string"
|
|
},
|
|
"link": {
|
|
"description": "HTTPS or mailto URL for link questions.",
|
|
"type": "string"
|
|
},
|
|
"optional": {
|
|
"description": "Whether respondents may skip this question.",
|
|
"type": "boolean"
|
|
},
|
|
"question": {
|
|
"description": "Question text shown to respondents.",
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "* `link` - link",
|
|
"enum": ["link"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "question", "link"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"branching": {
|
|
"anyOf": [
|
|
{
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"type": {
|
|
"description": "Continue to the next question in sequence.\n\n* `next_question` - next_question",
|
|
"enum": ["next_question"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"type": {
|
|
"description": "End the survey.\n\n* `end` - end",
|
|
"enum": ["end"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"index": {
|
|
"description": "0-based index of the next question.",
|
|
"minimum": 0,
|
|
"type": "number"
|
|
},
|
|
"type": {
|
|
"description": "Jump to a specific question index.\n\n* `specific_question` - specific_question",
|
|
"enum": ["specific_question"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "index"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"responseValues": {
|
|
"additionalProperties": {
|
|
"anyOf": [
|
|
{
|
|
"minimum": 0,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"enum": ["end"],
|
|
"type": "string"
|
|
}
|
|
]
|
|
},
|
|
"description": "Response-based branching map. Values can be a question index or 'end'.",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": {
|
|
"description": "Branch based on the selected or entered response.\n\n* `response_based` - response_based",
|
|
"enum": ["response_based"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "responseValues"],
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"buttonText": {
|
|
"description": "Custom button label.",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"description": "Optional helper text.",
|
|
"type": "string"
|
|
},
|
|
"descriptionContentType": {
|
|
"description": "Format for the description field.\n\n* `text` - text\n* `html` - html",
|
|
"enum": ["html", "text"],
|
|
"type": "string"
|
|
},
|
|
"display": {
|
|
"description": "Display format: 'number' shows numeric scale, 'emoji' shows emoji scale.\n\n* `number` - number\n* `emoji` - emoji",
|
|
"enum": ["number", "emoji"],
|
|
"type": "string"
|
|
},
|
|
"id": {
|
|
"description": "Stable question identifier (UUID). When editing an existing question, send back its current id so its responses (keyed by $survey_response_<id>) stay attached; omit it for new questions and the server generates one.",
|
|
"type": "string"
|
|
},
|
|
"lowerBoundLabel": {
|
|
"description": "Label for the lowest rating (e.g., 'Very Poor')",
|
|
"type": "string"
|
|
},
|
|
"optional": {
|
|
"description": "Whether respondents may skip this question.",
|
|
"type": "boolean"
|
|
},
|
|
"question": {
|
|
"description": "Question text shown to respondents.",
|
|
"type": "string"
|
|
},
|
|
"scale": {
|
|
"description": "Rating scale can be one of 3, 5, or 7",
|
|
"minimum": 1,
|
|
"type": "number"
|
|
},
|
|
"type": {
|
|
"description": "* `rating` - rating",
|
|
"enum": ["rating"],
|
|
"type": "string"
|
|
},
|
|
"upperBoundLabel": {
|
|
"description": "Label for the highest rating (e.g., 'Excellent')",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "question"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"branching": {
|
|
"anyOf": [
|
|
{
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"type": {
|
|
"description": "Continue to the next question in sequence.\n\n* `next_question` - next_question",
|
|
"enum": ["next_question"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"type": {
|
|
"description": "End the survey.\n\n* `end` - end",
|
|
"enum": ["end"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"index": {
|
|
"description": "0-based index of the next question.",
|
|
"minimum": 0,
|
|
"type": "number"
|
|
},
|
|
"type": {
|
|
"description": "Jump to a specific question index.\n\n* `specific_question` - specific_question",
|
|
"enum": ["specific_question"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "index"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"responseValues": {
|
|
"additionalProperties": {
|
|
"anyOf": [
|
|
{
|
|
"minimum": 0,
|
|
"type": "number"
|
|
},
|
|
{
|
|
"enum": ["end"],
|
|
"type": "string"
|
|
}
|
|
]
|
|
},
|
|
"description": "Response-based branching map. Values can be a question index or 'end'.",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": {
|
|
"description": "Branch based on the selected or entered response.\n\n* `response_based` - response_based",
|
|
"enum": ["response_based"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "responseValues"],
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
]
|
|
},
|
|
"buttonText": {
|
|
"description": "Custom button label.",
|
|
"type": "string"
|
|
},
|
|
"choices": {
|
|
"description": "Array of choice options. Choice indices (0, 1, 2, ...) are used for branching logic.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"maxItems": 20,
|
|
"minItems": 2,
|
|
"type": "array"
|
|
},
|
|
"description": {
|
|
"description": "Optional helper text.",
|
|
"type": "string"
|
|
},
|
|
"descriptionContentType": {
|
|
"description": "Format for the description field.\n\n* `text` - text\n* `html` - html",
|
|
"enum": ["html", "text"],
|
|
"type": "string"
|
|
},
|
|
"hasOpenChoice": {
|
|
"description": "Whether the final option should be an open-text choice (for example, 'Other').",
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"description": "Stable question identifier (UUID). When editing an existing question, send back its current id so its responses (keyed by $survey_response_<id>) stay attached; omit it for new questions and the server generates one.",
|
|
"type": "string"
|
|
},
|
|
"optional": {
|
|
"description": "Whether respondents may skip this question.",
|
|
"type": "boolean"
|
|
},
|
|
"question": {
|
|
"description": "Question text shown to respondents.",
|
|
"type": "string"
|
|
},
|
|
"shuffleOptions": {
|
|
"description": "Whether to randomize the order of choices for each respondent.",
|
|
"type": "boolean"
|
|
},
|
|
"type": {
|
|
"description": "* `single_choice` - single_choice",
|
|
"enum": ["single_choice"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "question", "choices"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"buttonText": {
|
|
"description": "Custom button label.",
|
|
"type": "string"
|
|
},
|
|
"choices": {
|
|
"description": "Array of choice options. Multiple selections allowed. No branching logic supported.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"maxItems": 20,
|
|
"minItems": 2,
|
|
"type": "array"
|
|
},
|
|
"description": {
|
|
"description": "Optional helper text.",
|
|
"type": "string"
|
|
},
|
|
"descriptionContentType": {
|
|
"description": "Format for the description field.\n\n* `text` - text\n* `html` - html",
|
|
"enum": ["html", "text"],
|
|
"type": "string"
|
|
},
|
|
"hasOpenChoice": {
|
|
"description": "Whether the final option should be an open-text choice (for example, 'Other').",
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"description": "Stable question identifier (UUID). When editing an existing question, send back its current id so its responses (keyed by $survey_response_<id>) stay attached; omit it for new questions and the server generates one.",
|
|
"type": "string"
|
|
},
|
|
"optional": {
|
|
"description": "Whether respondents may skip this question.",
|
|
"type": "boolean"
|
|
},
|
|
"question": {
|
|
"description": "Question text shown to respondents.",
|
|
"type": "string"
|
|
},
|
|
"shuffleOptions": {
|
|
"description": "Whether to randomize the order of choices for each respondent.",
|
|
"type": "boolean"
|
|
},
|
|
"type": {
|
|
"description": "* `multiple_choice` - multiple_choice",
|
|
"enum": ["multiple_choice"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["type", "question", "choices"],
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"type": "array"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Complete replacement question list. Existing question IDs are tied to response data and must be preserved. Before sending this field, fetch the survey first, modify the existing question objects in place, keep every unchanged or edited question's id, and include the complete intended ordered question list. New questions should omit id. Do not regenerate existing questions from scratch."
|
|
},
|
|
"remove_targeting_flag": {
|
|
"anyOf": [
|
|
{
|
|
"type": "boolean"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Set to true to completely remove all targeting filters from the survey, making it visible to all users (subject to other display conditions like URL matching)."
|
|
},
|
|
"responses_limit": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "The maximum number of responses before automatically stopping the survey."
|
|
},
|
|
"schedule": {
|
|
"anyOf": [
|
|
{
|
|
"description": "* `once` - once\n* `recurring` - recurring\n* `always` - always",
|
|
"enum": ["once", "recurring", "always"],
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Survey scheduling behavior: 'once' = show once per user (default), 'recurring' = repeat based on iteration_count and iteration_frequency_days settings, 'always' = show every time conditions are met (mainly for widget surveys)\n\n* `once` - once\n* `recurring` - recurring\n* `always` - always"
|
|
},
|
|
"start_date": {
|
|
"anyOf": [
|
|
{
|
|
"format": "date-time",
|
|
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Setting this will launch the survey immediately. Don't add a start_date unless explicitly requested to do so."
|
|
},
|
|
"targeting_flag_filters": {
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"aggregation_group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index for group-based feature flags."
|
|
},
|
|
"early_exit": {
|
|
"default": false,
|
|
"description": "When true, condition evaluation stops at the first matching condition set rather than continuing to evaluate subsequent groups.",
|
|
"type": "boolean"
|
|
},
|
|
"feature_enrollment": {
|
|
"anyOf": [
|
|
{
|
|
"type": "boolean"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Whether this flag has early access feature enrollment enabled. When true, the flag is evaluated against the person property $feature_enrollment/{flag_key}."
|
|
},
|
|
"groups": {
|
|
"description": "Release condition groups for the feature flag.",
|
|
"items": {
|
|
"properties": {
|
|
"aggregation_group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index for this condition set. None means person-level aggregation."
|
|
},
|
|
"properties": {
|
|
"description": "Property conditions for this release condition group.",
|
|
"items": {
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Operator used to compare the property value.\n\n* `exact` - exact\n* `is_not` - is_not\n* `icontains` - icontains\n* `not_icontains` - not_icontains\n* `starts_with` - starts_with\n* `not_starts_with` - not_starts_with\n* `ends_with` - ends_with\n* `not_ends_with` - not_ends_with\n* `regex` - regex\n* `not_regex` - not_regex\n* `gt` - gt\n* `gte` - gte\n* `lt` - lt\n* `lte` - lte",
|
|
"enum": [
|
|
"exact",
|
|
"is_not",
|
|
"icontains",
|
|
"not_icontains",
|
|
"starts_with",
|
|
"not_starts_with",
|
|
"ends_with",
|
|
"not_ends_with",
|
|
"regex",
|
|
"not_regex",
|
|
"gt",
|
|
"gte",
|
|
"lt",
|
|
"lte"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Property filter type. Common values are 'person' and 'cohort'.\n\n* `cohort` - cohort\n* `person` - person\n* `group` - group",
|
|
"enum": ["cohort", "person", "group"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Comparison value for the property filter. Supports strings, numbers, booleans, and arrays."
|
|
}
|
|
},
|
|
"required": ["key", "value", "operator"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Existence operator.\n\n* `is_set` - is_set\n* `is_not_set` - is_not_set",
|
|
"enum": ["is_set", "is_not_set"],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Property filter type. Common values are 'person' and 'cohort'.\n\n* `cohort` - cohort\n* `person` - person\n* `group` - group",
|
|
"enum": ["cohort", "person", "group"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Optional value. Runtime behavior determines whether this is ignored."
|
|
}
|
|
},
|
|
"required": ["key", "operator"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Date comparison operator.\n\n* `is_date_exact` - is_date_exact\n* `is_date_after` - is_date_after\n* `is_date_before` - is_date_before",
|
|
"enum": [
|
|
"is_date_exact",
|
|
"is_date_before",
|
|
"is_date_after"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Property filter type. Common values are 'person' and 'cohort'.\n\n* `cohort` - cohort\n* `person` - person\n* `group` - group",
|
|
"enum": ["cohort", "person", "group"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Date value in ISO format or relative date expression.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["key", "operator", "value"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Semantic version comparison operator.\n\n* `semver_gt` - semver_gt\n* `semver_gte` - semver_gte\n* `semver_lt` - semver_lt\n* `semver_lte` - semver_lte\n* `semver_eq` - semver_eq\n* `semver_neq` - semver_neq\n* `semver_tilde` - semver_tilde\n* `semver_caret` - semver_caret\n* `semver_wildcard` - semver_wildcard",
|
|
"enum": [
|
|
"semver_gt",
|
|
"semver_gte",
|
|
"semver_lt",
|
|
"semver_lte",
|
|
"semver_eq",
|
|
"semver_neq",
|
|
"semver_tilde",
|
|
"semver_caret",
|
|
"semver_wildcard"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Property filter type. Common values are 'person' and 'cohort'.\n\n* `cohort` - cohort\n* `person` - person\n* `group` - group",
|
|
"enum": ["cohort", "person", "group"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Semantic version string.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["key", "operator", "value"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Multi-contains operator.\n\n* `icontains_multi` - icontains_multi\n* `not_icontains_multi` - not_icontains_multi",
|
|
"enum": ["icontains_multi", "not_icontains_multi"],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Property filter type. Common values are 'person' and 'cohort'.\n\n* `cohort` - cohort\n* `person` - person\n* `group` - group",
|
|
"enum": ["cohort", "person", "group"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "List of strings to evaluate against.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": ["key", "operator", "value"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Membership operator for cohort properties.\n\n* `in` - in\n* `not_in` - not_in",
|
|
"enum": ["in", "not_in"],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Cohort property type required for in/not_in operators.\n\n* `cohort` - cohort",
|
|
"enum": ["cohort"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Cohort comparison value (single or list, depending on usage)."
|
|
}
|
|
},
|
|
"required": ["key", "type", "operator", "value"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"properties": {
|
|
"cohort_name": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Resolved cohort name for cohort-type filters."
|
|
},
|
|
"group_type_index": {
|
|
"anyOf": [
|
|
{
|
|
"type": "number"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Group type index when using group-based filters."
|
|
},
|
|
"key": {
|
|
"description": "Property key used in this feature flag condition.",
|
|
"type": "string"
|
|
},
|
|
"operator": {
|
|
"description": "Operator for feature flag dependency evaluation.\n\n* `flag_evaluates_to` - flag_evaluates_to",
|
|
"enum": ["flag_evaluates_to"],
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"description": "Flag property type required for flag dependency checks.\n\n* `flag` - flag",
|
|
"enum": ["flag"],
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "Value to compare flag evaluation against."
|
|
}
|
|
},
|
|
"required": ["key", "type", "operator", "value"],
|
|
"type": "object"
|
|
}
|
|
]
|
|
},
|
|
"type": "array"
|
|
},
|
|
"rollout_percentage": {
|
|
"description": "Rollout percentage for this release condition group.",
|
|
"type": "number"
|
|
},
|
|
"variant": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Variant key override for multivariate flags."
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"multivariate": {
|
|
"anyOf": [
|
|
{
|
|
"properties": {
|
|
"variants": {
|
|
"description": "Variant definitions for multivariate feature flags.",
|
|
"items": {
|
|
"properties": {
|
|
"key": {
|
|
"description": "Unique key for this variant.",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"description": "Human-readable name for this variant.",
|
|
"type": "string"
|
|
},
|
|
"rollout_percentage": {
|
|
"description": "Variant rollout percentage.",
|
|
"type": "number"
|
|
}
|
|
},
|
|
"required": ["key", "rollout_percentage"],
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": ["variants"],
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Multivariate configuration for variant-based rollouts."
|
|
},
|
|
"payloads": {
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"description": "Optional payload values keyed by variant key.",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"description": "Target specific users based on their properties. Example: {groups: [{properties: [{key: 'email', value: ['@company.com'], operator: 'icontains'}], rollout_percentage: 100}]}"
|
|
},
|
|
"targeting_flag_id": {
|
|
"description": "An existing targeting flag to use for this survey.",
|
|
"type": "number"
|
|
},
|
|
"translations": {
|
|
"description": "Complete replacement survey-level translations object. Do not provide this field unless changing translations. Preserve existing language keys and translated fields that should remain. Use null only when the user explicitly asks to remove survey-level translations."
|
|
},
|
|
"type": {
|
|
"description": "Survey type.\n\n* `popover` - popover\n* `widget` - widget\n* `external_survey` - external survey\n* `api` - api",
|
|
"enum": ["popover", "widget", "external_survey", "api"],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["id"],
|
|
"type": "object"
|
|
}
|