> For the complete documentation index, see [llms.txt](https://docs.themochi.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.themochi.app/common-tasks/read-business-metrics.md).

# Read business metrics

Use this guide to build a report for one organization and a clear date range. Decide which measures and units the report needs before requesting data. A one-time local report can use CLI browser approval. A scheduled report should use an API key with only the read scopes it actually needs.

Use the [generated OpenAPI contract](https://openapi.gitbook.com/o/M0sgy6xKutCblHRqGmE5/spec/mochi-api.json) for exact date parameters and result schemas.

For a member-bound connection, `revenue:read` requires a Creator, Manager, or Finance role. Organization policy may add more restrictions.

## Define the report first

1. Name the organization and exact inclusive `date_from`/`date_to` calendar dates for analytics and revenue.
2. Use ISO 8601 timestamps with offsets for booking `start_from`/`start_to`, then normalize presentation separately. Do not silently mix organization-local calendar dates and UTC timestamps.
3. Choose only the required operations and scopes. A report that has no revenue section should not receive `revenue:read`.
4. Read the current OpenAPI response schemas before selecting fields.
5. Revenue integers are **minor currency units**, such as cents for a currency with two decimal places. The summary response does not include a currency code, so do not guess one. If the report must name a currency, use a current OpenAPI operation that returns a currency and never combine different currencies.
6. Treat conversion-rate numerators and denominators as part of the result, not just the displayed decimal.
7. Walk booking cursors to `null`; one page is not a complete period.

## Revenue summary request

These examples request one explicit calendar period. They print only the aggregate response; keep the raw result out of prompts and logs if it contains business-sensitive metrics.

### cURL

```bash
curl --fail-with-body --silent --show-error --get \
  "${MOCHI_BASE_URL}/v1/revenue/summary/" \
  --header "Authorization: Bearer ${MOCHI_API_KEY}" \
  --header "Accept: application/json" \
  --data-urlencode "date_from=${MOCHI_DATE_FROM}" \
  --data-urlencode "date_to=${MOCHI_DATE_TO}"
```

### Python

```python
import os

import requests

response = requests.get(
    f"{os.environ['MOCHI_BASE_URL']}/v1/revenue/summary/",
    headers={"Authorization": f"Bearer {os.environ['MOCHI_API_KEY']}"},
    params={"date_from": os.environ["MOCHI_DATE_FROM"], "date_to": os.environ["MOCHI_DATE_TO"]},
    timeout=30,
)
response.raise_for_status()
summary = response.json()
print({"period": summary["period"], "metrics_minor_units": summary["metrics"]})
```

### Node.js / TypeScript

```typescript
const baseUrl = process.env.MOCHI_BASE_URL ?? "https://api.themochi.app";
const url = new URL("/v1/revenue/summary/", baseUrl);
url.searchParams.set("date_from", process.env.MOCHI_DATE_FROM!);
url.searchParams.set("date_to", process.env.MOCHI_DATE_TO!);
const response = await fetch(url, {
  headers: { Authorization: `Bearer ${process.env.MOCHI_API_KEY}` },
  signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(`Mochi HTTP ${response.status}`);
const summary = (await response.json()) as { period: object; metrics: object };
console.log({ period: summary.period, metricsMinorUnits: summary.metrics });
```

### PHP

```php
<?php
$query = http_build_query([
    "date_from" => getenv("MOCHI_DATE_FROM"),
    "date_to" => getenv("MOCHI_DATE_TO"),
]);
$baseUrl = getenv("MOCHI_BASE_URL") ?: "https://api.themochi.app";
$handle = curl_init($baseUrl . "/v1/revenue/summary/?" . $query);
curl_setopt_array($handle, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("MOCHI_API_KEY")],
]);
$body = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
curl_close($handle);
if ($body === false || $status < 200 || $status >= 300) throw new RuntimeException("Mochi read failed");
$summary = json_decode($body, true, flags: JSON_THROW_ON_ERROR);
echo json_encode(["period" => $summary["period"], "metrics_minor_units" => $summary["metrics"]]);
```

## Verification and failure behavior

Verify that each response echoes the intended period, record `computed_at`, reconcile booking page counts, and compare a small aggregate against the Mochi product for the same organization and dates. Do not merge results whose periods or units differ.

Reads can be retried only as described in [Errors](/troubleshooting-and-safety/errors.md) and [Rate limits](/troubleshooting-and-safety/rate-limits.md). Bound retries, honor current server guidance, and retain only sanitized request metadata plus `X-Request-ID`. A failed report should remain failed or explicitly partial; never fill a missing metric with zero.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.themochi.app/common-tasks/read-business-metrics.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
