mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
Mechanically re-derived: bin/debrand runs over a fresh import of posthog/posthog@fa1a9a60d4 (2026-08-06). The pipeline (.hanzo/workflows), the Dockerfiles and bin/docker* entrypoints, compose files, LLM.md and the squashed initial migration are restored from the shipped tree, same as the previous import. The prune's import-closure guard kept 21 products the new core now imports; dropping them is a refactor now, recorded rather than forced.
1574 lines
85 KiB
JSON
1574 lines
85 KiB
JSON
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"definitions": {
|
|
"AIObservabilityGetCostsSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"projectId": {
|
|
"description": "Project ID. Defaults to the active project when omitted.",
|
|
"type": "integer",
|
|
"exclusiveMinimum": 0,
|
|
"maximum": 9007199254740991
|
|
},
|
|
"days": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"BusinessKnowledgeUrlSourceCreateSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"maxLength": 255,
|
|
"description": "Short human label for the source. Shown in the settings list and in agent citations."
|
|
},
|
|
"url": {
|
|
"type": "string",
|
|
"maxLength": 2048,
|
|
"format": "uri",
|
|
"description": "Public HTTP(S) URL to fetch. Private or internal hosts are rejected."
|
|
},
|
|
"source_type": {
|
|
"default": "url",
|
|
"description": "Source type. Always \"url\" for this tool.",
|
|
"type": "string",
|
|
"const": "url"
|
|
},
|
|
"refresh_interval": {
|
|
"default": "manual",
|
|
"description": "How often to auto-refresh this source in the background. Defaults to \"manual\" (no auto-refresh).",
|
|
"type": "string",
|
|
"enum": ["manual", "1h", "6h", "24h", "7d"]
|
|
},
|
|
"always_include": {
|
|
"default": false,
|
|
"description": "When true, this source's content is injected into every support reply prompt as general context (tone, policies, direction), not just when it matches a query.",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": ["name", "url"]
|
|
},
|
|
"DebugMcpUiAppsSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"message": {
|
|
"description": "Optional message to include in the debug data",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"EmailTemplateDesignPatchSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "The email template id to edit."
|
|
},
|
|
"operations": {
|
|
"minItems": 1,
|
|
"type": "array",
|
|
"items": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_content"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the content block to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial content-block fields, deep-merged into the existing block; a null leaf deletes that key. e.g. {values: {text: '<p>Hi</p>'}} changes only the block's text."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_column"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the column to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial column fields, deep-merged; a null leaf deletes that key."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_row"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the row to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial row fields, deep-merged; a null leaf deletes that key."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_body"
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial body fields, deep-merged. e.g. {values: {backgroundColor: '#ffffff'}}."
|
|
}
|
|
},
|
|
"required": ["op", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "add_content"
|
|
},
|
|
"column_id": {
|
|
"type": "string",
|
|
"description": "Id of the column to insert the block into."
|
|
},
|
|
"content": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "A content block {type, values: {...}}; omit id and values._meta — they are assigned server-side. type is one of text, heading, button, image, divider, html, etc."
|
|
},
|
|
"index": {
|
|
"description": "0-based insert position; omit to append to the end.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["op", "column_id", "content"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "remove_content"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the content block to remove."
|
|
}
|
|
},
|
|
"required": ["op", "id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "move_content"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the content block to move."
|
|
},
|
|
"column_id": {
|
|
"type": "string",
|
|
"description": "Id of the destination column."
|
|
},
|
|
"index": {
|
|
"description": "0-based position in the destination column; omit to append.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["op", "id", "column_id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "add_row"
|
|
},
|
|
"row": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "A full row {cells, columns: [{contents: [...], values}], values}; ids and Unlayer numbering are assigned server-side for the row and everything nested in it."
|
|
},
|
|
"index": {
|
|
"description": "0-based insert position; omit to append to the end.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["op", "row"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "remove_row"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the row to remove."
|
|
}
|
|
},
|
|
"required": ["op", "id"]
|
|
}
|
|
]
|
|
},
|
|
"description": "Ordered edits applied atomically to the template's Unlayer design: the stored design is read, the ops are applied in order, the result is validated and re-rendered to HTML, and saved only if valid — otherwise the template is left unchanged. Reference blocks by id so you never resend the whole design."
|
|
}
|
|
},
|
|
"required": ["id", "operations"]
|
|
},
|
|
"EventDefinitionUpdateInputSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"description": {
|
|
"description": "Description explaining when the event is triggered",
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"description": "Tags to organize events by product area (e.g. \"checkout\", \"onboarding\") or user journey stage (e.g. \"acquisition\", \"activation\", \"monetization\", \"retention\")",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"verified": {
|
|
"description": "Mark as verified to indicate the event is properly instrumented and tracking correctly",
|
|
"type": "boolean"
|
|
},
|
|
"hidden": {
|
|
"description": "Mark event as no longer used/captured. Hides it from UI while preserving historical data",
|
|
"type": "boolean"
|
|
}
|
|
}
|
|
},
|
|
"EventDefinitionUpdateSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"eventName": {
|
|
"type": "string",
|
|
"description": "The name of the event to update (e.g. \"$pageview\", \"user_signed_up\")"
|
|
},
|
|
"data": {
|
|
"type": "object",
|
|
"properties": {
|
|
"description": {
|
|
"description": "Description explaining when the event is triggered",
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"description": "Tags to organize events by product area (e.g. \"checkout\", \"onboarding\") or user journey stage (e.g. \"acquisition\", \"activation\", \"monetization\", \"retention\")",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"verified": {
|
|
"description": "Mark as verified to indicate the event is properly instrumented and tracking correctly",
|
|
"type": "boolean"
|
|
},
|
|
"hidden": {
|
|
"description": "Mark event as no longer used/captured. Hides it from UI while preserving historical data",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"description": "The event definition data to update"
|
|
}
|
|
},
|
|
"required": ["eventName", "data"]
|
|
},
|
|
"ExecuteSQLSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"query": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"description": "The final SQL query to be executed."
|
|
},
|
|
"truncate": {
|
|
"default": true,
|
|
"description": "Whether to truncate large blob/JSON values in results. Defaults to true. Set to false when you need full untruncated results (e.g., for dumping to a file).",
|
|
"type": "boolean"
|
|
},
|
|
"connectionId": {
|
|
"description": "Optional id of an external data source (e.g. a Postgres, DuckDB, or MySQL direct-query connection). When set, runs the query against that source instead of the Datastore catalog. Use external-data-sources-list to discover available connection ids.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["query"]
|
|
},
|
|
"ExperimentResultsGetSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "number",
|
|
"description": "The ID of the experiment to get comprehensive results for"
|
|
},
|
|
"refresh": {
|
|
"default": false,
|
|
"description": "Force refresh of results instead of using cached values. Defaults to false.",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": ["id"]
|
|
},
|
|
"ExternalDataJobsAfterSchema": {
|
|
"type": "string",
|
|
"description": "ISO timestamp — only return jobs created after this date (e.g. \"2025-01-01T00:00:00Z\")."
|
|
},
|
|
"ExternalDataJobsBeforeSchema": {
|
|
"type": "string",
|
|
"description": "ISO timestamp — only return jobs created before this date (e.g. \"2025-12-31T23:59:59Z\")."
|
|
},
|
|
"ExternalDataJobsSchemasSchema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "Filter jobs by table schema names (e.g. [\"users\", \"orders\"]). Only returns jobs for these tables."
|
|
},
|
|
"ExternalDataSourcePayloadSchema": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Connection credentials for the source. Keys depend on source_type. For database sources: host, port, database, user, password, schema. For SaaS sources: api_key or OAuth fields. For source_type \"Custom\" (a user-defined REST API): `manifest_json` (a stringified RESTAPIConfig describing client.base_url, auth, and resources) plus the credential for the auth type declared in the manifest — `auth_token` (bearer), `auth_api_key` (api_key), or `auth_password` (http_basic); keep secrets in these auth_* keys, never inline in manifest_json. Use external-data-sources-wizard (pass source_type) to see required fields per source type. For the advanced external-data-sources-create flow, the per-table 'schemas' array (built from external-data-sources-db-schema) also goes in here, e.g. {\"host\": ..., \"password\": ..., \"schemas\": [{\"name\": \"orders\", \"should_sync\": true, \"sync_type\": \"incremental\", \"incremental_field\": \"updated_at\", \"incremental_field_type\": \"datetime\"}]}. Do not pass unresolved {\"secretRef\": ...} objects — resolve secrets to real values first, or use a credential_id from data-warehouse-source-connect-link."
|
|
},
|
|
"ExternalDataSourceTypeSchema": {
|
|
"type": "string",
|
|
"description": "The source type name (e.g. \"Postgres\", \"MySQL\", \"Stripe\"). Use external-data-sources-wizard to see available types and their required fields."
|
|
},
|
|
"FeedbackSubmitSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"summary": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"description": "A one-sentence headline capturing the feedback (e.g. \"session replay scrubber jumps backwards when you click the timeline\", \"query-trends descriptions made it hard to choose between trends and funnels\", or \"the new SQL editor autocomplete is excellent\")."
|
|
},
|
|
"feedback_type": {
|
|
"type": "string",
|
|
"enum": ["product", "mcp", "docs", "scout", "other"],
|
|
"description": "What this feedback is about. \"product\" = any Insights product or feature (insights, session replay, feature flags, the data warehouse, web analytics, error tracking, etc.). \"mcp\" = this MCP server itself — a tool, its input schema, response format, an error, or these instructions. \"docs\" = Insights documentation. \"scout\" = a canonical Insights scout skill's content — reserved for scheduled scout runs reporting an improvement opportunity in their own Insights-authored skill (set `scout_skill_name`, `scout_skill_version`, and `scout_category`). \"other\" = anything that doesn't fit the above."
|
|
},
|
|
"sentiment": {
|
|
"type": "string",
|
|
"enum": ["positive", "neutral", "negative", "mixed"],
|
|
"description": "The overall tone. Use \"negative\" for something broken or blocking, \"mixed\" for mostly-fine-but-with-a-concrete-problem, \"neutral\" for a suggestion or feature request with no strong sentiment, and \"positive\" for praise or something that worked well. All sentiments are welcome — positive feedback is encouraged, not just problems."
|
|
},
|
|
"product_area": {
|
|
"description": "The Insights product or area this is about, in free text (e.g. \"session replay\", \"insights\", \"data warehouse\", \"feature flags\", \"docs\"). Most useful for product feedback; for MCP feedback the tool name belongs in `details`/`friction_points` instead.",
|
|
"type": "string"
|
|
},
|
|
"category": {
|
|
"description": "For MCP feedback (`feedback_type: \"mcp\"`) only: the single category that best describes the dominant theme. Pick \"missing_tool\" if a capability was absent, \"tool_description\" if the tool docs were unclear, \"tool_input_schema\" if input args were confusing, \"tool_output_format\" if the response was hard to consume, \"instructions_clarity\" if these MCP instructions were unclear, \"tool_correctness\" if a tool returned wrong data, \"error_message\" if an error was unhelpful, \"performance\" if latency was the issue. Omit for product, docs, or other feedback.",
|
|
"type": "string",
|
|
"enum": [
|
|
"tool_correctness",
|
|
"tool_description",
|
|
"tool_input_schema",
|
|
"tool_output_format",
|
|
"missing_tool",
|
|
"instructions_clarity",
|
|
"performance",
|
|
"error_message",
|
|
"other"
|
|
]
|
|
},
|
|
"scout_skill_name": {
|
|
"description": "For scout feedback (`feedback_type: \"scout\"`) only: the canonical scout skill the feedback is about (e.g. \"signals-scout-web-analytics\"), exactly as named in the run identity. Required for scout feedback — without it the feedback cannot be aggregated per skill.",
|
|
"type": "string"
|
|
},
|
|
"scout_skill_version": {
|
|
"description": "For scout feedback (`feedback_type: \"scout\"`) only: the skill version the run executed (from the run identity). Feedback is only actionable against the version that produced it — the skill may have moved since.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
},
|
|
"scout_category": {
|
|
"description": "For scout feedback (`feedback_type: \"scout\"`) only: the single category that best describes the skill gap. \"false_positive\" = the skill's detection rules surfaced something that wasn't real; \"missed_detection\" = a real issue the skill's instructions steered you past; \"discriminator_gap\" = the skill's signal-vs-baseline discriminator doesn't hold for a class of projects; \"wasted_investigation\" = an investigation pattern the skill mandates burned budget without payoff; \"instruction_ambiguity\" = an instruction that is ambiguous in practice. Omit for non-scout feedback.",
|
|
"type": "string",
|
|
"enum": [
|
|
"false_positive",
|
|
"missed_detection",
|
|
"discriminator_gap",
|
|
"wasted_investigation",
|
|
"instruction_ambiguity",
|
|
"other"
|
|
]
|
|
},
|
|
"task_completed": {
|
|
"description": "Were you able to complete the user's task? Be honest — \"false\" is just as useful as \"true\". Most relevant when `feedback_type` is \"mcp\".",
|
|
"type": "boolean"
|
|
},
|
|
"tools_used": {
|
|
"description": "The MCP tool names you called while working on the user's task (e.g. [\"read-data-schema\", \"query-trends\"]). Helps us correlate feedback to specific tools.",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"friction_points": {
|
|
"description": "Clear, concise bullet points describing the friction — what was confusing, broken, slow, or missing. Quote the exact product surface, tool name, parameter, or error text where you can. Omit for purely positive feedback.",
|
|
"type": "string"
|
|
},
|
|
"suggested_improvement": {
|
|
"description": "The single most impactful, concrete change that would address this feedback, if you can name one (e.g. \"add a `filters` example to query-funnel's description\", or \"let the replay scrubber snap to the nearest event\"). Optional — praise or an observation doesn't need one.",
|
|
"type": "string"
|
|
},
|
|
"user_request": {
|
|
"description": "A short, anonymised paraphrase of what the user originally asked you to do. Do not include PII, customer names, or sensitive query content.",
|
|
"type": "string"
|
|
},
|
|
"details": {
|
|
"description": "Any additional context that doesn't fit the other fields. Keep it to clear, concise bullet points.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["summary", "feedback_type", "sentiment"]
|
|
},
|
|
"InsightQueryInputSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"insightId": {
|
|
"description": "The insight to run: its numeric `id` or 8-character `short_id`.",
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "number"
|
|
}
|
|
]
|
|
},
|
|
"output_format": {
|
|
"default": "optimized",
|
|
"description": "Output format. \"optimized\" returns a human-readable summary from server-side formatters (recommended for analysis). \"json\" returns the raw query results as JSON.",
|
|
"type": "string",
|
|
"enum": ["optimized", "json"]
|
|
},
|
|
"variables_override": {
|
|
"description": "Object (or pre-encoded JSON string) to override the insight's InsightsQL variables for this run only (not persisted). Format: {\"<variable_id>\": {\"code_name\": \"<code_name>\", \"variableId\": \"<variable_id>\", \"value\": <new_value>}}. Each entry must include `code_name` — partial entries are silently dropped. The simplest workflow is to call `insight-get` first, copy the matching entry from the response's query variables, and mutate `value`. Top-level keys replace; nested values are not deep-merged. Ignored when accessed via a sharing token.",
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {}
|
|
}
|
|
]
|
|
},
|
|
"filters_override": {
|
|
"description": "Object (or pre-encoded JSON string) to override the insight's filters for this run only (not persisted). Top-level keys replace; nested values are not deep-merged — pass the complete value for any key you override. Accepts the same keys as the dashboard filters schema (e.g., `date_from`, `date_to`, `properties`). Ignored when accessed via a sharing token.",
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"required": ["insightId"]
|
|
},
|
|
"OrganizationGetAllSchema": {
|
|
"type": "object",
|
|
"properties": {}
|
|
},
|
|
"OrganizationSetActiveSchema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"orgId": {
|
|
"type": "string",
|
|
"description": "The organization to switch to: the `id` returned by `organizations-get` (a UUID-like string, not the organization name). Use `organizations-get` to resolve a name to its id."
|
|
}
|
|
},
|
|
"required": ["orgId"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Alias for `orgId`. Accepts the `id` returned by `organizations-list` / `organization-get`."
|
|
}
|
|
},
|
|
"required": ["id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"organizationId": {
|
|
"type": "string",
|
|
"description": "Alias for `orgId`. Accepts the `id` returned by `organizations-list` / `organization-get`."
|
|
}
|
|
},
|
|
"required": ["organizationId"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"organization_id": {
|
|
"type": "string",
|
|
"description": "Alias for `orgId`. Accepts the `id` returned by `organizations-list` / `organization-get`."
|
|
}
|
|
},
|
|
"required": ["organization_id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"org_id": {
|
|
"type": "string",
|
|
"description": "Alias for `orgId`. Accepts the `id` returned by `organizations-list` / `organization-get`."
|
|
}
|
|
},
|
|
"required": ["org_id"]
|
|
}
|
|
]
|
|
},
|
|
"PathCleaningRulesUpdateSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"operations": {
|
|
"minItems": 1,
|
|
"type": "array",
|
|
"items": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"const": "append"
|
|
},
|
|
"alias": {
|
|
"type": "string",
|
|
"description": "The human-readable replacement, e.g. \"/users/<id>/profile\". Use angle-bracket placeholders (<id>, <uuid>, <slug>) by convention. An empty string is valid — it deletes the matched text (e.g. to strip a \"?page=N\" fragment). Not a regex template — backreferences are not supported."
|
|
},
|
|
"regex": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"description": "A re2 pattern matched against the path, e.g. \"/users/\\\\d+/profile\". No need to escape \"/\". Anchor with ^ / $ when you mean it."
|
|
}
|
|
},
|
|
"required": ["action", "alias", "regex"],
|
|
"description": "Add a new rule at the end of the ordered list (runs last)."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"const": "insert"
|
|
},
|
|
"index": {
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 9007199254740991,
|
|
"description": "Zero-based position to insert the rule at. Existing rules shift down."
|
|
},
|
|
"alias": {
|
|
"type": "string",
|
|
"description": "The human-readable replacement, e.g. \"/users/<id>/profile\". Use angle-bracket placeholders (<id>, <uuid>, <slug>) by convention. An empty string is valid — it deletes the matched text (e.g. to strip a \"?page=N\" fragment). Not a regex template — backreferences are not supported."
|
|
},
|
|
"regex": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"description": "A re2 pattern matched against the path, e.g. \"/users/\\\\d+/profile\". No need to escape \"/\". Anchor with ^ / $ when you mean it."
|
|
}
|
|
},
|
|
"required": ["action", "index", "alias", "regex"],
|
|
"description": "Insert a new rule at a specific position — use when it must run before more general rules."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"const": "replace"
|
|
},
|
|
"target_alias": {
|
|
"type": "string",
|
|
"description": "The alias of the existing rule to target (must match an existing rule exactly). Use \"\" to target a rule whose alias is empty."
|
|
},
|
|
"alias": {
|
|
"description": "New alias. Omit to keep the current alias.",
|
|
"type": "string"
|
|
},
|
|
"regex": {
|
|
"description": "New regex. Omit to keep the current regex.",
|
|
"type": "string",
|
|
"minLength": 1
|
|
}
|
|
},
|
|
"required": ["action", "target_alias"],
|
|
"description": "Replace the alias and/or regex of an existing rule, keeping its position."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"const": "remove"
|
|
},
|
|
"target_alias": {
|
|
"type": "string",
|
|
"description": "The alias of the existing rule to target (must match an existing rule exactly). Use \"\" to target a rule whose alias is empty."
|
|
}
|
|
},
|
|
"required": ["action", "target_alias"],
|
|
"description": "Remove an existing rule by alias."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"const": "reorder"
|
|
},
|
|
"ordered_aliases": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"description": "The full set of current aliases in the new desired order (including \"\" for any empty-alias rule and any duplicates). Must be a permutation of the existing aliases."
|
|
}
|
|
},
|
|
"required": ["action", "ordered_aliases"],
|
|
"description": "Reorder the existing rules. Order matters: rules apply sequentially, each feeding the next."
|
|
}
|
|
]
|
|
},
|
|
"description": "Ordered list of edits to apply to the current path cleaning rules, in sequence."
|
|
},
|
|
"sample_paths": {
|
|
"description": "Optional real paths (e.g. \"/users/123/profile\") to preview against, up to 25. The response shows how the resulting rule set rewrites each one. Approximate (JS regex, not re2) — use execute-sql with replaceRegexpAll to confirm edge cases.",
|
|
"maxItems": 25,
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"maxLength": 2048
|
|
}
|
|
},
|
|
"confirm": {
|
|
"default": false,
|
|
"description": "Must be true to persist. When false (default) the tool returns a preview of the resulting rules (and any sample-path rewrites) WITHOUT saving — surface it to the user, then re-run with confirm:true.",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": ["operations"]
|
|
},
|
|
"ProjectGetAllSchema": {
|
|
"type": "object",
|
|
"properties": {}
|
|
},
|
|
"ProjectSetActiveSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"projectId": {
|
|
"type": "integer",
|
|
"exclusiveMinimum": 0,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["projectId"]
|
|
},
|
|
"PromptListInputSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"search": {
|
|
"description": "Optional substring filter applied to prompt names and prompt content.",
|
|
"type": "string"
|
|
},
|
|
"content": {
|
|
"default": "none",
|
|
"description": "Controls how much prompt content is included in list results. 'full' includes the full prompt, 'preview' includes a short prompt_preview, and 'none' omits prompt content entirely.",
|
|
"type": "string",
|
|
"enum": ["full", "preview", "none"]
|
|
}
|
|
}
|
|
},
|
|
"PropertyDefinitionUpdateInputSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"description": {
|
|
"description": "Description explaining what the property represents",
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"description": "Tags to organize properties by product area (e.g. \"checkout\", \"onboarding\") or user journey stage (e.g. \"acquisition\", \"activation\", \"monetization\", \"retention\"). Warning: this REPLACES the property's entire tag list, it does not merge. To keep existing tags, include them alongside the new ones; to remove a tag, omit it. Omit this field entirely to leave tags unchanged.",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"property_type": {
|
|
"description": "The data type of the property. Controls how the property is parsed, displayed, and filtered.",
|
|
"type": "string",
|
|
"enum": ["DateTime", "String", "Numeric", "Boolean", "Duration"]
|
|
},
|
|
"verified": {
|
|
"description": "Mark as verified to indicate the property is correctly instrumented and safe to use",
|
|
"type": "boolean"
|
|
},
|
|
"hidden": {
|
|
"description": "Mark property as no longer used. Hides it from the UI while preserving historical data",
|
|
"type": "boolean"
|
|
}
|
|
}
|
|
},
|
|
"PropertyDefinitionUpdateSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"propertyName": {
|
|
"type": "string",
|
|
"description": "The exact name of the property to update (e.g. \"$browser\", \"plan_type\")"
|
|
},
|
|
"type": {
|
|
"default": "event",
|
|
"description": "Which property taxonomy the property belongs to. Defaults to \"event\" (event properties).",
|
|
"type": "string",
|
|
"enum": ["event", "person", "group", "session"]
|
|
},
|
|
"groupTypeIndex": {
|
|
"description": "Required when type is \"group\": the zero-based index of the group type the property belongs to.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
},
|
|
"data": {
|
|
"type": "object",
|
|
"properties": {
|
|
"description": {
|
|
"description": "Description explaining what the property represents",
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"description": "Tags to organize properties by product area (e.g. \"checkout\", \"onboarding\") or user journey stage (e.g. \"acquisition\", \"activation\", \"monetization\", \"retention\"). Warning: this REPLACES the property's entire tag list, it does not merge. To keep existing tags, include them alongside the new ones; to remove a tag, omit it. Omit this field entirely to leave tags unchanged.",
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"property_type": {
|
|
"description": "The data type of the property. Controls how the property is parsed, displayed, and filtered.",
|
|
"type": "string",
|
|
"enum": ["DateTime", "String", "Numeric", "Boolean", "Duration"]
|
|
},
|
|
"verified": {
|
|
"description": "Mark as verified to indicate the property is correctly instrumented and safe to use",
|
|
"type": "boolean"
|
|
},
|
|
"hidden": {
|
|
"description": "Mark property as no longer used. Hides it from the UI while preserving historical data",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"description": "The property definition data to update"
|
|
}
|
|
},
|
|
"required": ["propertyName", "data"]
|
|
},
|
|
"ReadDataSchemaSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"query": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "events"
|
|
},
|
|
"limit": {
|
|
"description": "Number of events to return per page.",
|
|
"default": 500,
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 500
|
|
},
|
|
"offset": {
|
|
"description": "Number of events to skip for pagination.",
|
|
"default": 0,
|
|
"type": "integer",
|
|
"minimum": 0,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["kind"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "event_properties"
|
|
},
|
|
"event_name": {
|
|
"type": "string",
|
|
"description": "The name of the event that you want to retrieve properties for."
|
|
}
|
|
},
|
|
"required": ["kind", "event_name"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "entity_properties"
|
|
},
|
|
"entity": {
|
|
"type": "string",
|
|
"description": "The type of the entity that you want to retrieve properties for."
|
|
}
|
|
},
|
|
"required": ["kind", "entity"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "action_properties"
|
|
},
|
|
"action_id": {
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991,
|
|
"description": "The ID of the action that you want to retrieve properties for."
|
|
}
|
|
},
|
|
"required": ["kind", "action_id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "entity_property_values"
|
|
},
|
|
"entity": {
|
|
"type": "string",
|
|
"description": "The type of the entity that you want to retrieve properties for."
|
|
},
|
|
"property_name": {
|
|
"type": "string",
|
|
"description": "Verified property name of an entity."
|
|
}
|
|
},
|
|
"required": ["kind", "entity", "property_name"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "event_property_values"
|
|
},
|
|
"event_name": {
|
|
"type": "string",
|
|
"description": "Verified event name"
|
|
},
|
|
"property_name": {
|
|
"type": "string",
|
|
"description": "Verified property name of an event."
|
|
}
|
|
},
|
|
"required": ["kind", "event_name", "property_name"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"kind": {
|
|
"type": "string",
|
|
"const": "action_property_values"
|
|
},
|
|
"action_id": {
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991,
|
|
"description": "Verified action ID"
|
|
},
|
|
"property_name": {
|
|
"type": "string",
|
|
"description": "Verified property name of an action."
|
|
}
|
|
},
|
|
"required": ["kind", "action_id", "property_name"]
|
|
}
|
|
],
|
|
"description": "The data schema query to execute."
|
|
}
|
|
},
|
|
"required": ["query"]
|
|
},
|
|
"SavedMetricsAttachSchema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991,
|
|
"description": "ID of an existing shared/saved metric. Discover IDs with experiment-saved-metrics-list."
|
|
},
|
|
"metadata": {
|
|
"description": "Optional per-link metadata. Omit to default this metric to primary.",
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["primary", "secondary"],
|
|
"description": "Whether this metric is a primary or secondary metric on the experiment."
|
|
}
|
|
},
|
|
"required": ["type"]
|
|
}
|
|
},
|
|
"required": ["id"]
|
|
},
|
|
"description": "The complete desired set of shared (saved) metrics for the experiment — this REPLACES all existing saved-metric links, it does not append. To add or remove one, first read the experiment's current saved_metrics via experiment-get and resend the full set. Pass an empty array to detach all shared metrics."
|
|
},
|
|
"ScoreDefinitionConfigSchema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"options": {
|
|
"minItems": 1,
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"key": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 128,
|
|
"description": "Stable option key — lowercase letters, numbers, underscores, hyphens. Sent back when this option is selected."
|
|
},
|
|
"label": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 256,
|
|
"description": "Human-readable label shown in the review UI."
|
|
}
|
|
},
|
|
"required": ["key", "label"]
|
|
},
|
|
"description": "Ordered categorical options. Must contain at least one option with unique keys."
|
|
},
|
|
"selection_mode": {
|
|
"description": "Whether reviewers select one option or many. Defaults to \"single\".",
|
|
"type": "string",
|
|
"enum": ["single", "multiple"]
|
|
},
|
|
"min_selections": {
|
|
"description": "Minimum selections required. Only valid when selection_mode is \"multiple\".",
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 9007199254740991
|
|
},
|
|
"max_selections": {
|
|
"description": "Maximum selections allowed. Only valid when selection_mode is \"multiple\".",
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["options"],
|
|
"additionalProperties": false,
|
|
"description": "Config shape used when kind is \"categorical\"."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"min": {
|
|
"description": "Optional inclusive minimum score.",
|
|
"type": "number"
|
|
},
|
|
"max": {
|
|
"description": "Optional inclusive maximum score (must be ≥ min).",
|
|
"type": "number"
|
|
},
|
|
"step": {
|
|
"description": "Optional increment step for numeric input, e.g. 1 or 0.5.",
|
|
"type": "number",
|
|
"exclusiveMinimum": 0
|
|
}
|
|
},
|
|
"additionalProperties": false,
|
|
"description": "Config shape used when kind is \"numeric\"."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"true_label": {
|
|
"description": "Optional label shown for the true branch (e.g. \"Yes\").",
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"false_label": {
|
|
"description": "Optional label shown for the false branch (e.g. \"No\").",
|
|
"type": "string",
|
|
"minLength": 1
|
|
}
|
|
},
|
|
"additionalProperties": false,
|
|
"description": "Config shape used when kind is \"boolean\"."
|
|
}
|
|
],
|
|
"description": "Immutable scorer configuration. Pick the shape matching the scorer kind: categorical (options + selection_mode), numeric (min/max/step), or boolean (true_label/false_label). The server validates the shape against the kind on the parent scorer and returns 400 on a mismatch."
|
|
},
|
|
"UsageMetricFiltersSchema": {
|
|
"anyOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"source": {
|
|
"type": "string",
|
|
"const": "data_warehouse"
|
|
},
|
|
"table_name": {
|
|
"type": "string",
|
|
"description": "Name of a synced data warehouse table. Use `external-data-schemas-list` to discover available tables."
|
|
},
|
|
"timestamp_field": {
|
|
"type": "string",
|
|
"description": "Timestamp column or InsightsQL expression on the row (e.g. \"created\" or \"toDateTime(created_at)\"). Use `execute-sql` (`SELECT * FROM <table> LIMIT 1`) to inspect available columns."
|
|
},
|
|
"key_field": {
|
|
"type": "string",
|
|
"description": "Column on the row whose value matches the entity key. v1 supports group profiles only — the column value is compared to the group_key."
|
|
}
|
|
},
|
|
"required": ["source", "table_name", "timestamp_field", "key_field"],
|
|
"description": "Data-warehouse-source filter shape."
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"events": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Event name (e.g. \"$pageview\")."
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"const": "events"
|
|
},
|
|
"order": {
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
},
|
|
"properties": {
|
|
"type": "array",
|
|
"items": {}
|
|
}
|
|
},
|
|
"required": ["id"]
|
|
},
|
|
"description": "Events to count or sum over."
|
|
},
|
|
"actions": {
|
|
"type": "array",
|
|
"items": {}
|
|
},
|
|
"properties": {
|
|
"type": "array",
|
|
"items": {}
|
|
},
|
|
"filter_test_accounts": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": ["events"],
|
|
"description": "Events-source filter shape (default)."
|
|
}
|
|
],
|
|
"description": "Filter definition. Pick exactly one branch: `data_warehouse` (set `source: \"data_warehouse\"` plus `table_name`/`timestamp_field`/`key_field`) or `events` (InsightsFunction filter shape with an `events` array)."
|
|
},
|
|
"WorkflowActionEmailPatchSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "The workflow (InsightsFlow) id."
|
|
},
|
|
"action_id": {
|
|
"type": "string",
|
|
"description": "Id of the function_email step whose email to edit."
|
|
},
|
|
"operations": {
|
|
"description": "Ordered edits applied atomically to the step's email design - the same operations as workflows-patch-email-template. The result is re-rendered to HTML server-side, so the sent email always matches the patched design. Reference blocks by id (read them via workflows-get).",
|
|
"minItems": 1,
|
|
"type": "array",
|
|
"items": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_content"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the content block to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial content-block fields, deep-merged into the existing block; a null leaf deletes that key. e.g. {values: {text: '<p>Hi</p>'}} changes only the block's text."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_column"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the column to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial column fields, deep-merged; a null leaf deletes that key."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_row"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the row to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial row fields, deep-merged; a null leaf deletes that key."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_body"
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial body fields, deep-merged. e.g. {values: {backgroundColor: '#ffffff'}}."
|
|
}
|
|
},
|
|
"required": ["op", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "add_content"
|
|
},
|
|
"column_id": {
|
|
"type": "string",
|
|
"description": "Id of the column to insert the block into."
|
|
},
|
|
"content": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "A content block {type, values: {...}}; omit id and values._meta — they are assigned server-side. type is one of text, heading, button, image, divider, html, etc."
|
|
},
|
|
"index": {
|
|
"description": "0-based insert position; omit to append to the end.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["op", "column_id", "content"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "remove_content"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the content block to remove."
|
|
}
|
|
},
|
|
"required": ["op", "id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "move_content"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the content block to move."
|
|
},
|
|
"column_id": {
|
|
"type": "string",
|
|
"description": "Id of the destination column."
|
|
},
|
|
"index": {
|
|
"description": "0-based position in the destination column; omit to append.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["op", "id", "column_id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "add_row"
|
|
},
|
|
"row": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "A full row {cells, columns: [{contents: [...], values}], values}; ids and Unlayer numbering are assigned server-side for the row and everything nested in it."
|
|
},
|
|
"index": {
|
|
"description": "0-based insert position; omit to append to the end.",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["op", "row"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "remove_row"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the row to remove."
|
|
}
|
|
},
|
|
"required": ["op", "id"]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"email_patch": {
|
|
"description": "Partial email fields deep-merged into the step's email (a null leaf deletes the key): subject, preheader, text, to, from, replyTo, cc, bcc. The design is edited via operations, and html is always re-rendered from it.",
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {}
|
|
},
|
|
"base_updated_at": {
|
|
"description": "Optimistic concurrency: the updated_at (or draft_updated_at) last loaded. If the stored workflow is newer, the patch is rejected with 409 instead of clobbering a concurrent edit.",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["id", "action_id"]
|
|
},
|
|
"WorkflowGraphPatchSchema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"description": "The workflow (InsightsFlow) id to edit."
|
|
},
|
|
"operations": {
|
|
"minItems": 1,
|
|
"type": "array",
|
|
"items": {
|
|
"oneOf": [
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "update_action"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the action to update."
|
|
},
|
|
"patch": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "Partial action fields, deep-merged into the existing action; a null leaf deletes that key. e.g. {config: {inputs: {subject: {value: \"Hi\"}}}} changes only that one input."
|
|
}
|
|
},
|
|
"required": ["op", "id", "patch"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "add_action"
|
|
},
|
|
"action": {
|
|
"type": "object",
|
|
"propertyNames": {
|
|
"type": "string"
|
|
},
|
|
"additionalProperties": {},
|
|
"description": "A full action node {id, name, type, config, ...}; same shape as entries in the workflow actions array."
|
|
}
|
|
},
|
|
"required": ["op", "action"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "remove_action"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Id of the action to remove. Its incoming edges reconnect to its first outgoer."
|
|
}
|
|
},
|
|
"required": ["op", "id"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "add_edge"
|
|
},
|
|
"edge": {
|
|
"type": "object",
|
|
"properties": {
|
|
"from": {
|
|
"type": "string",
|
|
"description": "Source action id."
|
|
},
|
|
"to": {
|
|
"type": "string",
|
|
"description": "Target action id."
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["continue", "branch"],
|
|
"description": "'continue' = fall-through (sequential or no-match path); 'branch' = a condition/cohort branch (needs index)."
|
|
},
|
|
"index": {
|
|
"description": "Required for type=branch: which condition/cohort slot this branch matches (0-based).",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["from", "to", "type"],
|
|
"description": "The edge to add."
|
|
}
|
|
},
|
|
"required": ["op", "edge"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "remove_edge"
|
|
},
|
|
"edge": {
|
|
"type": "object",
|
|
"properties": {
|
|
"from": {
|
|
"type": "string",
|
|
"description": "Source action id."
|
|
},
|
|
"to": {
|
|
"type": "string",
|
|
"description": "Target action id."
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["continue", "branch"],
|
|
"description": "'continue' = fall-through (sequential or no-match path); 'branch' = a condition/cohort branch (needs index)."
|
|
},
|
|
"index": {
|
|
"description": "Required for type=branch: which condition/cohort slot this branch matches (0-based).",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["from", "to", "type"],
|
|
"description": "The edge to remove (matched on from/to/type/index)."
|
|
}
|
|
},
|
|
"required": ["op", "edge"]
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"const": "replace_action_edges"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"description": "Action id whose outgoing edges are being replaced."
|
|
},
|
|
"edges": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"from": {
|
|
"type": "string",
|
|
"description": "Source action id."
|
|
},
|
|
"to": {
|
|
"type": "string",
|
|
"description": "Target action id."
|
|
},
|
|
"type": {
|
|
"type": "string",
|
|
"enum": ["continue", "branch"],
|
|
"description": "'continue' = fall-through (sequential or no-match path); 'branch' = a condition/cohort branch (needs index)."
|
|
},
|
|
"index": {
|
|
"description": "Required for type=branch: which condition/cohort slot this branch matches (0-based).",
|
|
"type": "integer",
|
|
"minimum": -9007199254740991,
|
|
"maximum": 9007199254740991
|
|
}
|
|
},
|
|
"required": ["from", "to", "type"]
|
|
},
|
|
"description": "The complete set of the action's outgoing edges; incoming edges are preserved."
|
|
}
|
|
},
|
|
"required": ["op", "id", "edges"]
|
|
}
|
|
]
|
|
},
|
|
"description": "Ordered graph edits applied atomically: the stored graph is read, ops are applied in order, the result is fully validated, and it is saved only if valid — otherwise the workflow is left unchanged. Reference nodes/edges by id so you never resend the whole graph. The full updated workflow is returned."
|
|
}
|
|
},
|
|
"required": ["id", "operations"]
|
|
}
|
|
}
|
|
}
|