# Ask questions about your product's data

Analytics is the part of the platform that answers questions about your product's own data. Ask a question in plain English, the way you would ask a colleague, and you get an answer back — no SQL, no schema knowledge, no reporting setup.

## Ask a question

The question is one free-text string, scoped to the product you are working in. Two surfaces run the same operation.

| Surface | Call | Argument | Credential |
| --- | --- | --- | --- |
| MCP | [`analytics_query_run`](/reference/mcp-tools/analytics_query_run) | `q`, the natural-language question | An MCP session that is signed in and pinned to a product |
| REST | [`POST /analytics/query`](/reference/openapi/analytics) | the same `q` | Your user session |

Either way the argument is the question itself:

```json
{ "q": "How many deployments happened yesterday?" }
```

- **MCP is the primary interface an agent uses.** `analytics_query_run` takes that single argument and nothing else.
- **REST is what the generated application SDK exposes,** as the `analytics` namespace. The response body is exactly the five fields below — there is no envelope around them.
- **The product comes from the request context,** not from anything you pass in. There is no argument for choosing a different product.

## What comes back

| Field | What it holds |
| --- | --- |
| `answer` | The answer phrased in plain English. |
| `sql` | The query that was executed. |
| `rows` | The result rows. |
| `truncated` | `true` when the result was cut short and more rows exist. |
| `explanation` | How the question was interpreted. |

## What you can ask

- Counts — "How many deployments do we have?"
- Time-bounded counts — "How many deployments happened yesterday?"
- Sums and averages over a numeric field.
- Ratios between two measures.
- Grouping and filtering by the attributes the data exposes (names, domains, statuses, and similar).

One question covers the data the platform holds for that product, across the different parts of it. You do not pick a data source and you do not join anything yourself. Only data that has been made available to analytics can be queried; a product with nothing available returns an empty result rather than an error.

## How a query runs

1. You send the question together with your product context.
2. The service looks up which entities, measures and attributes exist for that product.
3. A language model translates your question into a query over those entities.
4. Before anything is executed, the query is rewritten so that it can only read rows belonging to your product. The product is injected by the server. It is never taken from the model, so a generated query cannot widen its own scope.
5. The query runs and the result is phrased back in words.

## When a query fails

A failed query returns a short, generic message. Details about the underlying query, the entity names or the storage layer are not returned to the caller; they go to the server-side log only.

The status code is meaningful and is preserved on both surfaces:

- A rejected generated query returns **422**.
- An upstream failure returns **502**.

The distinction is the part you can act on. The rejection judges the generated query rather than your question, so the useful response to a 422 is to rephrase the question, not to correct a syntax error of your own.

## Next steps

- [Read how product data is kept apart](/privacy/data-and-privacy#separation-between-products): the boundary the query rewrite enforces.
- [Open the analytics REST reference](/reference/openapi/analytics): the request and response shapes in full.
- [Browse the MCP tools](/reference/mcp-tools): every tool an agent can call in a product session.
