> ## Agent Instructions
>
> Base URL: https://api.anysite.io
> Authentication: send the `access-token` header. Do NOT use `Authorization: Bearer`.
> Full endpoint catalog: https://app.anysite.io/docs
# Data analysis

Page, filter, aggregate, merge and export data fetched through the MCP server without new API calls.

Goal: fetch data once with `execute`, then work with the full result on the server instead of re-fetching it
or loading it all into the conversation.

You normally just ask your client in plain language ("keep only the ones in Berlin and export a CSV"); the
client picks these tools itself. This page describes what they do so you know what to ask for.

## How the cache works

1. `execute` stores the **whole** result on the server and returns the first 10 items, the `total` and a
   `cache_key`. If there are more items, the response also has `next_offset`.
2. Every tool below takes that `cache_key`. None of them calls the source again, and none of them costs
   usage.
3. Cached results and the history of your `execute` calls are kept for 7 days. After that, a `cache_key`
   returns `No data found for this cache_key. It may have expired — re-run execute().`

## Page through results

`get_page(cache_key, offset, limit)` returns the items from `offset`, with `next_offset` and `has_more`.
One page holds at most 50 items; a larger `limit` returns 50 and a note to continue from `next_offset`.

## Filter and sort

`query_cache(cache_key, conditions, sort_by, sort_order, limit, offset)` returns matching items and their
`total`.

```json
{
  "cache_key": "<cache_key>",
  "conditions": [
    {"field": "location", "op": "contains", "value": "Berlin"},
    {"field": "follower_count", "op": ">", "value": 1000}
  ],
  "sort_by": "follower_count",
  "sort_order": "desc",
  "limit": 10
}
```

- All conditions must match (AND).
- Operators: `=`, `!=`, `>`, `<`, `>=`, `<=`, `contains`, `not_contains`. `contains` and `not_contains` ignore
  case; `>`, `<`, `>=`, `<=` compare numbers.
- Nested fields use dots, for example `"field": "company.name"`.
- `sort_order` is `asc` (default) or `desc`.
- Field names are those of the items `execute` returned. If nothing matches but the cache has items, the tool
  says so — check the field name and value.

## Aggregate

Add `aggregate` to get one number instead of items:

```json
{"cache_key": "<cache_key>", "aggregate": {"field": "follower_count", "op": "avg"}}
```

- Functions: `count`, `sum`, `avg`, `min`, `max`, `uniq` (number of distinct values). `count` needs no field.
- Add `group_by` to get one value per group, largest first, up to `limit` groups (default 10):
  `{"aggregate": {"op": "count"}, "group_by": "industry"}` returns `{"groups": {"Software": 42, ...}}`.
- `conditions` apply before aggregation.

## Merge several results

`merge_data(cache_keys, dedupe_by)` combines 2 to 20 cached results (up to 100,000 rows in total) into a new
`cache_key` that works with every tool on this page.

- Identical rows are always collapsed.
- `dedupe_by` (up to 10 field names, for example `["url"]`) also collapses rows that share those values.
  Rows where any of those fields is missing or empty are kept and counted in `rows_without_key`.
- Keys that have expired are skipped and listed in a note; the rest are merged.

## Export a file

`export_data(cache_key, output_format, list_unpack)` returns a `file_url`, the row `total`, the file size and
a preview.

- Formats: `json` (default), `csv`, `jsonl`, `xlsx`.
- The export always contains **all** items of the `cache_key`. Filters from `query_cache` do not narrow it.
  To export several fetches as one file, `merge_data` them first and export the merged key.
- `list_unpack` (CSV and XLSX only, 0–255, default 1) sets how many items of each nested list become their
  own columns.
- The download link works without a key — anyone with the link can download the file, so do not share it if
  the data is sensitive. The link keeps working for as long as the cached result exists.

## Find an earlier result

`search_requests(source, category, endpoint, query, since, until, limit, offset)` lists your past `execute`
calls, newest first, with their parameters, item count, time and `cache_key`. `query` matches text inside the
parameters; `since` and `until` take ISO 8601 date-times. Use it instead of fetching the same data again.

## Troubleshooting

| Message | Fix |
|---|---|
| `No data found for this cache_key. It may have expired — re-run execute().` | The result is older than 7 days or the key is wrong. Fetch again. |
| `No items matched the given conditions (N items in cache). Check condition fields and values.` | The field name or value does not match the items. Look at one item with `get_page` first. |
| `Invalid operator: …` / `Invalid aggregate: …` | Use one of the operators or functions listed above. |
| `Unsupported format '…'. Use: json, csv, jsonl, xlsx` | Pick a supported `output_format`. |
| `cache_keys must contain at least 2 different cache_key values` / `Too many cache_keys` / `Too many rows to merge` | Merge between 2 and 20 results with at most 100,000 rows in total. |
