{"paths":{"/v1/code/schema":{"get":{"description":"Get the JSON Schema for Steep YAML files, accepting both `module` and `targets` files. Point your editor at it to get autocomplete and inline errors while writing. No API key needed.","tags":["code"],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1CodeSchema"}},"/v1/code/schema/module":{"get":{"description":"Get the JSON Schema for a Steep YAML `module` file. No API key needed.","tags":["code"],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1CodeSchemaModule"}},"/v1/code/schema/targets":{"get":{"description":"Get the JSON Schema for a Steep YAML `targets` file. No API key needed.","tags":["code"],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1CodeSchemaTargets"}},"/v1/metrics":{"get":{"description":"List metrics for your workspace. Use for broader catalog exploration. For targeted discovery, prefer metric search over scanning this list. A metric or dimension may carry the data team's AI context. `synonyms`: Other names people use for this, e.g. abbreviations or terms in other languages. `examples` (metrics only): Sample questions this metric answers. `agentInstructions`: The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","tags":["metrics"],"x-steep":{"requiredScopes":["metrics:read"],"exposeUnderMCP":true},"parameters":[{"name":"expand","in":"query","required":false,"schema":{"default":"false","description":"Boolean string. When `true`, populates `dimensions`, `module`, `slices`, `cohort`, `owners`, `category`, `filters`, and `teamIdsWithAccess`. When `false`, those fields are `null`. Avoid `expand=true` unless filtering by `identifiers`, as an expanded full-catalog response can be large.","type":"string","format":"boolean"}},{"name":"identifiers","in":"query","required":false,"schema":{"description":"Filter to metrics with these exact `metric.identifier`s (Readable semantic model keys).","examples":[["revenue","order_count"]],"minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1}}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"skip":{"type":"number"},"data":{"type":"array","items":{"allOf":[{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"label":{"type":"string"},"description":{"type":["string","null"]},"link":{"type":"string","description":"A link to the metric in the app"},"isPrivate":{"type":"boolean"},"teamIdsWithAccess":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Team `id`s with access to this metric. Populated when `expand=true` for private metrics; otherwise `null`."},"isUnlisted":{"type":"boolean"},"updatedAt":{"type":"string","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))$"},"dimensions":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":["string","null"]},"type":{"type":"string","enum":["string-or-boolean","city","country","time","h3-cell-index"]},"description":{"type":["string","null"]},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","label","type","description","synonyms","agentInstructions"],"additionalProperties":false}},{"type":"null"}],"description":"Dimensions for this metric. Populated when `expand=true`; otherwise `null`."},"module":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":["string","null"]},"description":{"type":["string","null"]},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"table":{"type":"string"},"schema":{"type":"string"},"externalSource":{"anyOf":[{"type":"string","enum":["dbt-cloud","cube","code"]},{"type":"null"}]},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","label","description","identifier","table","schema","externalSource","synonyms","agentInstructions"],"additionalProperties":false,"title":"Module"},{"type":"null"}],"description":"Module for this metric. Populated when `expand=true`; otherwise `null`."},"slices":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":"string"},"description":{"type":["string","null"]},"filter":{"anyOf":[{"type":"object","properties":{"column":{"type":"string"},"operator":{"type":"string","enum":["equals","not-equals","less-than","less-than-or-equal","greater-than","greater-than-or-equal","in","not-in","is","is-not","like","not-like"]},"expression":{"type":"string"}},"required":["column","operator","expression"],"additionalProperties":false},{"type":"null"}]}},"required":["id","label","filter"],"additionalProperties":false}},{"type":"null"}],"description":"Slices for this metric. Populated when `expand=true`; otherwise `null`."},"cohort":{"anyOf":[{"type":"object","properties":{"deltaTimeCalculationType":{"anyOf":[{"type":"string","const":"calendar-periods"},{"type":"string","const":"rolling-periods"}]},"label":{"type":["string","null"]},"calculateRetention":{"description":"% of initial value.","type":["boolean","null"]},"timeGrains":{"anyOf":[{"type":"array","items":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]}},{"type":"null"}]},"time":{"type":"string"}},"required":["deltaTimeCalculationType","time"],"additionalProperties":false},{"type":"null"}],"description":"Cohort for this metric. Populated when `expand=true`; otherwise `null`."},"owners":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Owner user `id`s for this metric. Match `id` from list workspace members. Populated when `expand=true`; otherwise `null`."},"category":{"description":"Category name for this metric. Populated when `expand=true`; otherwise `null`.","type":["string","null"]},"time":{"description":"Time dimension for this metric, as `table.column`. `null` for derived-ratio metrics.","type":["string","null"]},"timeResampling":{"anyOf":[{"type":"string","enum":["sum/divide","average/repeat"]},{"type":"null"}]},"timeGrains":{"anyOf":[{"type":"array","items":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]}},{"type":"null"}]},"filters":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"column":{"type":"string"},"operator":{"type":"string","enum":["equals","not-equals","less-than","less-than-or-equal","greater-than","greater-than-or-equal","in","not-in","is","is-not","like","not-like"]},"expression":{"type":"string"}},"required":["column","operator","expression"],"additionalProperties":false}},{"type":"null"}],"description":"Filters for this metric. Populated when `expand=true`; otherwise `null`."},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"examples":{"type":"array","items":{"type":"string"},"description":"Sample questions this metric answers."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","identifier","label","description","link","isPrivate","teamIdsWithAccess","isUnlisted","updatedAt","dimensions","module","slices","cohort","owners","category","time","timeResampling","timeGrains","filters","synonyms","examples","agentInstructions"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"calculation":{"type":"string","const":"sum"},"value":{"type":"string"}},"required":["calculation","value"],"additionalProperties":false,"title":"Metric (sum)"},{"type":"object","properties":{"calculation":{"type":"string","const":"ratio"},"numerator":{"type":["string","null"]},"denominator":{"type":["string","null"]},"format":{"type":"string","enum":["number","percentage"]}},"required":["calculation","numerator","denominator","format"],"additionalProperties":false,"title":"Metric (ratio)"},{"type":"object","properties":{"calculation":{"type":"string","const":"count"}},"required":["calculation"],"additionalProperties":false,"title":"Metric (count)"},{"type":"object","properties":{"calculation":{"type":"string","const":"count-distinct"},"distinct_on":{"type":"string"}},"required":["calculation","distinct_on"],"additionalProperties":false,"title":"Metric (count distinct)"},{"type":"object","properties":{"calculation":{"type":"string","const":"custom-value"},"sqlExpression":{"type":"string"}},"required":["calculation","sqlExpression"],"additionalProperties":false,"title":"Metric (custom value)"},{"type":"object","properties":{"calculation":{"type":"string","const":"custom-ratio"},"numeratorSql":{"type":["string","null"]},"denominatorSql":{"type":["string","null"]},"format":{"type":"string","enum":["number","percentage"]}},"required":["calculation","numeratorSql","denominatorSql","format"],"additionalProperties":false,"title":"Metric (custom ratio)"},{"type":"object","properties":{"calculation":{"type":"string","const":"derived-ratio"},"numeratorMetricId":{"type":"string","description":"`id` of the metric used as the numerator"},"denominatorMetricId":{"type":"string","description":"`id` of the metric used as the denominator"},"format":{"type":"string","enum":["number","percentage"]}},"required":["calculation","numeratorMetricId","denominatorMetricId","format"],"additionalProperties":false,"title":"Metric (derived ratio)"}]}],"title":"Metric"}}},"required":["total","limit","skip","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1Metrics"}},"/v1/metrics/search":{"get":{"description":"Search metrics by keywords. Returns relevance-ranked search hits. Get further details via get metric by `id`, or list metrics filtered by `identifiers`. A metric or dimension may carry the data team's AI context. `synonyms`: Other names people use for this, e.g. abbreviations or terms in other languages. `examples` (metrics only): Sample questions this metric answers. `agentInstructions`: The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","tags":["metrics"],"x-steep":{"requiredScopes":["metrics:read"],"exposeUnderMCP":true},"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Search keywords."}},{"name":"limit","in":"query","required":false,"schema":{"default":10,"description":"Maximum number of hits to return.","type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"label":{"type":"string"},"link":{"type":"string"},"descriptionPreview":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Up to 200 characters of the metric description."},"timeGrains":{"anyOf":[{"type":"array","items":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]}},{"type":"null"}],"description":"Grains this metric can be queried at; `null` means all grains. A restricted set (e.g. only `monthly`) means query periods must align to whole allowed periods."},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"examples":{"type":"array","items":{"type":"string"},"description":"Sample questions this metric answers."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","identifier","label","link","descriptionPreview","timeGrains","synonyms","examples","agentInstructions"],"additionalProperties":false,"title":"Metric search hit"}}},"required":["data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1MetricsSearch"}},"/v1/metrics/{metricId}":{"get":{"description":"Get a single metric by `id`. A metric or dimension may carry the data team's AI context. `synonyms`: Other names people use for this, e.g. abbreviations or terms in other languages. `examples` (metrics only): Sample questions this metric answers. `agentInstructions`: The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","tags":["metrics"],"x-steep":{"requiredScopes":["metrics:read"],"exposeUnderMCP":true},"parameters":[{"name":"metricId","in":"path","required":true,"schema":{"type":"string","description":"`metric.id` — Unique resource ID (opaque)."}},{"name":"expand","in":"query","required":false,"schema":{"default":"false","description":"Boolean string. When `true`, populates `dimensions`, `module`, `slices`, `cohort`, `owners`, `category`, `filters`, and `teamIdsWithAccess`. When `false`, those fields are `null`.","type":"string","format":"boolean"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","allOf":[{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"label":{"type":"string"},"description":{"type":["string","null"]},"link":{"type":"string","description":"A link to the metric in the app"},"isPrivate":{"type":"boolean"},"teamIdsWithAccess":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Team `id`s with access to this metric. Populated when `expand=true` for private metrics; otherwise `null`."},"isUnlisted":{"type":"boolean"},"updatedAt":{"type":"string","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))$"},"dimensions":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":["string","null"]},"type":{"type":"string","enum":["string-or-boolean","city","country","time","h3-cell-index"]},"description":{"type":["string","null"]},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","label","type","description","synonyms","agentInstructions"],"additionalProperties":false}},{"type":"null"}],"description":"Dimensions for this metric. Populated when `expand=true`; otherwise `null`."},"module":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":["string","null"]},"description":{"type":["string","null"]},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"table":{"type":"string"},"schema":{"type":"string"},"externalSource":{"anyOf":[{"type":"string","enum":["dbt-cloud","cube","code"]},{"type":"null"}]},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","label","description","identifier","table","schema","externalSource","synonyms","agentInstructions"],"additionalProperties":false,"title":"Module"},{"type":"null"}],"description":"Module for this metric. Populated when `expand=true`; otherwise `null`."},"slices":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":"string"},"description":{"type":["string","null"]},"filter":{"anyOf":[{"type":"object","properties":{"column":{"type":"string"},"operator":{"type":"string","enum":["equals","not-equals","less-than","less-than-or-equal","greater-than","greater-than-or-equal","in","not-in","is","is-not","like","not-like"]},"expression":{"type":"string"}},"required":["column","operator","expression"],"additionalProperties":false},{"type":"null"}]}},"required":["id","label","filter"],"additionalProperties":false}},{"type":"null"}],"description":"Slices for this metric. Populated when `expand=true`; otherwise `null`."},"cohort":{"anyOf":[{"type":"object","properties":{"deltaTimeCalculationType":{"anyOf":[{"type":"string","const":"calendar-periods"},{"type":"string","const":"rolling-periods"}]},"label":{"type":["string","null"]},"calculateRetention":{"description":"% of initial value.","type":["boolean","null"]},"timeGrains":{"anyOf":[{"type":"array","items":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]}},{"type":"null"}]},"time":{"type":"string"}},"required":["deltaTimeCalculationType","time"],"additionalProperties":false},{"type":"null"}],"description":"Cohort for this metric. Populated when `expand=true`; otherwise `null`."},"owners":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Owner user `id`s for this metric. Match `id` from list workspace members. Populated when `expand=true`; otherwise `null`."},"category":{"description":"Category name for this metric. Populated when `expand=true`; otherwise `null`.","type":["string","null"]},"time":{"description":"Time dimension for this metric, as `table.column`. `null` for derived-ratio metrics.","type":["string","null"]},"timeResampling":{"anyOf":[{"type":"string","enum":["sum/divide","average/repeat"]},{"type":"null"}]},"timeGrains":{"anyOf":[{"type":"array","items":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]}},{"type":"null"}]},"filters":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"column":{"type":"string"},"operator":{"type":"string","enum":["equals","not-equals","less-than","less-than-or-equal","greater-than","greater-than-or-equal","in","not-in","is","is-not","like","not-like"]},"expression":{"type":"string"}},"required":["column","operator","expression"],"additionalProperties":false}},{"type":"null"}],"description":"Filters for this metric. Populated when `expand=true`; otherwise `null`."},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"examples":{"type":"array","items":{"type":"string"},"description":"Sample questions this metric answers."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","identifier","label","description","link","isPrivate","teamIdsWithAccess","isUnlisted","updatedAt","dimensions","module","slices","cohort","owners","category","time","timeResampling","timeGrains","filters","synonyms","examples","agentInstructions"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"calculation":{"type":"string","const":"sum"},"value":{"type":"string"}},"required":["calculation","value"],"additionalProperties":false,"title":"Metric (sum)"},{"type":"object","properties":{"calculation":{"type":"string","const":"ratio"},"numerator":{"type":["string","null"]},"denominator":{"type":["string","null"]},"format":{"type":"string","enum":["number","percentage"]}},"required":["calculation","numerator","denominator","format"],"additionalProperties":false,"title":"Metric (ratio)"},{"type":"object","properties":{"calculation":{"type":"string","const":"count"}},"required":["calculation"],"additionalProperties":false,"title":"Metric (count)"},{"type":"object","properties":{"calculation":{"type":"string","const":"count-distinct"},"distinct_on":{"type":"string"}},"required":["calculation","distinct_on"],"additionalProperties":false,"title":"Metric (count distinct)"},{"type":"object","properties":{"calculation":{"type":"string","const":"custom-value"},"sqlExpression":{"type":"string"}},"required":["calculation","sqlExpression"],"additionalProperties":false,"title":"Metric (custom value)"},{"type":"object","properties":{"calculation":{"type":"string","const":"custom-ratio"},"numeratorSql":{"type":["string","null"]},"denominatorSql":{"type":["string","null"]},"format":{"type":"string","enum":["number","percentage"]}},"required":["calculation","numeratorSql","denominatorSql","format"],"additionalProperties":false,"title":"Metric (custom ratio)"},{"type":"object","properties":{"calculation":{"type":"string","const":"derived-ratio"},"numeratorMetricId":{"type":"string","description":"`id` of the metric used as the numerator"},"denominatorMetricId":{"type":"string","description":"`id` of the metric used as the denominator"},"format":{"type":"string","enum":["number","percentage"]}},"required":["calculation","numeratorMetricId","denominatorMetricId","format"],"additionalProperties":false,"title":"Metric (derived ratio)"}]}],"title":"Metric"}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1MetricsByMetricId"}},"/v1/metrics/{metricId}/query":{"post":{"description":"Query data for a metric, optionally for a specific slice. Returns metric values for the requested date range. Omit `timeGrain` for a single aggregate over the period; set it for time-series data. Supports breakdown dimensions and filters.","tags":["metrics"],"x-steep":{"requiredScopes":["metrics:read","dataqueries:read"],"exposeUnderMCP":true},"parameters":[{"name":"metricId","in":"path","required":true,"schema":{"type":"string","description":"`metric.id` — Unique resource ID (opaque)."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"timeGrain":{"description":"Time grain for aggregation. Omit for a single aggregate over the whole period. Most metrics accept any range, but for a metric with restricted grains (check its allowed time grains) both ends must align to whole-period boundaries of an allowed grain — and without an explicit timeGrain the range may have to be a single whole period, so to span several periods set timeGrain to an allowed grain and align to its boundaries. E.g. a monthly-only metric: one whole calendar month 2026-05-01 to 2026-05-31, or timeGrain=monthly over month-aligned dates to span months; never use today's date as a boundary (2026-06-01 to 2026-06-24 is rejected).","type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},"fromDate":{"type":"string","description":"Start of the query period (ISO 8601). Inclusive — it is part of the range, so a colloquial period spans exactly its calendar days. With a timeGrain, align to the first day of a period (e.g. monthly: 2026-05-01)."},"toDate":{"type":"string","description":"End of the query period (ISO 8601). Inclusive — the last day counts, so one month is 2026-05-01 to 2026-05-31, not 2026-06-01. With a timeGrain, align to the last day of a period (e.g. monthly: 2026-05-31)."},"breakdownDimensionIds":{"description":"Dimension `id`s to break down by.","type":"array","items":{"type":"string"}},"sliceId":{"description":"Slice `id` to fetch query data for.","type":"string"},"filters":{"description":"Dimension filters to apply.","type":"array","items":{"type":"object","properties":{"dimensionId":{"type":"string","description":"Dimension `id` to filter by."},"filterValues":{"type":"array","items":{"type":"string"},"description":"Filter values for this dimension.","examples":[["US","UK"]]}},"required":["dimensionId","filterValues"],"additionalProperties":false}},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or reduce the result set (eg. shorter time period, coarser `timeGrain`, stricter filters).","type":"integer","minimum":1,"maximum":500000}},"required":["fromDate","toDate"],"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"timeGrain":{"description":"Time grain for aggregation. Omit for a single aggregate over the whole period. Most metrics accept any range, but for a metric with restricted grains (check its allowed time grains) both ends must align to whole-period boundaries of an allowed grain — and without an explicit timeGrain the range may have to be a single whole period, so to span several periods set timeGrain to an allowed grain and align to its boundaries. E.g. a monthly-only metric: one whole calendar month 2026-05-01 to 2026-05-31, or timeGrain=monthly over month-aligned dates to span months; never use today's date as a boundary (2026-06-01 to 2026-06-24 is rejected).","type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},"fromDate":{"type":"string","description":"Start of the query period (ISO 8601). Inclusive — it is part of the range, so a colloquial period spans exactly its calendar days. With a timeGrain, align to the first day of a period (e.g. monthly: 2026-05-01)."},"toDate":{"type":"string","description":"End of the query period (ISO 8601). Inclusive — the last day counts, so one month is 2026-05-01 to 2026-05-31, not 2026-06-01. With a timeGrain, align to the last day of a period (e.g. monthly: 2026-05-31)."},"breakdownDimensionIds":{"description":"Dimension `id`s to break down by.","type":"array","items":{"type":"string"}},"sliceId":{"description":"Slice `id` to fetch query data for.","type":"string"},"filters":{"description":"Dimension filters to apply.","type":"array","items":{"type":"object","properties":{"dimensionId":{"type":"string","description":"Dimension `id` to filter by."},"filterValues":{"type":"array","items":{"type":"string"},"description":"Filter values for this dimension.","examples":[["US","UK"]]}},"required":["dimensionId","filterValues"],"additionalProperties":false}},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or reduce the result set (eg. shorter time period, coarser `timeGrain`, stricter filters).","type":"integer","minimum":1,"maximum":500000}},"required":["fromDate","toDate"],"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"timeGrain":{"description":"Time grain for aggregation. Omit for a single aggregate over the whole period. Most metrics accept any range, but for a metric with restricted grains (check its allowed time grains) both ends must align to whole-period boundaries of an allowed grain — and without an explicit timeGrain the range may have to be a single whole period, so to span several periods set timeGrain to an allowed grain and align to its boundaries. E.g. a monthly-only metric: one whole calendar month 2026-05-01 to 2026-05-31, or timeGrain=monthly over month-aligned dates to span months; never use today's date as a boundary (2026-06-01 to 2026-06-24 is rejected).","type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},"fromDate":{"type":"string","description":"Start of the query period (ISO 8601). Inclusive — it is part of the range, so a colloquial period spans exactly its calendar days. With a timeGrain, align to the first day of a period (e.g. monthly: 2026-05-01)."},"toDate":{"type":"string","description":"End of the query period (ISO 8601). Inclusive — the last day counts, so one month is 2026-05-01 to 2026-05-31, not 2026-06-01. With a timeGrain, align to the last day of a period (e.g. monthly: 2026-05-31)."},"breakdownDimensionIds":{"description":"Dimension `id`s to break down by.","type":"array","items":{"type":"string"}},"sliceId":{"description":"Slice `id` to fetch query data for.","type":"string"},"filters":{"description":"Dimension filters to apply.","type":"array","items":{"type":"object","properties":{"dimensionId":{"type":"string","description":"Dimension `id` to filter by."},"filterValues":{"type":"array","items":{"type":"string"},"description":"Filter values for this dimension.","examples":[["US","UK"]]}},"required":["dimensionId","filterValues"],"additionalProperties":false}},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or reduce the result set (eg. shorter time period, coarser `timeGrain`, stricter filters).","type":"integer","minimum":1,"maximum":500000}},"required":["fromDate","toDate"],"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"cacheTtlInSeconds":{"type":"number"},"refreshedAt":{"type":"string","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))$"},"sql":{"type":"string"},"limit":{"type":"number","description":"The effective row limit applied to this query."},"hasMore":{"type":"boolean","description":"Indicates there is more data beyond the row limit."},"data":{"type":"array","items":{"type":"object","properties":{"time":{"type":"string","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))$","description":"The time of the data point. Undefined if timeGrain is not provided."},"metric":{"description":"The metric value for the given time.","type":["number","null"]}},"required":["metric"],"additionalProperties":{"title":"Breakdown value","description":"Breakdown value for the given breakdown dimension. The field name matches the breakdown dimension identifier.","type":["string","number","boolean","null"]},"title":"Data point"}}},"required":["cacheTtlInSeconds","refreshedAt","sql","limit","hasMore","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1MetricsByMetricIdQuery"}},"/v1/targets":{"get":{"description":"List available target series and their metrics for your workspace. Use for broader target series exploration, or filter by metric `identifier` if metrics of interest are already known.","tags":["targets"],"x-steep":{"requiredScopes":["targets:read"],"exposeUnderMCP":true},"parameters":[{"name":"metricIdentifiers","in":"query","required":false,"schema":{"description":"Filter to targets for these exact `metric.identifier`s (Readable semantic model keys).","minItems":1,"maxItems":50,"type":"array","items":{"type":"string","minLength":1}}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"targetSeries":{"type":"string"},"metricIdentifier":{"type":"string"},"timeGrain":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"null"}]},"fromDate":{"type":"string"},"toDate":{"type":"string"},"rowCount":{"type":"number"},"dimensionValues":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","number"]}},{"type":"null"}],"description":"Map of dimension identifier to value for this target row. Keys are dimension identifiers (e.g. \"country\", \"region\"). Null when the target has no dimension breakdown.","examples":[{"country":"US"}]}},"required":["targetSeries","metricIdentifier","timeGrain","fromDate","toDate","rowCount","dimensionValues"],"additionalProperties":false,"title":"Target row"}}},"required":["data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1Targets"}},"/v1/targets/query":{"post":{"description":"Query time-series target data for a metric and target series.","tags":["targets"],"x-steep":{"requiredScopes":["target-queries:read"],"exposeUnderMCP":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"metricIdentifier":{"type":"string","description":"The `metric.identifier` to query targets for. Must match the `metricIdentifier` value returned when listing targets."},"targetSeries":{"type":"string","description":"The target series to query. Must match the `targetSeries` value returned when listing targets."},"breakdownDimensionIdentifiers":{"description":"Dimension `identifier`s to break down by. Use keys from a `dimensionValues` object returned when listing targets (`{ dimensionIdentifier: dimensionValue }`). Every combination of values becomes a separate data point carrying each value under its identifier; a `dimensionFilters` entry for a dimension narrows it to the listed values.","examples":[["country","product"]],"minItems":1,"type":"array","items":{"type":"string","minLength":1}},"breakdownDimensionIdentifier":{"deprecated":true,"description":"Deprecated, use `breakdownDimensionIdentifiers` with one entry. One dimension `identifier` to break down by; each data point also repeats the value under the deprecated `breakdown`.","examples":["country"],"type":"string"},"dimensionFilters":{"description":"Dimension filters to apply. Keys are dimension `identifier`s; values are allowed values. Derive both from `dimensionValues` returned when listing targets — e.g. `{ \"country\": \"US\" }` → `{ \"country\": [\"US\"] }`.","examples":[{"country":["US","UK"]}],"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or apply stricter filters.","type":"integer","minimum":1,"maximum":500000}},"required":["metricIdentifier","targetSeries"],"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"metricIdentifier":{"type":"string","description":"The `metric.identifier` to query targets for. Must match the `metricIdentifier` value returned when listing targets."},"targetSeries":{"type":"string","description":"The target series to query. Must match the `targetSeries` value returned when listing targets."},"breakdownDimensionIdentifiers":{"description":"Dimension `identifier`s to break down by. Use keys from a `dimensionValues` object returned when listing targets (`{ dimensionIdentifier: dimensionValue }`). Every combination of values becomes a separate data point carrying each value under its identifier; a `dimensionFilters` entry for a dimension narrows it to the listed values.","examples":[["country","product"]],"minItems":1,"type":"array","items":{"type":"string","minLength":1}},"breakdownDimensionIdentifier":{"deprecated":true,"description":"Deprecated, use `breakdownDimensionIdentifiers` with one entry. One dimension `identifier` to break down by; each data point also repeats the value under the deprecated `breakdown`.","examples":["country"],"type":"string"},"dimensionFilters":{"description":"Dimension filters to apply. Keys are dimension `identifier`s; values are allowed values. Derive both from `dimensionValues` returned when listing targets — e.g. `{ \"country\": \"US\" }` → `{ \"country\": [\"US\"] }`.","examples":[{"country":["US","UK"]}],"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or apply stricter filters.","type":"integer","minimum":1,"maximum":500000}},"required":["metricIdentifier","targetSeries"],"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"metricIdentifier":{"type":"string","description":"The `metric.identifier` to query targets for. Must match the `metricIdentifier` value returned when listing targets."},"targetSeries":{"type":"string","description":"The target series to query. Must match the `targetSeries` value returned when listing targets."},"breakdownDimensionIdentifiers":{"description":"Dimension `identifier`s to break down by. Use keys from a `dimensionValues` object returned when listing targets (`{ dimensionIdentifier: dimensionValue }`). Every combination of values becomes a separate data point carrying each value under its identifier; a `dimensionFilters` entry for a dimension narrows it to the listed values.","examples":[["country","product"]],"minItems":1,"type":"array","items":{"type":"string","minLength":1}},"breakdownDimensionIdentifier":{"deprecated":true,"description":"Deprecated, use `breakdownDimensionIdentifiers` with one entry. One dimension `identifier` to break down by; each data point also repeats the value under the deprecated `breakdown`.","examples":["country"],"type":"string"},"dimensionFilters":{"description":"Dimension filters to apply. Keys are dimension `identifier`s; values are allowed values. Derive both from `dimensionValues` returned when listing targets — e.g. `{ \"country\": \"US\" }` → `{ \"country\": [\"US\"] }`.","examples":[{"country":["US","UK"]}],"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or apply stricter filters.","type":"integer","minimum":1,"maximum":500000}},"required":["metricIdentifier","targetSeries"],"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"time":{"type":"string","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))$","description":"The time of the data point."},"value":{"description":"The target value for the given time. Null when the target leaves the period blank.","type":["number","null"]},"breakdown":{"deprecated":true,"description":"Deprecated. Present only when the request used `breakdownDimensionIdentifier`; the same value sits under the dimension's identifier.","type":["string","number","boolean"]}},"required":["time","value"],"additionalProperties":{"title":"Breakdown value","description":"Breakdown value for the given breakdown dimension. The field name matches the breakdown dimension identifier.","type":["string","number","boolean","null"]},"title":"Target data point"}},"timeGrain":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"null"}]},"cacheTtlInSeconds":{"type":["number","null"]},"limit":{"type":"number","description":"The effective row limit applied to this query."},"hasMore":{"type":"boolean","description":"Indicates there is more data beyond the row limit."}},"required":["data","timeGrain","cacheTtlInSeconds","limit","hasMore"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1TargetsQuery"}},"/v1/entities":{"get":{"description":"List entities for your workspace.","tags":["entities"],"x-steep":{"requiredScopes":["entities:read"],"exposeUnderMCP":true},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"skip":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"name":{"type":"string","description":"Display name. Not unique — `identifier` is the stable key."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]},"moduleId":{"type":"string","description":"`id` of the module this entity belongs to."},"module":{"type":"string","description":"`identifier` of the module this entity belongs to. Readable semantic model key. Used to cross-reference objects in the semantic model."}},"required":["id","identifier","name","createdAt","updatedAt","synonyms","agentInstructions","moduleId","module"],"additionalProperties":false,"title":"Entity"}}},"required":["total","limit","skip","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1Entities"}},"/v1/entities/{entityId}":{"get":{"description":"Get a single entity by `id`, with its properties, primary key column and linked metrics. Use after list entities to inspect what an entity holds.","tags":["entities"],"x-steep":{"requiredScopes":["entities:read"],"exposeUnderMCP":true},"parameters":[{"name":"entityId","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"`entity.id` — Unique resource ID (opaque)."}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"name":{"type":"string","description":"Display name. Not unique — `identifier` is the stable key."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]},"module":{"type":"string","description":"`identifier` of the module this entity belongs to. Readable semantic model key. Used to cross-reference objects in the semantic model."},"primaryKeyColumn":{"type":"string","description":"Warehouse column that uniquely identifies a row."},"properties":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["number","time","date","string","boolean","uuid","geography"]},"column":{"type":"string","description":"Warehouse column backing this property.","examples":["email"]}},"required":["name","type","column"],"additionalProperties":false,"title":"Entity property"},"description":"Attributes of this entity, in display order."},"metricIdentifiers":{"type":"array","items":{"type":"string"},"description":"`identifier`s of the metrics linked to this entity. Match `identifier` from list metrics, search metrics, or get metric by `id`."},"externalSource":{"anyOf":[{"type":"string","enum":["dbt-cloud","cube","code"]},{"type":"null"}],"description":"System that manages this definition. `null` when managed in Steep."}},"required":["id","identifier","name","createdAt","updatedAt","synonyms","agentInstructions","module","primaryKeyColumn","properties","metricIdentifiers","externalSource"],"additionalProperties":false,"title":"Entity detail"}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1EntitiesByEntityId"}},"/v1/entities/{entityId}/query":{"post":{"description":"Query rows of an entity. Returns one object per row, keyed by property `column`. Use get entity by `id` first to learn which columns exist, then filter and sort by them.","tags":["entities"],"x-steep":{"requiredScopes":["entities:read","entity-queries:read"],"exposeUnderMCP":true},"parameters":[{"name":"entityId","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"`entity.id` — Unique resource ID (opaque)."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"filters":{"description":"Property filters to apply. Rows must match every filter.","type":"array","items":{"type":"object","properties":{"column":{"type":"string","description":"Property `column`, as published by get entity by `id`."},"operator":{"description":"Comparison operator. Defaults to `=`. A `date` or `time` property takes only `>=`, `<=` or `=`, and compares whole days.","type":"string","enum":["=","!=","<","<=",">",">="]},"values":{"minItems":1,"type":"array","items":{"type":["string","number","boolean","null"]},"description":"Values to compare against. A row matches any of them, or none of them for `!=`. A `date` or `time` property takes exactly one date string — express a range as two filters on the same column.","examples":[["US","UK"]]}},"required":["column","values"],"additionalProperties":false}},"sortBy":{"description":"Property to sort by. Defaults to the entity's first sortable property.","type":"object","properties":{"column":{"type":"string","description":"Property `column`, as published by get entity by `id`."},"direction":{"description":"Sort direction. Defaults to `asc`.","type":"string","enum":["asc","desc"]}},"required":["column"],"additionalProperties":false},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or narrow the result set with stricter `filters`.","type":"integer","minimum":1,"maximum":500000}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"filters":{"description":"Property filters to apply. Rows must match every filter.","type":"array","items":{"type":"object","properties":{"column":{"type":"string","description":"Property `column`, as published by get entity by `id`."},"operator":{"description":"Comparison operator. Defaults to `=`. A `date` or `time` property takes only `>=`, `<=` or `=`, and compares whole days.","type":"string","enum":["=","!=","<","<=",">",">="]},"values":{"minItems":1,"type":"array","items":{"type":["string","number","boolean","null"]},"description":"Values to compare against. A row matches any of them, or none of them for `!=`. A `date` or `time` property takes exactly one date string — express a range as two filters on the same column.","examples":[["US","UK"]]}},"required":["column","values"],"additionalProperties":false}},"sortBy":{"description":"Property to sort by. Defaults to the entity's first sortable property.","type":"object","properties":{"column":{"type":"string","description":"Property `column`, as published by get entity by `id`."},"direction":{"description":"Sort direction. Defaults to `asc`.","type":"string","enum":["asc","desc"]}},"required":["column"],"additionalProperties":false},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or narrow the result set with stricter `filters`.","type":"integer","minimum":1,"maximum":500000}},"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"filters":{"description":"Property filters to apply. Rows must match every filter.","type":"array","items":{"type":"object","properties":{"column":{"type":"string","description":"Property `column`, as published by get entity by `id`."},"operator":{"description":"Comparison operator. Defaults to `=`. A `date` or `time` property takes only `>=`, `<=` or `=`, and compares whole days.","type":"string","enum":["=","!=","<","<=",">",">="]},"values":{"minItems":1,"type":"array","items":{"type":["string","number","boolean","null"]},"description":"Values to compare against. A row matches any of them, or none of them for `!=`. A `date` or `time` property takes exactly one date string — express a range as two filters on the same column.","examples":[["US","UK"]]}},"required":["column","values"],"additionalProperties":false}},"sortBy":{"description":"Property to sort by. Defaults to the entity's first sortable property.","type":"object","properties":{"column":{"type":"string","description":"Property `column`, as published by get entity by `id`."},"direction":{"description":"Sort direction. Defaults to `asc`.","type":"string","enum":["asc","desc"]}},"required":["column"],"additionalProperties":false},"limit":{"default":1000,"description":"Maximum number of rows to return. When the row limit is reached, response `hasMore` is `true`. For a more complete result, increase `limit` or narrow the result set with stricter `filters`.","type":"integer","minimum":1,"maximum":500000}},"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"cacheTtlInSeconds":{"type":["number","null"]},"sql":{"type":"string"},"limit":{"type":"number","description":"The effective row limit applied to this query."},"hasMore":{"type":"boolean","description":"Indicates there is more data beyond the row limit."},"data":{"type":"array","items":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"title":"Property value","description":"Value for the given property. The field name matches the property `column`.","type":["string","number","boolean","null"]},"title":"Entity row"}}},"required":["cacheTtlInSeconds","sql","limit","hasMore","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1EntitiesByEntityIdQuery"}},"/v1/modules":{"get":{"description":"List modules for your workspace.","tags":["modules"],"x-steep":{"requiredScopes":["modules:read"],"exposeUnderMCP":true},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"skip":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"label":{"type":["string","null"]},"description":{"type":["string","null"]},"identifier":{"type":"string","description":"Readable semantic model key. Used to cross-reference objects in the semantic model."},"table":{"type":"string"},"schema":{"type":"string"},"externalSource":{"anyOf":[{"type":"string","enum":["dbt-cloud","cube","code"]},{"type":"null"}]},"synonyms":{"type":"array","items":{"type":"string"},"description":"Other names people use for this, e.g. abbreviations or terms in other languages."},"agentInstructions":{"description":"The data team's guidance for AI agents on using this. Follow it whenever this is part of what you query or present.","type":["string","null"]}},"required":["id","label","description","identifier","table","schema","externalSource","synonyms","agentInstructions"],"additionalProperties":false,"title":"Module"}}},"required":["total","limit","skip","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1Modules"}},"/v1/reports":{"post":{"description":"Create a new report: a saved, shareable document that persists in the workspace as a lasting artifact to revisit or share. Build its body from the `blocks` field. Returns the new report's `id`, title and `link` to open it in the Steep app.","tags":["reports"],"x-steep":{"requiredScopes":["reports:write"],"exposeUnderMCP":true},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Report title. Concise and descriptive."},"blocks":{"maxItems":100,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"properties":{"type":"object","properties":{"body":{"type":"string","description":"Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage."}},"required":["body"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"chart"},"properties":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID to visualize."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"timeGrainMode":{"default":"auto","description":"Either an explicit grain, or 'auto' to let the system choose.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"dimensionSettings":{"type":"object","properties":{"breakdown":{"description":"Dimension ID used for breakdown. Required for rank charts.","type":"string"},"filters":{"default":{},"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["filters"],"additionalProperties":false,"description":"Breakdown and filter configuration."},"targetName":{"description":"When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.","type":"string"},"metrics":{"description":"Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.","type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for the comparison series."},"sliceId":{"default":null,"description":"Optional slice/segment ID for the comparison series.","type":["string","null"]},"applyFilters":{"default":true,"description":"Whether to apply the chart's dimension filters to this series.","type":"boolean"},"yAxis":{"default":"right","description":"Which Y-axis this comparison series should use.","type":"string","enum":["left","right"]},"vizType":{"default":"line","description":"How to render the comparison series.","type":"string","enum":["line","bar"]}},"required":["metricId","sliceId","applyFilters","yAxis","vizType"],"additionalProperties":false,"description":"Compare the primary metric to another, different metric (e.g. revenue vs costs, metric A vs metric B)."}},"compares":{"description":"Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.","type":"array","items":{"type":"string","enum":["min","max","avg","lag-1y","last-period","x-over-x","year-over-year","avg-7d","avg-28d","lag-1y-same-weekday","year-over-year-same-weekday"],"description":"Period-over-period comparisons and same-metric derivations, shown only on a line or bar chart. Use ONLY a comparison the metric reports in its `compares` hint (from SearchMetrics/GetMetricDetails) — e.g. ratio metrics exclude year-over-year/x-over-x, so use lag-1y there — and respect that hint's daily-grain constraints. lag-1y and year-over-year overlay the same period from last year; last-period overlays the absolute values of the previous period of equal length as a comparison series (use this when user asks 'last week vs previous week', 'last 2 years vs previous 2 years', etc.); x-over-x shows the percentage change vs the previous period as a separate line — these are mutually exclusive alternatives, do NOT add both, pick only the one the user is asking for; min/max/avg aggregate over the visible range; avg-7d/avg-28d are moving averages; lag-1y-same-weekday and year-over-year-same-weekday align by weekday for year comparisons."}},"cumulative":{"default":false,"description":"Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.","type":"boolean"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional chart title to display above the visualization.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown items.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown items to show (e.g. top 3). Rank charts allow up to 1000; other chart types cap at 50.","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' row.","type":"boolean"},"show100PercentBars":{"description":"Show bars as percentages (only relevant for some charts).","type":"boolean"}},"additionalProperties":false},"showValues":{"default":"none","type":"string","enum":["none","main-metric","all"],"description":"Value labels visibility. Displayed above the data points or bars."},"pivotTable":{"type":"object","properties":{"rows":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"cols":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"totalsStyle":{"default":"none","description":"Whether to show row/column totals.","type":"string","enum":["none","rows-and-columns","columns","rows"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false}},"required":["tableStyle","totalsStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Pivot table configuration (rows/cols and rendering options)."},"cohortsTable":{"type":"object","properties":{"cohortId":{"description":"Cohort definition identifier.","type":"string"},"cohortTimeGrain":{"default":"auto","description":"Time grain used to bucket cohorts.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"deltaTimeGrain":{"default":"auto","description":"Time grain used for the delta/age axis.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false},"deltaTimeThresholds":{"description":"Optional [min, max] thresholds for the delta-time axis.","type":"array","prefixItems":[{"type":["number","null"]},{"type":["number","null"]}],"items":false,"minItems":2,"maxItems":2}},"required":["cohortTimeGrain","deltaTimeGrain","tableStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Cohorts table configuration."},"chartType":{"type":"string","enum":["line","bar","rank","pivot-table","cohorts-table"],"description":"Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["metricId","timeGrainMode","cumulative","showValues","chartType","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A chart visualizing a metric."},{"type":"object","properties":{"type":{"type":"string","const":"big-number"},"properties":{"type":"object","properties":{"variant":{"default":"metrics","type":"string","enum":["metrics","breakdown"],"description":"Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric."},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for this tile."},"sliceId":{"default":null,"description":"Optional slice/segment ID, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"description":"A metric (optionally narrowed to a slice) shown as one tile."},"description":"Metrics to show, one tile each. The breakdown variant uses exactly one entry."},"breakdownDimensionId":{"description":"Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.","type":"string"},"filters":{"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}},"compare":{"description":"Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.","type":"string","enum":["lag-1y","last-period"]},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional title displayed above the tiles.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown tiles.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown tiles to show (e.g. top 3).","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' tile.","type":"boolean"},"show100PercentBars":{"description":"Not rendered by big numbers; carried for type parity.","type":"boolean"}},"additionalProperties":false},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["variant","metricSliceIds","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail."},{"type":"object","properties":{"type":{"type":"string","const":"table"},"properties":{"type":"object","properties":{"title":{"description":"Optional title shown above the table.","type":"string"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"fullWidth":{"type":"boolean"},"fixedHeight":{"type":"boolean"},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID — from ListMetrics / SearchMetrics."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"props":{"description":"Optional per-metric column config (time comparisons).","type":"object","properties":{"compares":{"description":"Per-metric time comparisons shown as extra columns (e.g. lag-1y, year-over-year).","type":"object","propertyNames":{"type":"string","enum":["min","max","avg","avg-7d","avg-28d","lag-1y","year-over-year","lag-1y-same-weekday","year-over-year-same-weekday","last-period","x-over-x"]},"additionalProperties":{"type":"object","properties":{"displayVariants":{"default":["compare-values"],"type":"array","items":{"type":"string","enum":["compare-values","absolute-change-from-compare-values-to-actuals","relative-change-from-compare-values-to-actuals"]}}},"required":["displayVariants"],"additionalProperties":false}}},"additionalProperties":false}},"required":["metricId"],"additionalProperties":false},"description":"One or more metrics to show as columns."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"},"layout":{"default":{"rows":[{"type":"metrics"}],"columns":[]},"description":"How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.","type":"object","properties":{"rows":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Row levels, outermost first."},"columns":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Column levels, outermost first."},"grouping":{"type":"object","properties":{"groupRows":{"type":"boolean","description":"Nest each outer row level as a collapsible group."},"showTotals":{"type":"boolean"},"expandedLevels":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["groupRows"],"additionalProperties":false},"measures":{"type":"object","properties":{"axis":{"type":"string","enum":["rows","columns"]}},"required":["axis"],"additionalProperties":false},"sorting":{"description":"Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).","type":"array","items":{"type":"object","properties":{"subject":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"labels"},"levelKey":{"type":"string"},"pinned":{"type":"array","items":{"type":"string"}}},"required":["kind","levelKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"values"},"axis":{"type":"string","enum":["rows","columns"]},"path":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string"},"valueKey":{"type":"string"}},"required":["kind","dimensionKey","valueKey"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"daily"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","format":"date","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])))$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"weekly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0\\d|[1-4]\\d|5[0-3])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"monthly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"quarterly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[147]|10)$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"yearly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false}]},{"type":"object","properties":{"kind":{"type":"string","const":"metrics"},"metricSliceKey":{"type":"string"}},"required":["kind","metricSliceKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"actual"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"total"}},"required":["kind"],"additionalProperties":false}]}}},"required":["kind","path"],"additionalProperties":false}]},"direction":{"type":"string","enum":["asc","desc"]}},"required":["subject","direction"],"additionalProperties":false}},"limits":{"description":"Top N per dimension identifier — keeps that many values of the level, in sort order.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["rows","columns"],"additionalProperties":false}},"required":["metricSliceIds","fromDate","toDate","layout"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends."},{"type":"object","properties":{"type":{"type":"string","const":"divider"}},"required":["type"],"additionalProperties":false,"description":"A horizontal divider that separates sections of the report. Carries no content — use between groups of blocks to break up a long report."},{"type":"object","properties":{"type":{"type":"string","const":"layout"},"children":{"minItems":2,"maxItems":4,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"properties":{"type":"object","properties":{"body":{"type":"string","description":"Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage."}},"required":["body"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"chart"},"properties":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID to visualize."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"timeGrainMode":{"default":"auto","description":"Either an explicit grain, or 'auto' to let the system choose.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"dimensionSettings":{"type":"object","properties":{"breakdown":{"description":"Dimension ID used for breakdown. Required for rank charts.","type":"string"},"filters":{"default":{},"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["filters"],"additionalProperties":false,"description":"Breakdown and filter configuration."},"targetName":{"description":"When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.","type":"string"},"metrics":{"description":"Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.","type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for the comparison series."},"sliceId":{"default":null,"description":"Optional slice/segment ID for the comparison series.","type":["string","null"]},"applyFilters":{"default":true,"description":"Whether to apply the chart's dimension filters to this series.","type":"boolean"},"yAxis":{"default":"right","description":"Which Y-axis this comparison series should use.","type":"string","enum":["left","right"]},"vizType":{"default":"line","description":"How to render the comparison series.","type":"string","enum":["line","bar"]}},"required":["metricId","sliceId","applyFilters","yAxis","vizType"],"additionalProperties":false,"description":"Compare the primary metric to another, different metric (e.g. revenue vs costs, metric A vs metric B)."}},"compares":{"description":"Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.","type":"array","items":{"type":"string","enum":["min","max","avg","lag-1y","last-period","x-over-x","year-over-year","avg-7d","avg-28d","lag-1y-same-weekday","year-over-year-same-weekday"],"description":"Period-over-period comparisons and same-metric derivations, shown only on a line or bar chart. Use ONLY a comparison the metric reports in its `compares` hint (from SearchMetrics/GetMetricDetails) — e.g. ratio metrics exclude year-over-year/x-over-x, so use lag-1y there — and respect that hint's daily-grain constraints. lag-1y and year-over-year overlay the same period from last year; last-period overlays the absolute values of the previous period of equal length as a comparison series (use this when user asks 'last week vs previous week', 'last 2 years vs previous 2 years', etc.); x-over-x shows the percentage change vs the previous period as a separate line — these are mutually exclusive alternatives, do NOT add both, pick only the one the user is asking for; min/max/avg aggregate over the visible range; avg-7d/avg-28d are moving averages; lag-1y-same-weekday and year-over-year-same-weekday align by weekday for year comparisons."}},"cumulative":{"default":false,"description":"Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.","type":"boolean"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional chart title to display above the visualization.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown items.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown items to show (e.g. top 3). Rank charts allow up to 1000; other chart types cap at 50.","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' row.","type":"boolean"},"show100PercentBars":{"description":"Show bars as percentages (only relevant for some charts).","type":"boolean"}},"additionalProperties":false},"showValues":{"default":"none","type":"string","enum":["none","main-metric","all"],"description":"Value labels visibility. Displayed above the data points or bars."},"pivotTable":{"type":"object","properties":{"rows":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"cols":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"totalsStyle":{"default":"none","description":"Whether to show row/column totals.","type":"string","enum":["none","rows-and-columns","columns","rows"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false}},"required":["tableStyle","totalsStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Pivot table configuration (rows/cols and rendering options)."},"cohortsTable":{"type":"object","properties":{"cohortId":{"description":"Cohort definition identifier.","type":"string"},"cohortTimeGrain":{"default":"auto","description":"Time grain used to bucket cohorts.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"deltaTimeGrain":{"default":"auto","description":"Time grain used for the delta/age axis.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false},"deltaTimeThresholds":{"description":"Optional [min, max] thresholds for the delta-time axis.","type":"array","prefixItems":[{"type":["number","null"]},{"type":["number","null"]}],"items":false,"minItems":2,"maxItems":2}},"required":["cohortTimeGrain","deltaTimeGrain","tableStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Cohorts table configuration."},"chartType":{"type":"string","enum":["line","bar","rank","pivot-table","cohorts-table"],"description":"Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["metricId","timeGrainMode","cumulative","showValues","chartType","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A chart visualizing a metric."},{"type":"object","properties":{"type":{"type":"string","const":"big-number"},"properties":{"type":"object","properties":{"variant":{"default":"metrics","type":"string","enum":["metrics","breakdown"],"description":"Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric."},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for this tile."},"sliceId":{"default":null,"description":"Optional slice/segment ID, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"description":"A metric (optionally narrowed to a slice) shown as one tile."},"description":"Metrics to show, one tile each. The breakdown variant uses exactly one entry."},"breakdownDimensionId":{"description":"Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.","type":"string"},"filters":{"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}},"compare":{"description":"Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.","type":"string","enum":["lag-1y","last-period"]},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional title displayed above the tiles.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown tiles.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown tiles to show (e.g. top 3).","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' tile.","type":"boolean"},"show100PercentBars":{"description":"Not rendered by big numbers; carried for type parity.","type":"boolean"}},"additionalProperties":false},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["variant","metricSliceIds","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail."},{"type":"object","properties":{"type":{"type":"string","const":"table"},"properties":{"type":"object","properties":{"title":{"description":"Optional title shown above the table.","type":"string"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"fullWidth":{"type":"boolean"},"fixedHeight":{"type":"boolean"},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID — from ListMetrics / SearchMetrics."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"props":{"description":"Optional per-metric column config (time comparisons).","type":"object","properties":{"compares":{"description":"Per-metric time comparisons shown as extra columns (e.g. lag-1y, year-over-year).","type":"object","propertyNames":{"type":"string","enum":["min","max","avg","avg-7d","avg-28d","lag-1y","year-over-year","lag-1y-same-weekday","year-over-year-same-weekday","last-period","x-over-x"]},"additionalProperties":{"type":"object","properties":{"displayVariants":{"default":["compare-values"],"type":"array","items":{"type":"string","enum":["compare-values","absolute-change-from-compare-values-to-actuals","relative-change-from-compare-values-to-actuals"]}}},"required":["displayVariants"],"additionalProperties":false}}},"additionalProperties":false}},"required":["metricId"],"additionalProperties":false},"description":"One or more metrics to show as columns."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"},"layout":{"default":{"rows":[{"type":"metrics"}],"columns":[]},"description":"How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.","type":"object","properties":{"rows":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Row levels, outermost first."},"columns":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Column levels, outermost first."},"grouping":{"type":"object","properties":{"groupRows":{"type":"boolean","description":"Nest each outer row level as a collapsible group."},"showTotals":{"type":"boolean"},"expandedLevels":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["groupRows"],"additionalProperties":false},"measures":{"type":"object","properties":{"axis":{"type":"string","enum":["rows","columns"]}},"required":["axis"],"additionalProperties":false},"sorting":{"description":"Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).","type":"array","items":{"type":"object","properties":{"subject":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"labels"},"levelKey":{"type":"string"},"pinned":{"type":"array","items":{"type":"string"}}},"required":["kind","levelKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"values"},"axis":{"type":"string","enum":["rows","columns"]},"path":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string"},"valueKey":{"type":"string"}},"required":["kind","dimensionKey","valueKey"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"daily"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","format":"date","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])))$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"weekly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0\\d|[1-4]\\d|5[0-3])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"monthly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"quarterly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[147]|10)$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"yearly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false}]},{"type":"object","properties":{"kind":{"type":"string","const":"metrics"},"metricSliceKey":{"type":"string"}},"required":["kind","metricSliceKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"actual"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"total"}},"required":["kind"],"additionalProperties":false}]}}},"required":["kind","path"],"additionalProperties":false}]},"direction":{"type":"string","enum":["asc","desc"]}},"required":["subject","direction"],"additionalProperties":false}},"limits":{"description":"Top N per dimension identifier — keeps that many values of the level, in sort order.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["rows","columns"],"additionalProperties":false}},"required":["metricSliceIds","fromDate","toDate","layout"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends."}]},"description":"The 2–4 content blocks rendered as equal-width columns, left to right."}},"required":["type","children"],"additionalProperties":false,"description":"A layout block that arranges 2–4 content blocks side by side as equal-width columns. Children must be content blocks (text, chart, big-number) — layout blocks cannot nest. Use for comparisons or related charts that read well next to each other."}]},"description":"Ordered list of blocks that make up the report body, in document order. Chart, table and big-number blocks reference metric `id`s from list metrics, search metrics, or get metric by `id`."}},"required":["title","blocks"],"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Report title. Concise and descriptive."},"blocks":{"maxItems":100,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"properties":{"type":"object","properties":{"body":{"type":"string","description":"Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage."}},"required":["body"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"chart"},"properties":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID to visualize."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"timeGrainMode":{"default":"auto","description":"Either an explicit grain, or 'auto' to let the system choose.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"dimensionSettings":{"type":"object","properties":{"breakdown":{"description":"Dimension ID used for breakdown. Required for rank charts.","type":"string"},"filters":{"default":{},"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["filters"],"additionalProperties":false,"description":"Breakdown and filter configuration."},"targetName":{"description":"When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.","type":"string"},"metrics":{"description":"Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.","type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for the comparison series."},"sliceId":{"default":null,"description":"Optional slice/segment ID for the comparison series.","type":["string","null"]},"applyFilters":{"default":true,"description":"Whether to apply the chart's dimension filters to this series.","type":"boolean"},"yAxis":{"default":"right","description":"Which Y-axis this comparison series should use.","type":"string","enum":["left","right"]},"vizType":{"default":"line","description":"How to render the comparison series.","type":"string","enum":["line","bar"]}},"required":["metricId","sliceId","applyFilters","yAxis","vizType"],"additionalProperties":false,"description":"Compare the primary metric to another, different metric (e.g. revenue vs costs, metric A vs metric B)."}},"compares":{"description":"Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.","type":"array","items":{"type":"string","enum":["min","max","avg","lag-1y","last-period","x-over-x","year-over-year","avg-7d","avg-28d","lag-1y-same-weekday","year-over-year-same-weekday"],"description":"Period-over-period comparisons and same-metric derivations, shown only on a line or bar chart. Use ONLY a comparison the metric reports in its `compares` hint (from SearchMetrics/GetMetricDetails) — e.g. ratio metrics exclude year-over-year/x-over-x, so use lag-1y there — and respect that hint's daily-grain constraints. lag-1y and year-over-year overlay the same period from last year; last-period overlays the absolute values of the previous period of equal length as a comparison series (use this when user asks 'last week vs previous week', 'last 2 years vs previous 2 years', etc.); x-over-x shows the percentage change vs the previous period as a separate line — these are mutually exclusive alternatives, do NOT add both, pick only the one the user is asking for; min/max/avg aggregate over the visible range; avg-7d/avg-28d are moving averages; lag-1y-same-weekday and year-over-year-same-weekday align by weekday for year comparisons."}},"cumulative":{"default":false,"description":"Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.","type":"boolean"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional chart title to display above the visualization.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown items.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown items to show (e.g. top 3). Rank charts allow up to 1000; other chart types cap at 50.","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' row.","type":"boolean"},"show100PercentBars":{"description":"Show bars as percentages (only relevant for some charts).","type":"boolean"}},"additionalProperties":false},"showValues":{"default":"none","type":"string","enum":["none","main-metric","all"],"description":"Value labels visibility. Displayed above the data points or bars."},"pivotTable":{"type":"object","properties":{"rows":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"cols":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"totalsStyle":{"default":"none","description":"Whether to show row/column totals.","type":"string","enum":["none","rows-and-columns","columns","rows"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false}},"required":["tableStyle","totalsStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Pivot table configuration (rows/cols and rendering options)."},"cohortsTable":{"type":"object","properties":{"cohortId":{"description":"Cohort definition identifier.","type":"string"},"cohortTimeGrain":{"default":"auto","description":"Time grain used to bucket cohorts.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"deltaTimeGrain":{"default":"auto","description":"Time grain used for the delta/age axis.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false},"deltaTimeThresholds":{"description":"Optional [min, max] thresholds for the delta-time axis.","type":"array","prefixItems":[{"type":["number","null"]},{"type":["number","null"]}],"items":false,"minItems":2,"maxItems":2}},"required":["cohortTimeGrain","deltaTimeGrain","tableStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Cohorts table configuration."},"chartType":{"type":"string","enum":["line","bar","rank","pivot-table","cohorts-table"],"description":"Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["metricId","timeGrainMode","cumulative","showValues","chartType","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A chart visualizing a metric."},{"type":"object","properties":{"type":{"type":"string","const":"big-number"},"properties":{"type":"object","properties":{"variant":{"default":"metrics","type":"string","enum":["metrics","breakdown"],"description":"Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric."},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for this tile."},"sliceId":{"default":null,"description":"Optional slice/segment ID, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"description":"A metric (optionally narrowed to a slice) shown as one tile."},"description":"Metrics to show, one tile each. The breakdown variant uses exactly one entry."},"breakdownDimensionId":{"description":"Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.","type":"string"},"filters":{"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}},"compare":{"description":"Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.","type":"string","enum":["lag-1y","last-period"]},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional title displayed above the tiles.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown tiles.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown tiles to show (e.g. top 3).","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' tile.","type":"boolean"},"show100PercentBars":{"description":"Not rendered by big numbers; carried for type parity.","type":"boolean"}},"additionalProperties":false},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["variant","metricSliceIds","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail."},{"type":"object","properties":{"type":{"type":"string","const":"table"},"properties":{"type":"object","properties":{"title":{"description":"Optional title shown above the table.","type":"string"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"fullWidth":{"type":"boolean"},"fixedHeight":{"type":"boolean"},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID — from ListMetrics / SearchMetrics."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"props":{"description":"Optional per-metric column config (time comparisons).","type":"object","properties":{"compares":{"description":"Per-metric time comparisons shown as extra columns (e.g. lag-1y, year-over-year).","type":"object","propertyNames":{"type":"string","enum":["min","max","avg","avg-7d","avg-28d","lag-1y","year-over-year","lag-1y-same-weekday","year-over-year-same-weekday","last-period","x-over-x"]},"additionalProperties":{"type":"object","properties":{"displayVariants":{"default":["compare-values"],"type":"array","items":{"type":"string","enum":["compare-values","absolute-change-from-compare-values-to-actuals","relative-change-from-compare-values-to-actuals"]}}},"required":["displayVariants"],"additionalProperties":false}}},"additionalProperties":false}},"required":["metricId"],"additionalProperties":false},"description":"One or more metrics to show as columns."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"},"layout":{"default":{"rows":[{"type":"metrics"}],"columns":[]},"description":"How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.","type":"object","properties":{"rows":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Row levels, outermost first."},"columns":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Column levels, outermost first."},"grouping":{"type":"object","properties":{"groupRows":{"type":"boolean","description":"Nest each outer row level as a collapsible group."},"showTotals":{"type":"boolean"},"expandedLevels":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["groupRows"],"additionalProperties":false},"measures":{"type":"object","properties":{"axis":{"type":"string","enum":["rows","columns"]}},"required":["axis"],"additionalProperties":false},"sorting":{"description":"Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).","type":"array","items":{"type":"object","properties":{"subject":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"labels"},"levelKey":{"type":"string"},"pinned":{"type":"array","items":{"type":"string"}}},"required":["kind","levelKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"values"},"axis":{"type":"string","enum":["rows","columns"]},"path":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string"},"valueKey":{"type":"string"}},"required":["kind","dimensionKey","valueKey"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"daily"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","format":"date","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])))$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"weekly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0\\d|[1-4]\\d|5[0-3])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"monthly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"quarterly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[147]|10)$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"yearly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false}]},{"type":"object","properties":{"kind":{"type":"string","const":"metrics"},"metricSliceKey":{"type":"string"}},"required":["kind","metricSliceKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"actual"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"total"}},"required":["kind"],"additionalProperties":false}]}}},"required":["kind","path"],"additionalProperties":false}]},"direction":{"type":"string","enum":["asc","desc"]}},"required":["subject","direction"],"additionalProperties":false}},"limits":{"description":"Top N per dimension identifier — keeps that many values of the level, in sort order.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["rows","columns"],"additionalProperties":false}},"required":["metricSliceIds","fromDate","toDate","layout"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends."},{"type":"object","properties":{"type":{"type":"string","const":"divider"}},"required":["type"],"additionalProperties":false,"description":"A horizontal divider that separates sections of the report. Carries no content — use between groups of blocks to break up a long report."},{"type":"object","properties":{"type":{"type":"string","const":"layout"},"children":{"minItems":2,"maxItems":4,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"properties":{"type":"object","properties":{"body":{"type":"string","description":"Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage."}},"required":["body"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"chart"},"properties":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID to visualize."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"timeGrainMode":{"default":"auto","description":"Either an explicit grain, or 'auto' to let the system choose.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"dimensionSettings":{"type":"object","properties":{"breakdown":{"description":"Dimension ID used for breakdown. Required for rank charts.","type":"string"},"filters":{"default":{},"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["filters"],"additionalProperties":false,"description":"Breakdown and filter configuration."},"targetName":{"description":"When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.","type":"string"},"metrics":{"description":"Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.","type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for the comparison series."},"sliceId":{"default":null,"description":"Optional slice/segment ID for the comparison series.","type":["string","null"]},"applyFilters":{"default":true,"description":"Whether to apply the chart's dimension filters to this series.","type":"boolean"},"yAxis":{"default":"right","description":"Which Y-axis this comparison series should use.","type":"string","enum":["left","right"]},"vizType":{"default":"line","description":"How to render the comparison series.","type":"string","enum":["line","bar"]}},"required":["metricId","sliceId","applyFilters","yAxis","vizType"],"additionalProperties":false,"description":"Compare the primary metric to another, different metric (e.g. revenue vs costs, metric A vs metric B)."}},"compares":{"description":"Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.","type":"array","items":{"type":"string","enum":["min","max","avg","lag-1y","last-period","x-over-x","year-over-year","avg-7d","avg-28d","lag-1y-same-weekday","year-over-year-same-weekday"],"description":"Period-over-period comparisons and same-metric derivations, shown only on a line or bar chart. Use ONLY a comparison the metric reports in its `compares` hint (from SearchMetrics/GetMetricDetails) — e.g. ratio metrics exclude year-over-year/x-over-x, so use lag-1y there — and respect that hint's daily-grain constraints. lag-1y and year-over-year overlay the same period from last year; last-period overlays the absolute values of the previous period of equal length as a comparison series (use this when user asks 'last week vs previous week', 'last 2 years vs previous 2 years', etc.); x-over-x shows the percentage change vs the previous period as a separate line — these are mutually exclusive alternatives, do NOT add both, pick only the one the user is asking for; min/max/avg aggregate over the visible range; avg-7d/avg-28d are moving averages; lag-1y-same-weekday and year-over-year-same-weekday align by weekday for year comparisons."}},"cumulative":{"default":false,"description":"Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.","type":"boolean"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional chart title to display above the visualization.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown items.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown items to show (e.g. top 3). Rank charts allow up to 1000; other chart types cap at 50.","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' row.","type":"boolean"},"show100PercentBars":{"description":"Show bars as percentages (only relevant for some charts).","type":"boolean"}},"additionalProperties":false},"showValues":{"default":"none","type":"string","enum":["none","main-metric","all"],"description":"Value labels visibility. Displayed above the data points or bars."},"pivotTable":{"type":"object","properties":{"rows":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"cols":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"totalsStyle":{"default":"none","description":"Whether to show row/column totals.","type":"string","enum":["none","rows-and-columns","columns","rows"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false}},"required":["tableStyle","totalsStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Pivot table configuration (rows/cols and rendering options)."},"cohortsTable":{"type":"object","properties":{"cohortId":{"description":"Cohort definition identifier.","type":"string"},"cohortTimeGrain":{"default":"auto","description":"Time grain used to bucket cohorts.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"deltaTimeGrain":{"default":"auto","description":"Time grain used for the delta/age axis.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false},"deltaTimeThresholds":{"description":"Optional [min, max] thresholds for the delta-time axis.","type":"array","prefixItems":[{"type":["number","null"]},{"type":["number","null"]}],"items":false,"minItems":2,"maxItems":2}},"required":["cohortTimeGrain","deltaTimeGrain","tableStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Cohorts table configuration."},"chartType":{"type":"string","enum":["line","bar","rank","pivot-table","cohorts-table"],"description":"Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["metricId","timeGrainMode","cumulative","showValues","chartType","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A chart visualizing a metric."},{"type":"object","properties":{"type":{"type":"string","const":"big-number"},"properties":{"type":"object","properties":{"variant":{"default":"metrics","type":"string","enum":["metrics","breakdown"],"description":"Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric."},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for this tile."},"sliceId":{"default":null,"description":"Optional slice/segment ID, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"description":"A metric (optionally narrowed to a slice) shown as one tile."},"description":"Metrics to show, one tile each. The breakdown variant uses exactly one entry."},"breakdownDimensionId":{"description":"Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.","type":"string"},"filters":{"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}},"compare":{"description":"Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.","type":"string","enum":["lag-1y","last-period"]},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional title displayed above the tiles.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown tiles.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown tiles to show (e.g. top 3).","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' tile.","type":"boolean"},"show100PercentBars":{"description":"Not rendered by big numbers; carried for type parity.","type":"boolean"}},"additionalProperties":false},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["variant","metricSliceIds","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail."},{"type":"object","properties":{"type":{"type":"string","const":"table"},"properties":{"type":"object","properties":{"title":{"description":"Optional title shown above the table.","type":"string"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"fullWidth":{"type":"boolean"},"fixedHeight":{"type":"boolean"},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID — from ListMetrics / SearchMetrics."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"props":{"description":"Optional per-metric column config (time comparisons).","type":"object","properties":{"compares":{"description":"Per-metric time comparisons shown as extra columns (e.g. lag-1y, year-over-year).","type":"object","propertyNames":{"type":"string","enum":["min","max","avg","avg-7d","avg-28d","lag-1y","year-over-year","lag-1y-same-weekday","year-over-year-same-weekday","last-period","x-over-x"]},"additionalProperties":{"type":"object","properties":{"displayVariants":{"default":["compare-values"],"type":"array","items":{"type":"string","enum":["compare-values","absolute-change-from-compare-values-to-actuals","relative-change-from-compare-values-to-actuals"]}}},"required":["displayVariants"],"additionalProperties":false}}},"additionalProperties":false}},"required":["metricId"],"additionalProperties":false},"description":"One or more metrics to show as columns."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"},"layout":{"default":{"rows":[{"type":"metrics"}],"columns":[]},"description":"How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.","type":"object","properties":{"rows":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Row levels, outermost first."},"columns":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Column levels, outermost first."},"grouping":{"type":"object","properties":{"groupRows":{"type":"boolean","description":"Nest each outer row level as a collapsible group."},"showTotals":{"type":"boolean"},"expandedLevels":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["groupRows"],"additionalProperties":false},"measures":{"type":"object","properties":{"axis":{"type":"string","enum":["rows","columns"]}},"required":["axis"],"additionalProperties":false},"sorting":{"description":"Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).","type":"array","items":{"type":"object","properties":{"subject":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"labels"},"levelKey":{"type":"string"},"pinned":{"type":"array","items":{"type":"string"}}},"required":["kind","levelKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"values"},"axis":{"type":"string","enum":["rows","columns"]},"path":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string"},"valueKey":{"type":"string"}},"required":["kind","dimensionKey","valueKey"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"daily"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","format":"date","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])))$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"weekly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0\\d|[1-4]\\d|5[0-3])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"monthly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"quarterly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[147]|10)$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"yearly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false}]},{"type":"object","properties":{"kind":{"type":"string","const":"metrics"},"metricSliceKey":{"type":"string"}},"required":["kind","metricSliceKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"actual"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"total"}},"required":["kind"],"additionalProperties":false}]}}},"required":["kind","path"],"additionalProperties":false}]},"direction":{"type":"string","enum":["asc","desc"]}},"required":["subject","direction"],"additionalProperties":false}},"limits":{"description":"Top N per dimension identifier — keeps that many values of the level, in sort order.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["rows","columns"],"additionalProperties":false}},"required":["metricSliceIds","fromDate","toDate","layout"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends."}]},"description":"The 2–4 content blocks rendered as equal-width columns, left to right."}},"required":["type","children"],"additionalProperties":false,"description":"A layout block that arranges 2–4 content blocks side by side as equal-width columns. Children must be content blocks (text, chart, big-number) — layout blocks cannot nest. Use for comparisons or related charts that read well next to each other."}]},"description":"Ordered list of blocks that make up the report body, in document order. Chart, table and big-number blocks reference metric `id`s from list metrics, search metrics, or get metric by `id`."}},"required":["title","blocks"],"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Report title. Concise and descriptive."},"blocks":{"maxItems":100,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"properties":{"type":"object","properties":{"body":{"type":"string","description":"Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage."}},"required":["body"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"chart"},"properties":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID to visualize."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"timeGrainMode":{"default":"auto","description":"Either an explicit grain, or 'auto' to let the system choose.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"dimensionSettings":{"type":"object","properties":{"breakdown":{"description":"Dimension ID used for breakdown. Required for rank charts.","type":"string"},"filters":{"default":{},"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["filters"],"additionalProperties":false,"description":"Breakdown and filter configuration."},"targetName":{"description":"When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.","type":"string"},"metrics":{"description":"Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.","type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for the comparison series."},"sliceId":{"default":null,"description":"Optional slice/segment ID for the comparison series.","type":["string","null"]},"applyFilters":{"default":true,"description":"Whether to apply the chart's dimension filters to this series.","type":"boolean"},"yAxis":{"default":"right","description":"Which Y-axis this comparison series should use.","type":"string","enum":["left","right"]},"vizType":{"default":"line","description":"How to render the comparison series.","type":"string","enum":["line","bar"]}},"required":["metricId","sliceId","applyFilters","yAxis","vizType"],"additionalProperties":false,"description":"Compare the primary metric to another, different metric (e.g. revenue vs costs, metric A vs metric B)."}},"compares":{"description":"Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.","type":"array","items":{"type":"string","enum":["min","max","avg","lag-1y","last-period","x-over-x","year-over-year","avg-7d","avg-28d","lag-1y-same-weekday","year-over-year-same-weekday"],"description":"Period-over-period comparisons and same-metric derivations, shown only on a line or bar chart. Use ONLY a comparison the metric reports in its `compares` hint (from SearchMetrics/GetMetricDetails) — e.g. ratio metrics exclude year-over-year/x-over-x, so use lag-1y there — and respect that hint's daily-grain constraints. lag-1y and year-over-year overlay the same period from last year; last-period overlays the absolute values of the previous period of equal length as a comparison series (use this when user asks 'last week vs previous week', 'last 2 years vs previous 2 years', etc.); x-over-x shows the percentage change vs the previous period as a separate line — these are mutually exclusive alternatives, do NOT add both, pick only the one the user is asking for; min/max/avg aggregate over the visible range; avg-7d/avg-28d are moving averages; lag-1y-same-weekday and year-over-year-same-weekday align by weekday for year comparisons."}},"cumulative":{"default":false,"description":"Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.","type":"boolean"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional chart title to display above the visualization.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown items.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown items to show (e.g. top 3). Rank charts allow up to 1000; other chart types cap at 50.","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' row.","type":"boolean"},"show100PercentBars":{"description":"Show bars as percentages (only relevant for some charts).","type":"boolean"}},"additionalProperties":false},"showValues":{"default":"none","type":"string","enum":["none","main-metric","all"],"description":"Value labels visibility. Displayed above the data points or bars."},"pivotTable":{"type":"object","properties":{"rows":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"cols":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"totalsStyle":{"default":"none","description":"Whether to show row/column totals.","type":"string","enum":["none","rows-and-columns","columns","rows"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false}},"required":["tableStyle","totalsStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Pivot table configuration (rows/cols and rendering options)."},"cohortsTable":{"type":"object","properties":{"cohortId":{"description":"Cohort definition identifier.","type":"string"},"cohortTimeGrain":{"default":"auto","description":"Time grain used to bucket cohorts.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"deltaTimeGrain":{"default":"auto","description":"Time grain used for the delta/age axis.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false},"deltaTimeThresholds":{"description":"Optional [min, max] thresholds for the delta-time axis.","type":"array","prefixItems":[{"type":["number","null"]},{"type":["number","null"]}],"items":false,"minItems":2,"maxItems":2}},"required":["cohortTimeGrain","deltaTimeGrain","tableStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Cohorts table configuration."},"chartType":{"type":"string","enum":["line","bar","rank","pivot-table","cohorts-table"],"description":"Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["metricId","timeGrainMode","cumulative","showValues","chartType","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A chart visualizing a metric."},{"type":"object","properties":{"type":{"type":"string","const":"big-number"},"properties":{"type":"object","properties":{"variant":{"default":"metrics","type":"string","enum":["metrics","breakdown"],"description":"Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric."},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for this tile."},"sliceId":{"default":null,"description":"Optional slice/segment ID, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"description":"A metric (optionally narrowed to a slice) shown as one tile."},"description":"Metrics to show, one tile each. The breakdown variant uses exactly one entry."},"breakdownDimensionId":{"description":"Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.","type":"string"},"filters":{"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}},"compare":{"description":"Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.","type":"string","enum":["lag-1y","last-period"]},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional title displayed above the tiles.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown tiles.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown tiles to show (e.g. top 3).","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' tile.","type":"boolean"},"show100PercentBars":{"description":"Not rendered by big numbers; carried for type parity.","type":"boolean"}},"additionalProperties":false},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["variant","metricSliceIds","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail."},{"type":"object","properties":{"type":{"type":"string","const":"table"},"properties":{"type":"object","properties":{"title":{"description":"Optional title shown above the table.","type":"string"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"fullWidth":{"type":"boolean"},"fixedHeight":{"type":"boolean"},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID — from ListMetrics / SearchMetrics."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"props":{"description":"Optional per-metric column config (time comparisons).","type":"object","properties":{"compares":{"description":"Per-metric time comparisons shown as extra columns (e.g. lag-1y, year-over-year).","type":"object","propertyNames":{"type":"string","enum":["min","max","avg","avg-7d","avg-28d","lag-1y","year-over-year","lag-1y-same-weekday","year-over-year-same-weekday","last-period","x-over-x"]},"additionalProperties":{"type":"object","properties":{"displayVariants":{"default":["compare-values"],"type":"array","items":{"type":"string","enum":["compare-values","absolute-change-from-compare-values-to-actuals","relative-change-from-compare-values-to-actuals"]}}},"required":["displayVariants"],"additionalProperties":false}}},"additionalProperties":false}},"required":["metricId"],"additionalProperties":false},"description":"One or more metrics to show as columns."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"},"layout":{"default":{"rows":[{"type":"metrics"}],"columns":[]},"description":"How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.","type":"object","properties":{"rows":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Row levels, outermost first."},"columns":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Column levels, outermost first."},"grouping":{"type":"object","properties":{"groupRows":{"type":"boolean","description":"Nest each outer row level as a collapsible group."},"showTotals":{"type":"boolean"},"expandedLevels":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["groupRows"],"additionalProperties":false},"measures":{"type":"object","properties":{"axis":{"type":"string","enum":["rows","columns"]}},"required":["axis"],"additionalProperties":false},"sorting":{"description":"Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).","type":"array","items":{"type":"object","properties":{"subject":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"labels"},"levelKey":{"type":"string"},"pinned":{"type":"array","items":{"type":"string"}}},"required":["kind","levelKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"values"},"axis":{"type":"string","enum":["rows","columns"]},"path":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string"},"valueKey":{"type":"string"}},"required":["kind","dimensionKey","valueKey"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"daily"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","format":"date","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])))$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"weekly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0\\d|[1-4]\\d|5[0-3])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"monthly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"quarterly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[147]|10)$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"yearly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false}]},{"type":"object","properties":{"kind":{"type":"string","const":"metrics"},"metricSliceKey":{"type":"string"}},"required":["kind","metricSliceKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"actual"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"total"}},"required":["kind"],"additionalProperties":false}]}}},"required":["kind","path"],"additionalProperties":false}]},"direction":{"type":"string","enum":["asc","desc"]}},"required":["subject","direction"],"additionalProperties":false}},"limits":{"description":"Top N per dimension identifier — keeps that many values of the level, in sort order.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["rows","columns"],"additionalProperties":false}},"required":["metricSliceIds","fromDate","toDate","layout"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends."},{"type":"object","properties":{"type":{"type":"string","const":"divider"}},"required":["type"],"additionalProperties":false,"description":"A horizontal divider that separates sections of the report. Carries no content — use between groups of blocks to break up a long report."},{"type":"object","properties":{"type":{"type":"string","const":"layout"},"children":{"minItems":2,"maxItems":4,"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"text"},"properties":{"type":"object","properties":{"body":{"type":"string","description":"Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage."}},"required":["body"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"chart"},"properties":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID to visualize."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"timeGrainMode":{"default":"auto","description":"Either an explicit grain, or 'auto' to let the system choose.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"dimensionSettings":{"type":"object","properties":{"breakdown":{"description":"Dimension ID used for breakdown. Required for rank charts.","type":"string"},"filters":{"default":{},"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["filters"],"additionalProperties":false,"description":"Breakdown and filter configuration."},"targetName":{"description":"When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.","type":"string"},"metrics":{"description":"Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.","type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for the comparison series."},"sliceId":{"default":null,"description":"Optional slice/segment ID for the comparison series.","type":["string","null"]},"applyFilters":{"default":true,"description":"Whether to apply the chart's dimension filters to this series.","type":"boolean"},"yAxis":{"default":"right","description":"Which Y-axis this comparison series should use.","type":"string","enum":["left","right"]},"vizType":{"default":"line","description":"How to render the comparison series.","type":"string","enum":["line","bar"]}},"required":["metricId","sliceId","applyFilters","yAxis","vizType"],"additionalProperties":false,"description":"Compare the primary metric to another, different metric (e.g. revenue vs costs, metric A vs metric B)."}},"compares":{"description":"Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.","type":"array","items":{"type":"string","enum":["min","max","avg","lag-1y","last-period","x-over-x","year-over-year","avg-7d","avg-28d","lag-1y-same-weekday","year-over-year-same-weekday"],"description":"Period-over-period comparisons and same-metric derivations, shown only on a line or bar chart. Use ONLY a comparison the metric reports in its `compares` hint (from SearchMetrics/GetMetricDetails) — e.g. ratio metrics exclude year-over-year/x-over-x, so use lag-1y there — and respect that hint's daily-grain constraints. lag-1y and year-over-year overlay the same period from last year; last-period overlays the absolute values of the previous period of equal length as a comparison series (use this when user asks 'last week vs previous week', 'last 2 years vs previous 2 years', etc.); x-over-x shows the percentage change vs the previous period as a separate line — these are mutually exclusive alternatives, do NOT add both, pick only the one the user is asking for; min/max/avg aggregate over the visible range; avg-7d/avg-28d are moving averages; lag-1y-same-weekday and year-over-year-same-weekday align by weekday for year comparisons."}},"cumulative":{"default":false,"description":"Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.","type":"boolean"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional chart title to display above the visualization.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown items.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown items to show (e.g. top 3). Rank charts allow up to 1000; other chart types cap at 50.","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' row.","type":"boolean"},"show100PercentBars":{"description":"Show bars as percentages (only relevant for some charts).","type":"boolean"}},"additionalProperties":false},"showValues":{"default":"none","type":"string","enum":["none","main-metric","all"],"description":"Value labels visibility. Displayed above the data points or bars."},"pivotTable":{"type":"object","properties":{"rows":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"cols":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"value":{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Time grain to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"value":{"type":"string","description":"Dimension ID to use on this axis."}},"required":["type","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"total"}},"required":["type"],"additionalProperties":false}],"description":"Axis selection for pivot tables (rows/cols)."},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"totalsStyle":{"default":"none","description":"Whether to show row/column totals.","type":"string","enum":["none","rows-and-columns","columns","rows"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false}},"required":["tableStyle","totalsStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Pivot table configuration (rows/cols and rendering options)."},"cohortsTable":{"type":"object","properties":{"cohortId":{"description":"Cohort definition identifier.","type":"string"},"cohortTimeGrain":{"default":"auto","description":"Time grain used to bucket cohorts.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"deltaTimeGrain":{"default":"auto","description":"Time grain used for the delta/age axis.","anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"],"description":"Granularity used to aggregate a time series."},{"type":"string","const":"auto"}]},"tableStyle":{"default":"values-and-colors","description":"How to render each cell (values, colors, or both).","type":"string","enum":["values-and-colors","colors","values"]},"colorScheme":{"default":"monochrome-blue","description":"Heatmap color palette.","anyOf":[{"type":"string","enum":["monochrome-blue","monochrome-pink","monochrome-green","monochrome-yellow","monochrome-purple","monochrome-red","monochrome-gray","traffic-lights","viridis","magma","red-blue","cyclic-blue"]},{"type":"string","pattern":"^monochrome--?\\d+$"}]},"colorSchemeFlipped":{"default":false,"description":"Invert the heatmap mapping (high values become low colors).","type":"boolean"},"colorThresholds":{"description":"Optional thresholds to control heatmap scaling.","type":"object","properties":{"min":{"description":"Lower bound for color scaling.","type":"number"},"mid":{"description":"Midpoint for diverging scales.","type":"number"},"max":{"description":"Upper bound for color scaling.","type":"number"}},"additionalProperties":false},"deltaTimeThresholds":{"description":"Optional [min, max] thresholds for the delta-time axis.","type":"array","prefixItems":[{"type":["number","null"]},{"type":["number","null"]}],"items":false,"minItems":2,"maxItems":2}},"required":["cohortTimeGrain","deltaTimeGrain","tableStyle","colorScheme","colorSchemeFlipped"],"additionalProperties":false,"description":"Cohorts table configuration."},"chartType":{"type":"string","enum":["line","bar","rank","pivot-table","cohorts-table"],"description":"Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["metricId","timeGrainMode","cumulative","showValues","chartType","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A chart visualizing a metric."},{"type":"object","properties":{"type":{"type":"string","const":"big-number"},"properties":{"type":"object","properties":{"variant":{"default":"metrics","type":"string","enum":["metrics","breakdown"],"description":"Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric."},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID for this tile."},"sliceId":{"default":null,"description":"Optional slice/segment ID, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"description":"A metric (optionally narrowed to a slice) shown as one tile."},"description":"Metrics to show, one tile each. The breakdown variant uses exactly one entry."},"breakdownDimensionId":{"description":"Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.","type":"string"},"filters":{"description":"Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}}},"compare":{"description":"Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.","type":"string","enum":["lag-1y","last-period"]},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"title":{"description":"Optional title displayed above the tiles.","type":"string"},"breakdownSettings":{"type":"object","properties":{"sortBy":{"description":"How to sort breakdown tiles.","type":"string","enum":["value","name"]},"sortDirection":{"description":"Sort direction.","type":"string","enum":["asc","desc"]},"maxItems":{"description":"Maximum number of breakdown tiles to show (e.g. top 3).","type":"integer","exclusiveMinimum":0,"maximum":1000},"hideOther":{"description":"Whether to hide the aggregated 'Other' tile.","type":"boolean"},"show100PercentBars":{"description":"Not rendered by big numbers; carried for type parity.","type":"boolean"}},"additionalProperties":false},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"}},"required":["variant","metricSliceIds","fromDate","toDate"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail."},{"type":"object","properties":{"type":{"type":"string","const":"table"},"properties":{"type":"object","properties":{"title":{"description":"Optional title shown above the table.","type":"string"},"bypassReportFilters":{"description":"Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.","type":"boolean"},"fullWidth":{"type":"boolean"},"fixedHeight":{"type":"boolean"},"metricSliceIds":{"minItems":1,"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"Metric ID — from ListMetrics / SearchMetrics."},"sliceId":{"description":"Optional slice/segment ID.","type":"string"},"props":{"description":"Optional per-metric column config (time comparisons).","type":"object","properties":{"compares":{"description":"Per-metric time comparisons shown as extra columns (e.g. lag-1y, year-over-year).","type":"object","propertyNames":{"type":"string","enum":["min","max","avg","avg-7d","avg-28d","lag-1y","year-over-year","lag-1y-same-weekday","year-over-year-same-weekday","last-period","x-over-x"]},"additionalProperties":{"type":"object","properties":{"displayVariants":{"default":["compare-values"],"type":"array","items":{"type":"string","enum":["compare-values","absolute-change-from-compare-values-to-actuals","relative-change-from-compare-values-to-actuals"]}}},"required":["displayVariants"],"additionalProperties":false}}},"additionalProperties":false}},"required":["metricId"],"additionalProperties":false},"description":"One or more metrics to show as columns."},"fromDate":{"type":"string","format":"date","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])))$"},"toDate":{"type":"string","format":"date","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])))$"},"layout":{"default":{"rows":[{"type":"metrics"}],"columns":[]},"description":"How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.","type":"object","properties":{"rows":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Row levels, outermost first."},"columns":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"metrics"}},"required":["type"],"additionalProperties":false,"description":"Where the metrics sit. Exactly one per table."},{"type":"object","properties":{"type":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string","minLength":1,"description":"The dimension's identifier (a readable column like 'country'), as returned by the dimension lookup tool — not the opaque dimension id."}},"required":["type","dimensionKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"temporal"},"grainMode":{"anyOf":[{"type":"string","enum":["daily","weekly","monthly","quarterly","yearly"]},{"type":"string","const":"auto"}],"description":"An explicit time grain, or 'auto' to let the system choose."}},"required":["type","grainMode"],"additionalProperties":false}]},"description":"Column levels, outermost first."},"grouping":{"type":"object","properties":{"groupRows":{"type":"boolean","description":"Nest each outer row level as a collapsible group."},"showTotals":{"type":"boolean"},"expandedLevels":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["groupRows"],"additionalProperties":false},"measures":{"type":"object","properties":{"axis":{"type":"string","enum":["rows","columns"]}},"required":["axis"],"additionalProperties":false},"sorting":{"description":"Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).","type":"array","items":{"type":"object","properties":{"subject":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"labels"},"levelKey":{"type":"string"},"pinned":{"type":"array","items":{"type":"string"}}},"required":["kind","levelKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"values"},"axis":{"type":"string","enum":["rows","columns"]},"path":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"categorical"},"dimensionKey":{"type":"string"},"valueKey":{"type":"string"}},"required":["kind","dimensionKey","valueKey"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"daily"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","format":"date","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])))$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"weekly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0\\d|[1-4]\\d|5[0-3])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"monthly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"quarterly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}-(0[147]|10)$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"temporal"},"grain":{"type":"string","const":"yearly"},"at":{"oneOf":[{"type":"object","properties":{"form":{"type":"string","const":"absolute"},"instant":{"type":"string","pattern":"^\\d{4}$"}},"required":["form","instant"],"additionalProperties":false},{"type":"object","properties":{"form":{"type":"string","const":"relative"},"ordinal":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["form","ordinal"],"additionalProperties":false}]}},"required":["kind","grain","at"],"additionalProperties":false}]},{"type":"object","properties":{"kind":{"type":"string","const":"metrics"},"metricSliceKey":{"type":"string"}},"required":["kind","metricSliceKey"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"actual"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","const":"total"}},"required":["kind"],"additionalProperties":false}]}}},"required":["kind","path"],"additionalProperties":false}]},"direction":{"type":"string","enum":["asc","desc"]}},"required":["subject","direction"],"additionalProperties":false}},"limits":{"description":"Top N per dimension identifier — keeps that many values of the level, in sort order.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}},"required":["rows","columns"],"additionalProperties":false}},"required":["metricSliceIds","fromDate","toDate","layout"],"additionalProperties":false}},"required":["type","properties"],"additionalProperties":false,"description":"A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends."}]},"description":"The 2–4 content blocks rendered as equal-width columns, left to right."}},"required":["type","children"],"additionalProperties":false,"description":"A layout block that arranges 2–4 content blocks side by side as equal-width columns. Children must be content blocks (text, chart, big-number) — layout blocks cannot nest. Use for comparisons or related charts that read well next to each other."}]},"description":"Ordered list of blocks that make up the report body, in document order. Chart, table and big-number blocks reference metric `id`s from list metrics, search metrics, or get metric by `id`."}},"required":["title","blocks"],"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"title":{"type":"string"},"link":{"type":"string","description":"Link to the report in the Steep app."}},"required":["id","title","link"],"additionalProperties":false,"title":"CreatedReport"}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1Reports"},"get":{"description":"List reports in the workspace (metadata only, not content). Filter by creator, sharing, team, or metric; page with `limit` and `skip`. For keyword search use search reports; for full content use get report by `id`.","tags":["reports"],"x-steep":{"requiredScopes":["reports:read"],"exposeUnderMCP":true},"parameters":[{"name":"limit","in":"query","required":false,"schema":{"default":50,"description":"Maximum number of reports to return.","type":"integer","minimum":1,"maximum":100}},{"name":"skip","in":"query","required":false,"schema":{"default":0,"description":"Number of reports to skip, for paging.","type":"integer","minimum":0,"maximum":9007199254740991}},{"name":"createdBy","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Only reports created by this user. Pass a workspace member's user `id` from list workspace members, or the literal `me` for the calling user (`me` requires a user token)."}},{"name":"sharedWith","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Only reports shared directly with this user, excluding reports they created. Pass a workspace member's user `id` from list workspace members, or the literal `me` for the calling user (`me` requires a user token). Cannot be combined with `teamId`."}},{"name":"teamId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Only reports shared with this team. Cannot be combined with `sharedWith`."}},{"name":"metricId","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Only reports whose blocks reference this metric (chart, table, big-number or map blocks). Pass a metric `id` from list metrics, search metrics, or get metric by `id`. Use to find which reports reference a given metric."}},{"name":"sort","in":"query","required":false,"schema":{"default":"updatedAt","description":"Field to sort by.","type":"string","enum":["createdAt","updatedAt"]}},{"name":"order","in":"query","required":false,"schema":{"default":"desc","description":"Sort direction.","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"skip":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"title":{"type":"string"},"createdAt":{"type":"string","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))$","description":"When the report was created."},"updatedAt":{"type":"string","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))$","description":"When the report was last updated."},"author":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The id of the user who created the report."},"name":{"description":"The display name of the user who created the report. Null if the user has no name set.","type":["string","null"]}},"required":["id","name"],"additionalProperties":false,"title":"ReportAuthor"},{"type":"null"}],"description":"The user who created the report. Null if the creator is unknown."},"link":{"type":"string","description":"Link to the report in the Steep app."}},"required":["id","title","createdAt","updatedAt","author","link"],"additionalProperties":false,"title":"ReportListItem"}}},"required":["total","limit","skip","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1Reports"}},"/v1/reports/search":{"get":{"description":"Search existing reports by title and content: report titles and block headings/titles (text blocks, and chart, table, big-number, and map block titles); body text is not searched. Multiple words are matched independently. Returns the most recently updated matching reports, each flagged by whether it matched on the title or on content. Prefer this first for broad or open-ended questions about how an area, topic, or the business is doing, such as 'how is retention trending?', 'what's the latest on churn?', or 'give me a read on sales this quarter'. Teams curate reports as the canonical, vetted answer to exactly these questions, so look for an existing report before assembling answers from individual metrics. Skip it for precise, computational asks that name a specific metric, value, breakdown, or chart, such as 'what was MRR last month?' or 'chart gross margin by month'; use the metric tools directly for those.","tags":["reports"],"x-steep":{"requiredScopes":["reports:read"],"exposeUnderMCP":true},"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Search query of up to 5 words. Each word is matched independently: a report matches if any word appears in its title or content."}},{"name":"limit","in":"query","required":false,"schema":{"default":10,"description":"Maximum number of hits to return.","type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"title":{"type":"string"},"updatedAt":{"type":"string","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))$"},"link":{"type":"string","description":"Link to the report in the Steep app."},"matchedOn":{"type":"string","enum":["title","content"],"description":"Why the report matched the keyword: `title` if it matched the report title, `content` if it matched block content (a text-block heading or a chart/table/big-number/map block title)."}},"required":["id","title","updatedAt","link","matchedOn"],"additionalProperties":false,"title":"Report"}}},"required":["data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1ReportsSearch"}},"/v1/reports/{id}":{"get":{"description":"Read a report's full contents by `id`: title, each text block's heading and body, and the titles of chart/table/big-number/map blocks, in document order. Does not run metric queries.","tags":["reports"],"x-steep":{"requiredScopes":["reports:read"],"exposeUnderMCP":true},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1,"description":"The `id` of the report."}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"createdAt":{"type":"string","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))$","description":"When the report was created."},"updatedAt":{"type":"string","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))$","description":"When the report was last updated."},"author":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"The id of the user who created the report."},"name":{"description":"The display name of the user who created the report. Null if the user has no name set.","type":["string","null"]}},"required":["id","name"],"additionalProperties":false,"title":"ReportAuthor"},{"type":"null"}],"description":"The user who created the report. Null if the creator is unknown."},"link":{"type":"string","description":"Link to the report in the Steep app."},"blocks":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","const":"text"},"heading":{"type":"string"},"headingSize":{"type":"string","enum":["large","small"]},"body":{"type":"string"}},"required":["id","type","heading","headingSize","body"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["chart","table","big-number","map"]},"title":{"type":["string","null"]},"metrics":{"type":"array","items":{"type":"object","properties":{"metricId":{"type":"string","description":"The metric this series visualizes. Use query metric to fetch values, or get metric by `id` for its definition."},"sliceId":{"description":"The slice/segment the metric is narrowed to, or null for the whole metric.","type":["string","null"]}},"required":["metricId","sliceId"],"additionalProperties":false,"title":"ReportMetricRef"},"description":"The metrics visualized in this block, in display order. Empty for map blocks."},"timeFilter":{"description":"Relative time-window token (e.g. \"1w\", \"1y\"), or \"custom\" for an explicit fromDate/toDate range. Null if the block sets no time window.","type":["string","null"]},"fromDate":{"description":"Start of the block's time window as an ISO 8601 string, when set.","type":["string","null"]},"toDate":{"description":"End of the block's time window as an ISO 8601 string, when set.","type":["string","null"]}},"required":["id","type","title","metrics","timeFilter","fromDate","toDate"],"additionalProperties":false}]}}},"required":["id","title","createdAt","updatedAt","author","link","blocks"],"additionalProperties":false,"title":"ReportContent"}},"required":["data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1ReportsById"}},"/v1/workspace/members":{"get":{"description":"List members for your workspace.","tags":["workspace"],"x-steep":{"requiredScopes":["workspace-members:read"],"exposeUnderMCP":true},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"skip":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"User `id` for this member. This matches `id`s returned in `metric.owners`."},"workspaceMemberId":{"type":"string","description":"Workspace member record `id`."},"name":{"type":"string"},"email":{"type":"string"},"image":{"type":["string","null"]},"role":{"type":"string"},"loginMethod":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","workspaceMemberId","name","email","image","role","loginMethod","createdAt","updatedAt"],"additionalProperties":false,"title":"Member"}}},"required":["total","limit","skip","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1WorkspaceMembers"}},"/v1/workspace/teams":{"get":{"description":"List teams for your workspace.","tags":["workspace"],"x-steep":{"requiredScopes":["teams:read"],"exposeUnderMCP":true},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"skip":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"name":{"type":"string"},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"type":"boolean","description":"When true, only members of the team can see it."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"directoryLinked":{"type":"boolean","description":"Whether membership is managed in the directory. Only for workspaces on the Enterprise plan with Directory sync enabled."},"directoryGroupId":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]},"directoryGroupName":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]},"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"User `id` for this member. This matches `id`s returned in `metric.owners`."},"workspaceMemberId":{"type":"string","description":"Workspace member record `id`."},"name":{"type":"string"},"email":{"type":"string"},"image":{"type":["string","null"]},"loginMethod":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","workspaceMemberId","name","email","image","loginMethod","createdAt","updatedAt"],"additionalProperties":false}}},"required":["id","name","description","color","isPrivate","createdAt","updatedAt","directoryLinked","members"],"additionalProperties":false,"title":"TeamListItem"}}},"required":["total","limit","skip","data"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1WorkspaceTeams"},"post":{"description":"Create a team in your workspace.","tags":["workspace"],"x-steep":{"requiredScopes":["teams:write"],"exposeUnderMCP":false},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"default":false,"description":"When true, only members of the team can see it.","type":"boolean"},"directoryGroupId":{"description":"Links this team to a directory group. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":"string","pattern":"\\S"}},"required":["name","isPrivate"],"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"default":false,"description":"When true, only members of the team can see it.","type":"boolean"},"directoryGroupId":{"description":"Links this team to a directory group. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":"string","pattern":"\\S"}},"required":["name","isPrivate"],"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"default":false,"description":"When true, only members of the team can see it.","type":"boolean"},"directoryGroupId":{"description":"Links this team to a directory group. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":"string","pattern":"\\S"}},"required":["name","isPrivate"],"additionalProperties":false}}}},"responses":{"201":{"description":"Response for status 201","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"name":{"type":"string"},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"type":"boolean","description":"When true, only members of the team can see it."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"directoryLinked":{"type":"boolean","description":"Whether membership is managed in the directory. Only for workspaces on the Enterprise plan with Directory sync enabled."},"directoryGroupId":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]},"directoryGroupName":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]}},"required":["id","name","description","color","isPrivate","createdAt","updatedAt","directoryLinked"],"additionalProperties":false,"title":"Team"}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1WorkspaceTeams"}},"/v1/workspace/teams/{id}":{"get":{"description":"Get a team by `id`.","tags":["workspace"],"x-steep":{"requiredScopes":["teams:read"],"exposeUnderMCP":true},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"Unique resource ID (opaque)."}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"name":{"type":"string"},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"type":"boolean","description":"When true, only members of the team can see it."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"directoryLinked":{"type":"boolean","description":"Whether membership is managed in the directory. Only for workspaces on the Enterprise plan with Directory sync enabled."},"directoryGroupId":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]},"directoryGroupName":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]},"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"User `id` for this member. This matches `id`s returned in `metric.owners`."},"workspaceMemberId":{"type":"string","description":"Workspace member record `id`."},"name":{"type":"string"},"email":{"type":"string"},"image":{"type":["string","null"]},"loginMethod":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","workspaceMemberId","name","email","image","loginMethod","createdAt","updatedAt"],"additionalProperties":false}}},"required":["id","name","description","color","isPrivate","createdAt","updatedAt","directoryLinked","members"],"additionalProperties":false,"title":"TeamListItem"}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1WorkspaceTeamsById"},"patch":{"description":"Update a team by `id`. Omitted fields stay as they are.","tags":["workspace"],"x-steep":{"requiredScopes":["teams:write"],"exposeUnderMCP":false},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"Unique resource ID (opaque)."}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"description":"When true, only members of the team can see it.","type":"boolean"},"directoryGroupId":{"description":"Links this team to a directory group. Can only be set on a currently unlinked team. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":"string","pattern":"\\S"}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"description":"When true, only members of the team can see it.","type":"boolean"},"directoryGroupId":{"description":"Links this team to a directory group. Can only be set on a currently unlinked team. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":"string","pattern":"\\S"}},"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"description":"When true, only members of the team can see it.","type":"boolean"},"directoryGroupId":{"description":"Links this team to a directory group. Can only be set on a currently unlinked team. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":"string","pattern":"\\S"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"name":{"type":"string"},"description":{"type":["string","null"]},"color":{"anyOf":[{"type":"string","enum":["none","gray","gray-weak","blue","turquoise","green","yellow","orange","red","pink","purple"]},{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},{"type":"null"}]},"isPrivate":{"type":"boolean","description":"When true, only members of the team can see it."},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"directoryLinked":{"type":"boolean","description":"Whether membership is managed in the directory. Only for workspaces on the Enterprise plan with Directory sync enabled."},"directoryGroupId":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]},"directoryGroupName":{"description":"This field is only included in the response if the caller is a workspace admin or an API key. Only for workspaces on the Enterprise plan with Directory sync enabled.","type":["string","null"]}},"required":["id","name","description","color","isPrivate","createdAt","updatedAt","directoryLinked"],"additionalProperties":false,"title":"Team"}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"patchV1WorkspaceTeamsById"},"delete":{"description":"Delete a team by `id`.","tags":["workspace"],"x-steep":{"requiredScopes":["teams:write"],"exposeUnderMCP":false},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_-]+$","description":"Unique resource ID (opaque)."}}],"responses":{"204":{"description":"The team was deleted.","content":{"type":"null","description":"The team was deleted."}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"deleteV1WorkspaceTeamsById"}},"/v1/code/syncs":{"post":{"hide":false,"description":"Sync your semantic models (Steep YAML, dbt or Cube) into Steep. Enqueues the sync and returns immediately with a `queued` result; poll `get sync by id` until the `outcome` is terminal (`completed` or `failed`). With `dryRun`, previews the sync instead: returns what it would create, update and remove, without changing anything.","tags":["code"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"datasourceId":{"type":"string","description":"Unique resource ID (opaque). The datasource whose semantic models to sync."},"dryRun":{"description":"When `true`, previews the sync: returns what it would create, update and remove, without changing anything. Nothing is queued, so there is no sync to poll.","type":"boolean"},"files":{"description":"Only with `dryRun`. Steep YAML files to preview instead of the linked GitHub repository. Send the complete set: objects defined in code but missing from these files are reported as `removed`. Each `path` is relative to the repository root, uses forward slashes, ends in `.yml` or `.yaml`, and appears once. The request may be up to 10 MB.","type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"],"additionalProperties":false}}},"required":["datasourceId"],"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"datasourceId":{"type":"string","description":"Unique resource ID (opaque). The datasource whose semantic models to sync."},"dryRun":{"description":"When `true`, previews the sync: returns what it would create, update and remove, without changing anything. Nothing is queued, so there is no sync to poll.","type":"boolean"},"files":{"description":"Only with `dryRun`. Steep YAML files to preview instead of the linked GitHub repository. Send the complete set: objects defined in code but missing from these files are reported as `removed`. Each `path` is relative to the repository root, uses forward slashes, ends in `.yml` or `.yaml`, and appears once. The request may be up to 10 MB.","type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"],"additionalProperties":false}}},"required":["datasourceId"],"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"datasourceId":{"type":"string","description":"Unique resource ID (opaque). The datasource whose semantic models to sync."},"dryRun":{"description":"When `true`, previews the sync: returns what it would create, update and remove, without changing anything. Nothing is queued, so there is no sync to poll.","type":"boolean"},"files":{"description":"Only with `dryRun`. Steep YAML files to preview instead of the linked GitHub repository. Send the complete set: objects defined in code but missing from these files are reported as `removed`. Each `path` is relative to the repository root, uses forward slashes, ends in `.yml` or `.yaml`, and appears once. The request may be up to 10 MB.","type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"],"additionalProperties":false}}},"required":["datasourceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"datasourceId":{"type":"string","description":"Unique resource ID (opaque)."},"method":{"type":"string","description":"How the sync was triggered."},"outcome":{"type":"string","enum":["completed","failed"],"description":"`completed` when the sync would succeed, `failed` when it would fail, with the reason in `error`."},"created":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync would create. Null when the preview failed."},"updated":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync would update. Null when the preview failed."},"removed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync would remove. Null when the preview failed."},"unchanged":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync would leave unchanged. Null when the preview failed."},"error":{"description":"Why the sync would fail. Null unless the `outcome` is `failed`.","type":["string","null"]},"type":{"type":"string","const":"Steep as Code","description":"Source of the semantic models that were synced."},"errors":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Errors the sync reported. Null until terminal."},"warnings":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Warnings the sync reported. Null until terminal."},"dryRun":{"type":"boolean","const":true,"description":"Always `true`: this is a preview, and nothing was changed."},"accessPolicies":{"anyOf":[{"type":"object","properties":{"created":{"type":"array","items":{"type":"object","properties":{"module":{"type":"string","description":"`identifier` of the module the policy is on."},"policy":{"type":"string","description":"What the policy filters, as `table.column = user.<attribute>`."}},"required":["module","policy"],"additionalProperties":false},"description":"Access policies the sync would create."},"updated":{"type":"array","items":{"type":"object","properties":{"module":{"type":"string","description":"`identifier` of the module the policy is on."},"policy":{"type":"string","description":"What the policy filters, as `table.column = user.<attribute>`."}},"required":["module","policy"],"additionalProperties":false},"description":"Access policies the sync would update."},"removed":{"type":"array","items":{"type":"object","properties":{"module":{"type":"string","description":"`identifier` of the module the policy is on."},"policy":{"type":"string","description":"What the policy filters, as `table.column = user.<attribute>`."}},"required":["module","policy"],"additionalProperties":false},"description":"Access policies the sync would remove."},"unchanged":{"type":"array","items":{"type":"object","properties":{"module":{"type":"string","description":"`identifier` of the module the policy is on."},"policy":{"type":"string","description":"What the policy filters, as `table.column = user.<attribute>`."}},"required":["module","policy"],"additionalProperties":false},"description":"Access policies the sync would leave unchanged."}},"required":["created","updated","removed","unchanged"],"additionalProperties":false},{"type":"null"}],"description":"The row-level access policies in code, by what the sync would do to each. A changed attribute is one policy removed and another created. Null when the preview failed."}},"required":["datasourceId","method","outcome","created","updated","removed","unchanged","error","type","errors","warnings","dryRun","accessPolicies"],"additionalProperties":false,"title":"CodeSyncDryRun"}}}},"202":{"description":"Response for status 202","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"CodeSync","oneOf":[{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"workspaceId":{"description":"Unique resource ID (opaque). Null for `dbt Core`, `dbt Cloud`, and `Cube` syncs.","type":["string","null"]},"datasourceId":{"type":"string","description":"Unique resource ID (opaque)."},"method":{"type":"string","description":"How the sync was triggered."},"outcome":{"type":"string","enum":["queued","running","completed","failed"],"description":"Lifecycle state. `queued` and `running` are in-progress; `completed` and `failed` are terminal. Poll until terminal with `get sync by id`."},"createdAt":{"type":"string","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))$"},"created":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync created. Null until terminal."},"updated":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync updated. Null until terminal."},"removed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync removed. Null until terminal."},"unchanged":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync left unchanged. Null until terminal."},"error":{"description":"Job-level failure reason. Null unless the sync `failed`.","type":["string","null"]},"type":{"type":"string","const":"Steep as Code","description":"Source of the semantic models that were synced."},"errors":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Errors the sync reported. Null until terminal."},"warnings":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Warnings the sync reported. Null until terminal."}},"required":["id","workspaceId","datasourceId","method","outcome","createdAt","created","updated","removed","unchanged","error","type","errors","warnings"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"workspaceId":{"description":"Unique resource ID (opaque). Null for `dbt Core`, `dbt Cloud`, and `Cube` syncs.","type":["string","null"]},"datasourceId":{"type":"string","description":"Unique resource ID (opaque)."},"method":{"type":"string","description":"How the sync was triggered."},"outcome":{"type":"string","enum":["queued","running","completed","failed"],"description":"Lifecycle state. `queued` and `running` are in-progress; `completed` and `failed` are terminal. Poll until terminal with `get sync by id`."},"createdAt":{"type":"string","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))$"},"created":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync created. Null until terminal."},"updated":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync updated. Null until terminal."},"removed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync removed. Null until terminal."},"unchanged":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync left unchanged. Null until terminal."},"error":{"description":"Job-level failure reason. Null unless the sync `failed`.","type":["string","null"]},"type":{"anyOf":[{"type":"string","enum":["dbt Core","dbt Cloud","Cube"]},{"type":"null"}],"description":"Source of the semantic models that were synced."},"errors":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},{"type":"null"}],"description":"Errors keyed by metric `identifier`. Null until terminal."},"warnings":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},{"type":"null"}],"description":"Warnings keyed by metric `identifier`. Null until terminal."}},"required":["id","workspaceId","datasourceId","method","outcome","createdAt","created","updated","removed","unchanged","error","type","errors","warnings"],"additionalProperties":false}]}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"504":{"description":"Response for status 504","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1CodeSyncs"}},"/v1/code/syncs/{id}":{"get":{"hide":false,"description":"Get the current state of a sync by `id`. Use to poll an enqueued sync until its `outcome` is terminal (`completed` or `failed`).","tags":["code"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"CodeSync","oneOf":[{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"workspaceId":{"description":"Unique resource ID (opaque). Null for `dbt Core`, `dbt Cloud`, and `Cube` syncs.","type":["string","null"]},"datasourceId":{"type":"string","description":"Unique resource ID (opaque)."},"method":{"type":"string","description":"How the sync was triggered."},"outcome":{"type":"string","enum":["queued","running","completed","failed"],"description":"Lifecycle state. `queued` and `running` are in-progress; `completed` and `failed` are terminal. Poll until terminal with `get sync by id`."},"createdAt":{"type":"string","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))$"},"created":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync created. Null until terminal."},"updated":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync updated. Null until terminal."},"removed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync removed. Null until terminal."},"unchanged":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync left unchanged. Null until terminal."},"error":{"description":"Job-level failure reason. Null unless the sync `failed`.","type":["string","null"]},"type":{"type":"string","const":"Steep as Code","description":"Source of the semantic models that were synced."},"errors":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Errors the sync reported. Null until terminal."},"warnings":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Warnings the sync reported. Null until terminal."}},"required":["id","workspaceId","datasourceId","method","outcome","createdAt","created","updated","removed","unchanged","error","type","errors","warnings"],"additionalProperties":false},{"type":"object","properties":{"id":{"type":"string","description":"Unique resource ID (opaque)."},"workspaceId":{"description":"Unique resource ID (opaque). Null for `dbt Core`, `dbt Cloud`, and `Cube` syncs.","type":["string","null"]},"datasourceId":{"type":"string","description":"Unique resource ID (opaque)."},"method":{"type":"string","description":"How the sync was triggered."},"outcome":{"type":"string","enum":["queued","running","completed","failed"],"description":"Lifecycle state. `queued` and `running` are in-progress; `completed` and `failed` are terminal. Poll until terminal with `get sync by id`."},"createdAt":{"type":"string","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))$"},"created":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync created. Null until terminal."},"updated":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync updated. Null until terminal."},"removed":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync removed. Null until terminal."},"unchanged":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"`identifier`s of entities the sync left unchanged. Null until terminal."},"error":{"description":"Job-level failure reason. Null unless the sync `failed`.","type":["string","null"]},"type":{"anyOf":[{"type":"string","enum":["dbt Core","dbt Cloud","Cube"]},{"type":"null"}],"description":"Source of the semantic models that were synced."},"errors":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},{"type":"null"}],"description":"Errors keyed by metric `identifier`. Null until terminal."},"warnings":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},{"type":"null"}],"description":"Warnings keyed by metric `identifier`. Null until terminal."}},"required":["id","workspaceId","datasourceId","method","outcome","createdAt","created","updated","removed","unchanged","error","type","errors","warnings"],"additionalProperties":false}]}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"getV1CodeSyncsById"}},"/v1/code/validate":{"post":{"description":"Check a set of Steep YAML files before syncing them, e.g. in CI: returns whether they are `valid` and every problem, each pointing at its file. Only the files are checked: nothing is read from your workspace or warehouse, so metric operands, categories, owners, tables and columns are not checked. No API key needed. Send all Steep YAML files, not only the changed ones. Nothing is written; to see what a sync would change, use `dryRun` on `POST /v1/code/syncs`. The request may be up to 10 MB.","tags":["code"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"files":{"minItems":1,"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"],"additionalProperties":false},"description":"Every Steep YAML file, not only the changed ones, since identifiers must be unique across them. Each `path` is relative to the repository root, uses forward slashes, ends in `.yml` or `.yaml`, and appears once."}},"required":["files"],"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"files":{"minItems":1,"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"],"additionalProperties":false},"description":"Every Steep YAML file, not only the changed ones, since identifiers must be unique across them. Each `path` is relative to the repository root, uses forward slashes, ends in `.yml` or `.yaml`, and appears once."}},"required":["files"],"additionalProperties":false}},"multipart/form-data":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"files":{"minItems":1,"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"content":{"type":"string"}},"required":["path","content"],"additionalProperties":false},"description":"Every Steep YAML file, not only the changed ones, since identifiers must be unique across them. Each `path` is relative to the repository root, uses forward slashes, ends in `.yml` or `.yaml`, and appears once."}},"required":["files"],"additionalProperties":false}}}},"responses":{"200":{"description":"Response for status 200","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"valid":{"type":"boolean","description":"`false` when any problem is `fatal` or an `error`. Warnings alone keep it `true`."},"problems":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string","enum":["fatal","error","warning"],"description":"`fatal`: the files can't be synced at all. `error`: a definition, or part of one, would be left out. `warning`: nothing would change."},"code":{"type":"string","description":"Stable kind of problem, e.g. `yaml-invalid` or `metric-identifier-duplicated`, for acting on problems without parsing `message`."},"kind":{"type":"string","description":"The kind of definition the problem is about, e.g. `metrics` or `modules`; `files` for a file that can't be read."},"subject":{"type":"string","description":"The `identifier` or key of the definition the problem is about; the file's `path` when `kind` is `files`."},"message":{"type":"string"},"location":{"description":"Where the problem was found. `line` and `column` are set only when known.","type":"object","properties":{"path":{"type":"string","description":"The file, as sent."},"line":{"description":"1-based.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"column":{"description":"1-based.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["path"],"additionalProperties":false}},"required":["severity","code","kind","subject","message"],"additionalProperties":false}}},"required":["valid","problems"],"additionalProperties":false}}}},"401":{"description":"Response for status 401","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"403":{"description":"Response for status 403","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"422":{"description":"Response for status 422","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"},"validationErrors":{"type":"array","items":{"type":"object","properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["message"],"additionalProperties":false}}},"required":["message","validationErrors"],"additionalProperties":false}}}},"429":{"description":"Response for status 429","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}},"500":{"description":"Response for status 500","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"message":{"type":"string"}},"required":["message"],"additionalProperties":false}}}}},"operationId":"postV1CodeValidate"}}},"openapi":"3.0.3","info":{"title":"Steep API","description":"API documentation","version":"1.0.0"},"components":{"schemas":{}}}