# Search result totals `POST /analytics/v1/searches/results/summary` How a type or a set of results does in search, for example categories against products. Only the clicks, carts and sales on these results count. ## Request example ```bash curl --request POST \ --url 'https://api.eu1.luigisbox.ai/analytics/v1/searches/results/summary?channel_ids=' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "attribution_model": "last_touch", "date_range": { "date_from": "2026-04-15T12:00:00Z", "date_to": "2026-04-15T12:00:00Z" }, "filters": { "$and": [ {} ], "$not": {}, "$or": [ {} ] }, "group_by": [], "metrics": [ "users" ], "sort": { "direction": "asc", "field": "users" }, "touchpoints": [ "autocomplete" ] }' ``` ## Query Parameters | Name | Type | Required | Description | Constraints | |---|---|---|---|---| | `channel_ids` | `Array` | Yes | One or more channel ids to aggregate over. Provide as repeated query parameters (``?channel_ids=A&channel_ids=B``). | >= 1 items | ## Request Body **Required.** ### application/json Schema: `object` #### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `attribution_model` | `string` | No | Which of the lists that showed an item is credited with an interaction on it; only `last_touch`, the last of them, is recorded today. | allowed values: last_touch | | `date_range` | `object` | Yes | The time range of the report. | — | | `date_range.date_from` | `string` | Yes | Start, inclusive. | format: date-time | | `date_range.date_to` | `string` | Yes | End, exclusive. | format: date-time | | `filters` | `anyOf(oneOf(object, object), null)` | No | Which rows are counted; every row when left out. `followed_by_search` holds on an autocomplete list the shopper submitted as a search, and never on a `serp` list. At most 100 conditions, in groups nested at most 10 deep — conditions are counted and the groups holding them are not. A tree past either is a `422` of type `filter_too_complex`. | — | | `filters.$and` | `Array` | No | Nodes that must all match. | >= 1 items | | `filters.$not` | `oneOf(object, object)` | No | A node that must not match. | — | | `filters.$or` | `Array` | No | Nodes of which at least one must match. | >= 1 items | | `filters.consent_granted` | `object` | No | Operators on one true-or-false field. | — | | `filters.consent_granted.eq` | `boolean` | No | Equal to. | — | | `filters.device` | `object` | No | Operators on one text field. | — | | `filters.device.eq` | `string` | No | Equal to. | — | | `filters.device.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.device.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.device.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.device.neq` | `string` | No | Not equal to. | — | | `filters.device.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.external_ab_test_variant` | `object` | No | Operators on one text field. | — | | `filters.external_ab_test_variant.eq` | `string` | No | Equal to. | — | | `filters.external_ab_test_variant.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.external_ab_test_variant.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.external_ab_test_variant.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.external_ab_test_variant.neq` | `string` | No | Not equal to. | — | | `filters.external_ab_test_variant.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.filtered` | `object` | No | Operators on one true-or-false field. | — | | `filters.filtered.eq` | `boolean` | No | Equal to. | — | | `filters.followed_by_search` | `object` | No | Operators on one true-or-false field. | — | | `filters.followed_by_search.eq` | `boolean` | No | Equal to. | — | | `filters.identity` | `object` | No | Operators on one text field. | — | | `filters.identity.eq` | `string` | No | Equal to. | — | | `filters.identity.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.identity.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.identity.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.identity.neq` | `string` | No | Not equal to. | — | | `filters.identity.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.internal_ab_test_id` | `object` | No | Operators on one text field. | — | | `filters.internal_ab_test_id.eq` | `string` | No | Equal to. | — | | `filters.internal_ab_test_id.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.internal_ab_test_id.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.internal_ab_test_id.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.internal_ab_test_id.neq` | `string` | No | Not equal to. | — | | `filters.internal_ab_test_id.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.internal_ab_test_variant` | `object` | No | Operators on one text field. | — | | `filters.internal_ab_test_variant.eq` | `string` | No | Equal to. | — | | `filters.internal_ab_test_variant.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.internal_ab_test_variant.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.internal_ab_test_variant.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.internal_ab_test_variant.neq` | `string` | No | Not equal to. | — | | `filters.internal_ab_test_variant.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.landing_page` | `object` | No | Operators on one text field. | — | | `filters.landing_page.eq` | `string` | No | Equal to. | — | | `filters.landing_page.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.landing_page.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.landing_page.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.landing_page.neq` | `string` | No | Not equal to. | — | | `filters.landing_page.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.landing_page_host` | `object` | No | Operators on one text field. | — | | `filters.landing_page_host.eq` | `string` | No | Equal to. | — | | `filters.landing_page_host.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.landing_page_host.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.landing_page_host.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.landing_page_host.neq` | `string` | No | Not equal to. | — | | `filters.landing_page_host.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.personalized` | `object` | No | Operators on one true-or-false field. | — | | `filters.personalized.eq` | `boolean` | No | Equal to. | — | | `filters.platform` | `object` | No | Operators on one text field. | — | | `filters.platform.eq` | `string` | No | Equal to. | — | | `filters.platform.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.platform.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.platform.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.platform.neq` | `string` | No | Not equal to. | — | | `filters.platform.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.query` | `object` | No | Operators on one text field. | — | | `filters.query.eq` | `string` | No | Equal to. | — | | `filters.query.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.query.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.query.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.query.neq` | `string` | No | Not equal to. | — | | `filters.query.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.result_type` | `object` | No | Operators on one text field. | — | | `filters.result_type.eq` | `string` | No | Equal to. | — | | `filters.result_type.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.result_type.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.result_type.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.result_type.neq` | `string` | No | Not equal to. | — | | `filters.result_type.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.returning` | `object` | No | Operators on one true-or-false field. | — | | `filters.returning.eq` | `boolean` | No | Equal to. | — | | `filters.session_rank` | `object` | No | Operators on one whole-number field. | — | | `filters.session_rank.eq` | `integer` | No | Equal to. | — | | `filters.session_rank.gt` | `integer` | No | Greater than. | — | | `filters.session_rank.gte` | `integer` | No | At least. | — | | `filters.session_rank.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.session_rank.lt` | `integer` | No | Less than. | — | | `filters.session_rank.lte` | `integer` | No | At most. | — | | `filters.session_rank.neq` | `integer` | No | Not equal to. | — | | `filters.session_rank.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.title` | `object` | No | Operators on one text field. | — | | `filters.title.eq` | `string` | No | Equal to. | — | | `filters.title.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.title.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.title.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.title.neq` | `string` | No | Not equal to. | — | | `filters.title.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.traffic_source` | `object` | No | Operators on how a session arrived. | — | | `filters.traffic_source.eq` | `string` | No | Equal to. | allowed values: direct, paid, referral, llms | | `filters.traffic_source.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.traffic_source.neq` | `string` | No | Not equal to. | allowed values: direct, paid, referral, llms | | `filters.traffic_source.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.traffic_source_type` | `object` | No | Operators on one text field. | — | | `filters.traffic_source_type.eq` | `string` | No | Equal to. | — | | `filters.traffic_source_type.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.traffic_source_type.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.traffic_source_type.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.traffic_source_type.neq` | `string` | No | Not equal to. | — | | `filters.traffic_source_type.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.url_host` | `object` | No | Operators on one text field. | — | | `filters.url_host.eq` | `string` | No | Equal to. | — | | `filters.url_host.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.url_host.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.url_host.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.url_host.neq` | `string` | No | Not equal to. | — | | `filters.url_host.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.url_path` | `object` | No | Operators on one text field. | — | | `filters.url_path.eq` | `string` | No | Equal to. | — | | `filters.url_path.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.url_path.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.url_path.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.url_path.neq` | `string` | No | Not equal to. | — | | `filters.url_path.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `filters.*` | `object` | No | Operators on one text field. | — | | `filters.*.eq` | `string` | No | Equal to. | — | | `filters.*.exists` | `boolean` | No | Has a value (`true`) or has none (`false`). | — | | `filters.*.in` | `Array` | No | One of. | >= 1 items; <= 100 items | | `filters.*.matches` | `string` | No | Contains this text. | >= 1 characters | | `filters.*.neq` | `string` | No | Not equal to. | — | | `filters.*.not_in` | `Array` | No | None of. | >= 1 items; <= 100 items | | `group_by` | `Array` | No | Fields that split every row, summary and series point, e.g. `["touchpoint", "device"]`: at most 2 besides `touchpoint`, which splits the `touchpoints`. At most one of `landing_page`, `url_path`, `url_params.*` and `context.*`; a summary or series holds at most 500 groups, and a session with several values of a key counts once in each of its groups. | <= 3 items | | `metrics` | `Array` | No | Metrics to compute; every metric of the report when left out. | >= 1 items | | `sort` | `anyOf(object, null)` | No | Order of `groups`; by group value when left out. | — | | `sort.direction` | `string` | Yes | `asc` for ascending order, `desc` for descending. | allowed values: asc, desc | | `sort.field` | `string` | Yes | Metric to order by; one not in `metrics` is added to the response. | allowed values: users, sessions, searches, impressions, clicks, click_through_rate, users_click_through_rate, sessions_click_through_rate, attributed_transactions, attributed_transaction_rate, users_attributed_transaction_rate, sessions_attributed_transaction_rate, attributed_key_events_1, attributed_key_events_1_rate, users_attributed_key_events_1_rate, sessions_attributed_key_events_1_rate, attributed_key_events_2, attributed_key_events_2_rate, users_attributed_key_events_2_rate, sessions_attributed_key_events_2_rate, attributed_key_events_3, attributed_key_events_3_rate, users_attributed_key_events_3_rate, sessions_attributed_key_events_3_rate, exit_rate, reformulation_rate, average_position, average_click_position | | `touchpoints` | `Array` | Yes | Where the lists were shown. As with `channel_ids`, the touchpoints are pooled: one total, one series line and one row per key across all of them, and `group_by: ["touchpoint"]` splits them. Pooled, the counts of searches, impressions, clicks, transactions and key events add up, and so does money; users, sessions and queries count once however many of the touchpoints they appear at; and a rate is taken over the pooled lists. `searches` counts the lists shown, so an autocomplete submitted as a search counts once at each touchpoint, and an average position mixes the two touchpoints' scales. A reformulation is a change of query on the next list at the same touchpoint. | >= 1 items | #### Request body example ```json { "attribution_model": "last_touch", "date_range": { "date_from": "2026-04-15T12:00:00Z", "date_to": "2026-04-15T12:00:00Z" }, "filters": { "$and": [ {} ], "$not": {}, "$or": [ {} ] }, "group_by": [], "metrics": [ "users" ], "sort": { "direction": "asc", "field": "users" }, "touchpoints": [ "autocomplete" ] } ``` ## Responses | Status | Description | Content | |---|---|---| | `200` | Successful Response | application/json: object | | `400` | Malformed request | application/json: object | | `401` | Missing or invalid credentials | application/json: object | | `403` | Authenticated but not permitted | application/json: object | | `422` | Request validation failed, or the report cannot answer it as asked (`exception_details.problems`). | application/json: object | | `503` | Service temporarily unavailable | application/json: object | ### 200 Successful Response #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `groups` | `Array` | Yes | One item, the total, without `group_by`; one item for each group with it, in `sort` order, or by group value without a `sort`. | — | | `groups[].group` | `object` | No | Its `group_by` values; present with `group_by`. | — | | `groups[].group.channel_id` | `anyOf(string, null)` | No | The channel the counts come from. | — | | `groups[].group.consent_granted` | `anyOf(boolean, null)` | No | The visitor granted personalization consent. | — | | `groups[].group.context` | `anyOf(object, null)` | No | Context values grouped as `context.`, keyed by name. | — | | `groups[].group.context.*` | `anyOf(string, null)` | No | Additional property. | — | | `groups[].group.device` | `anyOf(string, null)` | No | Device: `desktop`, `mobile`, `tablet`, … | — | | `groups[].group.external_ab_test_variant` | `anyOf(string, null)` | No | Variant of the client's own A/B test. | — | | `groups[].group.internal_ab_test_id` | `anyOf(string, null)` | No | Luigi's Box A/B test. | — | | `groups[].group.internal_ab_test_variant` | `anyOf(string, null)` | No | Variant of the Luigi's Box A/B test. | — | | `groups[].group.landing_page` | `anyOf(string, null)` | No | The entry URL. | — | | `groups[].group.landing_page_host` | `anyOf(string, null)` | No | The entry URL's host. | — | | `groups[].group.personalized` | `anyOf(boolean, null)` | No | The session was served personalized results. | — | | `groups[].group.platform` | `anyOf(string, null)` | No | Platform: `ios`, `android`, `windows`, … | — | | `groups[].group.result_type` | `anyOf(string, null)` | No | Type of the result: `item`, `category`, `brand`, … | — | | `groups[].group.returning` | `anyOf(boolean, null)` | No | The visitor had an earlier session: `session_rank` of 2 or more. | — | | `groups[].group.surface_id` | `anyOf(string, null)` | No | The Surface that answered. | — | | `groups[].group.touchpoint` | `anyOf(string, null)` | No | Where the lists were shown. | — | | `groups[].group.traffic_source` | `anyOf(string, null)` | No | How the session arrived. | — | | `groups[].group.traffic_source_type` | `anyOf(string, null)` | No | Traffic source type, e.g. `chatgpt`. | — | | `groups[].group.url_host` | `anyOf(string, null)` | No | Host of the page the search ran on, e.g. a language site. | — | | `groups[].group.url_params` | `anyOf(object, null)` | No | URL parameters grouped as `url_params.`, keyed by name, so `url_params.utm_source` reads as `group.url_params.utm_source`. | — | | `groups[].group.url_params.*` | `anyOf(string, null)` | No | Additional property. | — | | `groups[].group.url_path` | `anyOf(string, null)` | No | Path of the page the search ran on, without its query string. | — | | `groups[].metrics` | `object` | Yes | Metrics over the group. | — | | `groups[].metrics.attributed_key_events_1` | `anyOf(number, null)` | No | Key event 1 interactions credited; by default key event 1 counts add-to-carts. | — | | `groups[].metrics.attributed_key_events_1_rate` | `anyOf(number, null)` | No | Searches in which it led to key event 1 (by default, an add-to-cart) / searches that showed it. | — | | `groups[].metrics.attributed_key_events_2` | `anyOf(number, null)` | No | Key event 2 interactions credited. | — | | `groups[].metrics.attributed_key_events_2_rate` | `anyOf(number, null)` | No | Searches in which it led to key event 2 / searches that showed it. | — | | `groups[].metrics.attributed_key_events_3` | `anyOf(number, null)` | No | Key event 3 interactions credited. | — | | `groups[].metrics.attributed_key_events_3_rate` | `anyOf(number, null)` | No | Searches in which it led to key event 3 / searches that showed it. | — | | `groups[].metrics.attributed_transaction_rate` | `anyOf(number, null)` | No | Searches in which it was bought / searches that showed it. | — | | `groups[].metrics.attributed_transactions` | `anyOf(number, null)` | No | Transactions credited to it. | — | | `groups[].metrics.average_click_position` | `anyOf(number, null)` | No | Average position at which it was clicked; `null` without clicks. | — | | `groups[].metrics.average_position` | `anyOf(number, null)` | No | Average position at which it was shown. | — | | `groups[].metrics.click_through_rate` | `anyOf(number, null)` | No | Searches in which it was clicked / searches that showed it. | — | | `groups[].metrics.clicks` | `anyOf(number, null)` | No | Clicks on it. | — | | `groups[].metrics.exit_rate` | `anyOf(number, null)` | No | Sessions that ended on a search showing it / sessions that showed it. | — | | `groups[].metrics.impressions` | `anyOf(integer, null)` | No | Times it was shown. | — | | `groups[].metrics.reformulation_rate` | `anyOf(number, null)` | No | Users who changed the query on their next search at the same touchpoint after one showing it / users shown it. | — | | `groups[].metrics.searches` | `anyOf(integer, null)` | No | Searches that showed it. | — | | `groups[].metrics.sessions` | `anyOf(integer, null)` | No | Sessions that showed it. | — | | `groups[].metrics.sessions_attributed_key_events_1_rate` | `anyOf(number, null)` | No | Sessions in which it led to key event 1 (by default, an add-to-cart) / sessions that showed it. | — | | `groups[].metrics.sessions_attributed_key_events_2_rate` | `anyOf(number, null)` | No | Sessions in which it led to key event 2 / sessions that showed it. | — | | `groups[].metrics.sessions_attributed_key_events_3_rate` | `anyOf(number, null)` | No | Sessions in which it led to key event 3 / sessions that showed it. | — | | `groups[].metrics.sessions_attributed_transaction_rate` | `anyOf(number, null)` | No | Sessions in which it was bought / sessions that showed it. | — | | `groups[].metrics.sessions_click_through_rate` | `anyOf(number, null)` | No | Sessions in which it was clicked / sessions that showed it. | — | | `groups[].metrics.users` | `anyOf(integer, null)` | No | Unique users who were shown it. | — | | `groups[].metrics.users_attributed_key_events_1_rate` | `anyOf(number, null)` | No | Users it led to key event 1 (by default, an add-to-cart) / users shown it. | — | | `groups[].metrics.users_attributed_key_events_2_rate` | `anyOf(number, null)` | No | Users it led to key event 2 / users shown it. | — | | `groups[].metrics.users_attributed_key_events_3_rate` | `anyOf(number, null)` | No | Users it led to key event 3 / users shown it. | — | | `groups[].metrics.users_attributed_transaction_rate` | `anyOf(number, null)` | No | Users who bought it / users shown it. | — | | `groups[].metrics.users_click_through_rate` | `anyOf(number, null)` | No | Users who clicked it / users shown it. | — | ##### Response example ```json { "groups": [ { "group": { "channel_id": "example", "consent_granted": true, "context": { "additionalProperty": "example" }, "device": "example", "external_ab_test_variant": "example", "internal_ab_test_id": "example", "internal_ab_test_variant": "example", "landing_page": "example", "landing_page_host": "example", "personalized": true, "platform": "example", "result_type": "example", "returning": true, "surface_id": "example", "touchpoint": "autocomplete", "traffic_source": "direct", "traffic_source_type": "example", "url_host": "example", "url_params": { "additionalProperty": "example" }, "url_path": "example" }, "metrics": { "attributed_key_events_1": 1, "attributed_key_events_1_rate": 1, "attributed_key_events_2": 1, "attributed_key_events_2_rate": 1, "attributed_key_events_3": 1, "attributed_key_events_3_rate": 1, "attributed_transaction_rate": 1, "attributed_transactions": 1, "average_click_position": 1, "average_position": 1, "click_through_rate": 1, "clicks": 1, "exit_rate": 1, "impressions": 1, "reformulation_rate": 1, "searches": 1, "sessions": 1, "sessions_attributed_key_events_1_rate": 1, "sessions_attributed_key_events_2_rate": 1, "sessions_attributed_key_events_3_rate": 1, "sessions_attributed_transaction_rate": 1, "sessions_click_through_rate": 1, "users": 1, "users_attributed_key_events_1_rate": 1, "users_attributed_key_events_2_rate": 1, "users_attributed_key_events_3_rate": 1, "users_attributed_transaction_rate": 1, "users_click_through_rate": 1 } } ] } ``` ### 400 Malformed request #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.error_code` | `string` | No | Stable machine code naming why a well-formed request was refused: snake_case, prefixed by its domain — e.g. `filter_unknown_field` or `cursor_mismatch`. Safe to branch on; `reason` is not. Absent when the status code says all there is to say. | — | | `exception_details.validation_errors` | `Array` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "error_code": "example", "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 401 Missing or invalid credentials #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.error_code` | `string` | No | Stable machine code naming why a well-formed request was refused: snake_case, prefixed by its domain — e.g. `filter_unknown_field` or `cursor_mismatch`. Safe to branch on; `reason` is not. Absent when the status code says all there is to say. | — | | `exception_details.validation_errors` | `Array` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "error_code": "example", "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 403 Authenticated but not permitted #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.error_code` | `string` | No | Stable machine code naming why a well-formed request was refused: snake_case, prefixed by its domain — e.g. `filter_unknown_field` or `cursor_mismatch`. Safe to branch on; `reason` is not. Absent when the status code says all there is to say. | — | | `exception_details.validation_errors` | `Array` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "error_code": "example", "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 422 Request validation failed, or the report cannot answer it as asked (`exception_details.problems`). #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | Yes | Machine-readable error context. | — | | `exception_details.error_code` | `string` | No | Stable machine code naming why a well-formed request was refused: snake_case, prefixed by its domain — e.g. `filter_unknown_field` or `cursor_mismatch`. Safe to branch on; `reason` is not. Absent when the status code says all there is to say. | — | | `exception_details.problems` | `Array` | No | Why the report cannot answer the request as asked; `validation_errors` covers malformed fields. | — | | `exception_details.problems[].code` | `string` | Yes | Stable code of the problem; switch on it, not on `message`. | allowed values: too_many_groups, too_many_high_cardinality_groups, too_many_points, ab_test_variant_without_test, nothing_to_compare, report_too_large | | `exception_details.problems[].loc` | `Array` | Yes | Where in the request, as in `validation_errors[].loc`, e.g. `["body", "group_by", 1]`. | — | | `exception_details.problems[].message` | `string` | Yes | What to change. | — | | `exception_details.validation_errors` | `Array` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "error_code": "example", "problems": [ { "code": "too_many_groups", "loc": [ "example" ], "message": "example" } ], "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 503 Service temporarily unavailable #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.error_code` | `string` | No | Stable machine code naming why a well-formed request was refused: snake_case, prefixed by its domain — e.g. `filter_unknown_field` or `cursor_mismatch`. Safe to branch on; `reason` is not. Absent when the status code says all there is to say. | — | | `exception_details.validation_errors` | `Array` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "error_code": "example", "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ```