---
name: "maison-analytics"
description: "Measure and report: the Analytics page figures for one hotel and the Portfolio page figures across every hotel the caller may read (conversations, answered without handoff, knowledge gaps, daily channels, top unanswered questions, needs-you items), a portfolio overview, per-hotel dashboard statistics, and chat-log and AI-visibility reports (run, list runs across hotels, read as HTML or download as a spreadsheet, rerun). Use when asked how a hotel or portfolio is performing, to produce a periodic report, or to email a report to recipients. Tools: get_ai_visibility_report, get_chatlog_report, get_conversation_analytics, get_dashboard_stats, get_portfolio_analytics, get_portfolio_overview, list_ai_visibility_reports, list_chatlog_reports, list_report_runs, rerun_ai_visibility_report, rerun_chatlog_report, run_ai_visibility_report, run_chatlog_report."
license: "Proprietary. Use with a Maison API key under the Maison terms of service."
metadata:
  author: "maison-labs"
  version: "1.0.0"
  category: "analytics"
  api-base: "https://maison-labs.com"
  openapi: "https://maison-labs.com/api/v1/openapi.json"
  docs: "https://docs.maison-labs.com/skills/maison-analytics/"
---

# Maison — Analytics and reports

Measure and report: the Analytics page figures for one hotel and the Portfolio page figures across every hotel the caller may read (conversations, answered without handoff, knowledge gaps, daily channels, top unanswered questions, needs-you items), a portfolio overview, per-hotel dashboard statistics, and chat-log and AI-visibility reports (run, list runs across hotels, read as HTML or download as a spreadsheet, rerun). Use when asked how a hotel or portfolio is performing, to produce a periodic report, or to email a report to recipients.

Part of the Maison public API. Read the `maison-public-api` skill first for authentication, discovery and transport details (`https://docs.maison-labs.com/skills/maison-public-api/SKILL.md`).

## When to use

- Portfolio health over a period — `get_portfolio_overview` with `from`/`to`.
- One hotel's numbers — `get_dashboard_stats`.
- Produce and deliver a report — `run_chatlog_report` or `run_ai_visibility_report` with `recipients`.
- One hotel's conversation figures against the previous period — `get_conversation_analytics` with ISO `from`/`to`.
- Every hotel at once, with what needs attention — `get_portfolio_analytics`.
- Report runs across hotels, failed ones first — `list_report_runs` with `status: "ERROR"`.

## Before you start

1. Send `x-api-key: <key>` on every call; the key only reaches `/api/v1`.
2. `GET /api/v1/tools` (or MCP `tools/list`) returns the tools THIS key may run — if a tool below is missing there, you lack a grant; do not retry it.
3. Client-scoped tools take `clientId` (a hotel id). `whoami` lists the ids you can act on.

## Tools

| Tool | What it does | REST | Needs |
| --- | --- | --- | --- |
| `get_ai_visibility_report` | Retrieve a completed AI-visibility analytics report: with `format: "html"` (default) the run metadata and the full HTML (up to 2 MiB); with `format: "xlsx"` the metadata and a download `url` for the spreadsheet, valid for 5 minutes (`expiresAt`). | `GET /api/v1/client/{clientId}/report/aivisibility/{analyticsId}` | ai-visibility-analytics READ (client); read-only |
| `get_chatlog_report` | Retrieve a completed chat-log analytics report: with `format: "html"` (default) the run metadata and the full HTML (up to 2 MiB); with `format: "xlsx"` the metadata and a download `url` for the spreadsheet, valid for 5 minutes (`expiresAt`). | `GET /api/v1/client/{clientId}/report/chatlogs/{analyticsId}` | chat-log-analytics READ (client); read-only |
| `get_conversation_analytics` | The Analytics page figures for one hotel over [from, to] (ISO 8601 date-times, at most 400 UTC days): conversations and conversations answered without handoff, knowledge gaps opened / resolved / open, each compared with the equal-length previous window (`previous` is null before the hotel's first indexed conversation), the daily conversation count per channel, the median days to resolve a gap, and the top 10 open unanswered questions — `unanswered` is null unless the caller may also read conversations (chat-logs). | `GET /api/v1/client/{clientId}/analytics/conversations` | chat-log-analytics READ (client); plan: `chat-log-analytics`; read-only |
| `get_dashboard_stats` | System-wide counts (active clients, users) and a recent activity feed for one hotel. | `GET /api/v1/client/{clientId}/dashboard` | dashboard READ (client); read-only |
| `get_portfolio_analytics` | The Portfolio page figures over [from, to] (ISO 8601 date-times, at most 400 UTC days) across every enabled hotel the caller may read with analytics in its plan: summed conversations, answered without handoff and open gaps against the previous window, a per-property table, the daily conversations per channel, the top 10 unanswered questions across properties (only for hotels whose conversations the caller may read), and `needsYou` — integration or website-sync errors and open knowledge gaps, most urgent first. | `GET /api/v1/portfolio/analytics` | clients READ (any), chat-log-analytics READ (any); read-only |
| `get_portfolio_overview` | Health metrics and conversation trends across every hotel in the caller's portfolio over a date window (YYYY-MM-DD). | `GET /api/v1/portfolio/overview` | clients READ (any); read-only |
| `list_ai_visibility_reports` | Page through past AI-visibility analytics runs for a hotel ordered newest first. | `GET /api/v1/client/{clientId}/reports/aivisibility` | ai-visibility-analytics READ (client); read-only |
| `list_chatlog_reports` | Page through past chat-log analytics runs for a hotel ordered newest first. | `GET /api/v1/client/{clientId}/reports/chatlogs` | chat-log-analytics READ (client); read-only |
| `list_report_runs` | Page through analytics report runs (one row per run and hotel), newest first, across every hotel the caller may read — chat-log and AI-visibility runs alike, narrowed to the report types the caller holds. | `GET /api/v1/reports` | chat-log-analytics READ (any); read-only |
| `rerun_ai_visibility_report` | Reset errored clients in an existing AI-visibility analytics session back to QUEUED and requeue the SQS pipeline. | `POST /api/v1/client/{clientId}/report/aivisibility/{analyticsId}/rerun` | ai-visibility-analytics EXECUTE (client) |
| `rerun_chatlog_report` | Reset errored clients in an existing chat-log analytics session back to QUEUED and requeue the pipeline. | `POST /api/v1/client/{clientId}/report/chatlogs/{analyticsId}/rerun` | chat-log-analytics EXECUTE (client) |
| `run_ai_visibility_report` | Trigger an asynchronous AI-visibility report for one hotel. | `POST /api/v1/client/{clientId}/report/aivisibility` | ai-visibility-analytics EXECUTE (client); plan: `ai-visibility-analytics` |
| `run_chatlog_report` | Trigger an asynchronous chat-log analytics report for one hotel. | `POST /api/v1/client/{clientId}/report/chatlogs` | chat-log-analytics EXECUTE (client); plan: `chat-log-analytics` |

Full input fields for every tool: [references/tools.md](references/tools.md).

## Recommended workflows

### Run and read a chat-log report

1. `run_chatlog_report` with optional `startDate`/`endDate` and `recipients.to[]` (202, returns `analyticsId`).
2. Poll `list_chatlog_reports` (or `list_report_runs`) until the run's status is `DONE` (`ERROR` = failed; `QUEUED`/`IN_PROGRESS` = still running).
3. `get_chatlog_report` with the `analyticsId` for the HTML, or `format: "xlsx"` for a 5-minute download URL of the spreadsheet; `rerun_chatlog_report` to regenerate.

## Tips

- Reports are per type with their own grants: chat-log tools need `chat-log-analytics`, AI-visibility tools need `ai-visibility-analytics`.
- Report and overview dates are ISO `YYYY-MM-DD`; the portfolio overview is inclusive of both ends.
- `get_conversation_analytics` / `get_portfolio_analytics` take ISO 8601 date-times (with offset), at most 400 UTC days; `previous` is null — not zero — when the earlier window predates the hotel's indexed history.
- The unanswered-question lists need conversation read access (`chat-logs`); without it `unanswered` is null.

## Pitfalls

- A 409 from `run_*_report` means a run is already in flight for that hotel — poll the history instead of retrying.
- `get_*_report` returns HTML inline and refuses documents over 2 MiB — use `format: "xlsx"` for a download link instead; the link expires after 5 minutes.
- Run status values are exactly QUEUED, IN_PROGRESS, ERROR, DONE.
- In `get_portfolio_overview`, a `null` conversation count means that period's chat history is not available for that hotel; it is not zero. `conversationCoverage` says how many hotels report.

## Calling conventions

Same tool, three transports — pick whichever your runtime already speaks. Always send `x-api-key`.

```bash
# REST
curl -X GET "https://maison-labs.com/api/v1/client/<clientId>/report/aivisibility/<analyticsId>" -H "x-api-key: $MAISON_API_KEY"
```

```json
// MCP (https://maison-labs.com/mcp, Streamable HTTP): tools/call
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_ai_visibility_report", "arguments": {} } }
```

```json
// A2A (https://maison-labs.com/a2a): tasks/send with a data part
{ "jsonrpc": "2.0", "id": 1, "method": "tasks/send", "params": { "message": { "role": "user", "parts": [{ "type": "data", "data": { "tool": "get_ai_visibility_report", "input": {} } }] } } }
```

Errors are the same everywhere: `401` no/invalid key; `403 forbidden` with `details.missing` (the grants you lack — fall back to the composite's parts or stop); `403 not_entitled` (the hotel's plan lacks the feature); `404`, `409`, `413 too_large`, `503`. Inputs that fail validation return `400 invalid_input` with the Zod issues — fix and retry once.
