> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file to discover all available pages before exploring further.

# Reports & Analytics

> Pull count and time-series analytics from the Rhombus API — people and vehicle counts, occupancy trends, line-crossing (threshold) counts, and CSV export.

## Overview

The Rhombus Report Webservice turns detections from your cameras into aggregated, time-bucketed analytics. Instead of iterating over individual events, you request a count report for a time range and interval, and Rhombus returns one data point per bucket with a per-type count.

Through the API, you can:

* **Build count time-series** for people, vehicles, motion, faces, and other detection types across an org, location, or single device
* **Track people counts and occupancy** with the latest readings and bucketed occupancy trends
* **Measure line-crossing (threshold) counts** for humans or vehicles that cross a configured line
* **Export report data as CSV** for spreadsheets, BI tools, and compliance reporting

A few conventions apply across this API:

* **Timestamps are epoch milliseconds** on the V2, occupancy, and threshold endpoints (`startTimeMs` / `endTimeMs`). The legacy v1 `getCountReport` uses `"YYYY-MM-DD"` **date strings** instead.
* **Reports are described by three enums** — a report type (what to count), an interval (bucket size), and a scope (org, location, or device). See the [reference tables](#enum-reference) below.
* **There is no "list report types" endpoint.** The available types are fixed and documented in the [`ReportType` table](#reporttype).

## Prerequisites

<Note>
  Before you begin, make sure you have:

  * A **Rhombus API key** with report permissions (generated in the Rhombus Console under Settings > API)
  * At least one **camera** deployed and reporting the analytics you want to query (for example, a camera running people counting or LPR)
  * The **UUID** of the org, location, or device you want to scope the report to
  * For **CSV export** and audit/diagnostic feeds: the **`REPORT_ADMINISTRATION`** permission on the API key
</Note>

All requests are `POST`, send a JSON body, and use the base URL `https://api2.rhombussystems.com` with these headers:

```
x-auth-scheme: api-token
x-auth-apikey: YOUR_API_KEY
Content-Type: application/json
```

## Build a count time-series

`getCountReportV2` is the primary reporting endpoint. Supply a time range in epoch milliseconds, an interval, a scope, and one or more report types. Rhombus returns one data point per interval bucket, each carrying an `eventCountMap` keyed by report type.

This example pulls hourly **people** and **vehicle** counts for a single location over the last 24 hours.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/report/getCountReportV2",
      headers=headers,
      json={
          "scope": "LOCATION",
          "uuid": "YOUR_LOCATION_UUID",
          "types": ["PEOPLE", "VEHICLES"],
          "interval": "HOURLY",
          "startTimeMs": one_day_ago_ms,
          "endTimeMs": now_ms,
          "timeZone": "America/Los_Angeles"
      }
  )

  data = response.json()
  for point in data.get("timeSeriesDataPoints", []):
      counts = point.get("eventCountMap", {})
      print(f"{point.get('dateLocal')}: "
            f"people={counts.get('PEOPLE', 0)}, "
            f"vehicles={counts.get('VEHICLES', 0)}")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneDayAgo = now - (24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/report/getCountReportV2', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      scope: 'LOCATION',
      uuid: 'YOUR_LOCATION_UUID',
      types: ['PEOPLE', 'VEHICLES'],
      interval: 'HOURLY',
      startTimeMs: oneDayAgo,
      endTimeMs: now,
      timeZone: 'America/Los_Angeles'
    })
  });

  const data = await response.json();
  for (const point of data.timeSeriesDataPoints || []) {
    const counts = point.eventCountMap || {};
    console.log(`${point.dateLocal}: people=${counts.PEOPLE || 0}, vehicles=${counts.VEHICLES || 0}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/report/getCountReportV2 \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "scope": "LOCATION",
      "uuid": "YOUR_LOCATION_UUID",
      "types": ["PEOPLE", "VEHICLES"],
      "interval": "HOURLY",
      "startTimeMs": 1712620800000,
      "endTimeMs": 1712707200000,
      "timeZone": "America/Los_Angeles"
    }'
  ```
</CodeGroup>

### Request fields

<ParamField body="scope" type="string" required>
  Aggregation level. One of `ORG`, `LOCATION`, `DEVICE`, or `REGION`. See the [`ReportScope` table](#reportscope).
</ParamField>

<ParamField body="uuid" type="string">
  The location or device UUID that matches your `scope`. Omit for `scope: "ORG"` to report across the whole organization.
</ParamField>

<ParamField body="types" type="string[]" required>
  One or more report types to count. See the [`ReportType` table](#reporttype).
</ParamField>

<ParamField body="interval" type="string" required>
  Bucket size for each data point. One of `MINUTELY`, `QUARTERHOURLY`, `HOURLY`, `DAILY`, `WEEKLY`, `MONTHLY`. See the [`ReportInterval` table](#reportinterval).
</ParamField>

<ParamField body="startTimeMs" type="integer" required>
  Start of the range, in epoch milliseconds.
</ParamField>

<ParamField body="endTimeMs" type="integer" required>
  End of the range, in epoch milliseconds.
</ParamField>

<ParamField body="timeZone" type="string">
  Optional IANA time zone (for example, `America/New_York`). Controls where interval bucket boundaries fall and populates `dateLocal`. Defaults to UTC when omitted.
</ParamField>

<Warning>
  The V2 endpoint accepts legacy `startDate` / `endDate` string fields, but these are deprecated. Use the epoch-millisecond `startTimeMs` / `endTimeMs` fields instead.
</Warning>

### Response fields

<ResponseField name="timeSeriesDataPoints" type="object[]">
  One entry per interval bucket.

  <Expandable title="TimeSeriesDataPointV2Type">
    <ResponseField name="dateUtc" type="string">Bucket start expressed in UTC.</ResponseField>
    <ResponseField name="dateLocal" type="string">Bucket start expressed in the requested `timeZone`.</ResponseField>
    <ResponseField name="eventCountMap" type="object">Map of report type to count for this bucket, for example `{"PEOPLE": 42, "VEHICLES": 7}`.</ResponseField>
    <ResponseField name="reportingDevicesMap" type="object">Map of report type to the list of device UUIDs that contributed counts in this bucket.</ResponseField>
  </Expandable>
</ResponseField>

<Tip>
  Need a single total instead of a bucketed series? Call `/api/report/getSummaryCountReport` with the same `startTimeMs`, `endTimeMs`, `interval`, `scope`, and a single `type`.
</Tip>

### Legacy date-string reports

The v1 `/api/report/getCountReport` endpoint predates epoch-millisecond timestamps. It takes `startDate` and `endDate` as `"YYYY-MM-DD"` strings and a single `type` rather than a `types` array. Prefer `getCountReportV2` for new integrations; use v1 only if you already depend on its date-string behavior.

```bash cURL theme={null}
curl -X POST https://api2.rhombussystems.com/api/report/getCountReport \
  -H "Content-Type: application/json" \
  -H "x-auth-scheme: api-token" \
  -H "x-auth-apikey: YOUR_API_KEY" \
  -d '{
    "scope": "LOCATION",
    "uuid": "YOUR_LOCATION_UUID",
    "type": "PEOPLE",
    "interval": "DAILY",
    "startDate": "2024-01-01",
    "endDate": "2024-01-31"
  }'
```

## Build a people-count and occupancy dashboard

For a live dashboard, combine two endpoints: `getMostRecentPeopleCountEvents` for the latest readings from a camera, and `getOccupancyCountsV2` for a bucketed occupancy trend over time.

### Latest people-count readings

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/report/getMostRecentPeopleCountEvents",
      headers=headers,
      json={
          "deviceUuid": "YOUR_CAMERA_UUID",
          "numMostRecent": 10
      }
  )

  data = response.json()
  for event in data.get("events", []):
      print(f"[{event.get('eventTimestamp')}] people={event.get('peopleCount')}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/report/getMostRecentPeopleCountEvents', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      deviceUuid: 'YOUR_CAMERA_UUID',
      numMostRecent: 10
    })
  });

  const data = await response.json();
  for (const event of data.events || []) {
    console.log(`[${event.eventTimestamp}] people=${event.peopleCount}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/report/getMostRecentPeopleCountEvents \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "deviceUuid": "YOUR_CAMERA_UUID",
      "numMostRecent": 10
    }'
  ```
</CodeGroup>

Each entry in `events` is a people-count reading:

<ResponseField name="events" type="object[]">
  <Expandable title="PeopleCountEventType">
    <ResponseField name="uuid" type="string">Unique identifier for the reading.</ResponseField>
    <ResponseField name="deviceUuid" type="string">The camera that produced the reading.</ResponseField>
    <ResponseField name="locationUuid" type="string">Location the device belongs to.</ResponseField>
    <ResponseField name="orgUuid" type="string">Organization identifier.</ResponseField>
    <ResponseField name="eventTimestamp" type="integer">Reading time in epoch milliseconds.</ResponseField>
    <ResponseField name="peopleCount" type="integer">Number of people counted at this moment.</ResponseField>
    <ResponseField name="imageS3Key" type="string">S3 key for the associated frame (a key, not a URL).</ResponseField>
    <ResponseField name="boundingBoxes" type="object[]">Detection bounding boxes for the counted people.</ResponseField>
    <ResponseField name="deviceLabels" type="string[]">Labels applied to the device.</ResponseField>
    <ResponseField name="locationLabels" type="string[]">Labels applied to the location.</ResponseField>
    <ResponseField name="subLocationsHierarchyKey" type="string">Sub-location hierarchy key, when configured.</ResponseField>
  </Expandable>
</ResponseField>

### Occupancy trend over time

`getOccupancyCountsV2` returns bucketed occupancy for a device across a time range, using the same interval model as count reports.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/report/getOccupancyCountsV2",
      headers=headers,
      json={
          "deviceUuid": "YOUR_CAMERA_UUID",
          "startTimeMs": one_day_ago_ms,
          "endTimeMs": now_ms,
          "interval": "HOURLY"
      }
  )

  data = response.json()
  for point in data.get("timeSeriesDataPoints", []):
      print(f"{point.get('dateLocal')}: {point.get('eventCountMap')}")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneDayAgo = now - (24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/report/getOccupancyCountsV2', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      deviceUuid: 'YOUR_CAMERA_UUID',
      startTimeMs: oneDayAgo,
      endTimeMs: now,
      interval: 'HOURLY'
    })
  });

  const data = await response.json();
  for (const point of data.timeSeriesDataPoints || []) {
    console.log(`${point.dateLocal}: ${JSON.stringify(point.eventCountMap)}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/report/getOccupancyCountsV2 \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "deviceUuid": "YOUR_CAMERA_UUID",
      "startTimeMs": 1712620800000,
      "endTimeMs": 1712707200000,
      "interval": "HOURLY"
    }'
  ```
</CodeGroup>

The response `timeSeriesDataPoints` carry the same `dateUtc`, `dateLocal`, `eventCountMap`, and `reportingDevicesMap` fields as count reports, plus a `timestampMs` (bucket start in epoch milliseconds) and an `approximateTimestampMsMap`.

<Note>
  This occupancy report is derived from camera analytics via the Report Webservice. It is distinct from the Occupancy Webservice (`/api/occupancy/*`), which reads physical BLE and motion sensors — a separate product.
</Note>

## Count line crossings (threshold counts)

When a camera has a crossing line configured, Rhombus counts objects that cross it. `getThresholdCrossingCounts` returns those counts bucketed over time for one or more devices, filtered to a single object class.

The `dailyResetTimeMinute` field sets the minute of the day (0–1439, in the device's local time) at which the running daily count resets — useful for aligning counts to a business day rather than midnight.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  one_week_ago_ms = now_ms - (7 * 24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/report/getThresholdCrossingCounts",
      headers=headers,
      json={
          "devices": ["YOUR_CAMERA_UUID"],
          "startTimeMs": one_week_ago_ms,
          "endTimeMs": now_ms,
          "crossingObject": "HUMAN",
          "dailyResetTimeMinute": 0
      }
  )

  data = response.json()
  for entry in data.get("counts", []):
      print(f"[{entry.get('timestampMs')}] crossings={entry.get('count')}")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneWeekAgo = now - (7 * 24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/report/getThresholdCrossingCounts', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      devices: ['YOUR_CAMERA_UUID'],
      startTimeMs: oneWeekAgo,
      endTimeMs: now,
      crossingObject: 'HUMAN',
      dailyResetTimeMinute: 0
    })
  });

  const data = await response.json();
  for (const entry of data.counts || []) {
    console.log(`[${entry.timestampMs}] crossings=${entry.count}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/report/getThresholdCrossingCounts \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "devices": ["YOUR_CAMERA_UUID"],
      "startTimeMs": 1712016000000,
      "endTimeMs": 1712620800000,
      "crossingObject": "HUMAN",
      "dailyResetTimeMinute": 0
    }'
  ```
</CodeGroup>

### Request fields

<ParamField body="devices" type="string[]">
  One or more camera UUIDs to include in the counts.
</ParamField>

<ParamField body="startTimeMs" type="integer">
  Start of the range, in epoch milliseconds.
</ParamField>

<ParamField body="endTimeMs" type="integer">
  End of the range, in epoch milliseconds.
</ParamField>

<ParamField body="crossingObject" type="string">
  The object class to count. Common values are `HUMAN` and `VEHICLE`. See the [`CrossingObject` table](#crossingobject).
</ParamField>

<ParamField body="dailyResetTimeMinute" type="integer">
  Minute of the day (0–1439) at which the daily count resets, in the device's local time.
</ParamField>

### Response fields

<ResponseField name="counts" type="object[]">
  <Expandable title="ThresholdCrossingCountType">
    <ResponseField name="count" type="integer">Number of crossings in this bucket.</ResponseField>
    <ResponseField name="timestampMs" type="integer">Bucket start in epoch milliseconds.</ResponseField>
  </Expandable>
</ResponseField>

## Export report data as CSV

The Export Webservice streams report data as **CSV** (`text/csv`) rather than JSON. There is **no PDF export** — CSV is the only export format.

<Warning>
  Export endpoints (and the audit/diagnostic feeds) require the **`REPORT_ADMINISTRATION`** permission on your API key. Without it, these calls are rejected.
</Warning>

`/api/export/countReports` mirrors the count report parameters but returns a CSV stream. Note that export takes a **single** `type` field, not a `types` array, and both `startTimeMs` and `endTimeMs` are required.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  thirty_days_ago_ms = now_ms - (30 * 24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/export/countReports",
      headers=headers,
      json={
          "scope": "LOCATION",
          "uuidList": ["YOUR_LOCATION_UUID"],
          "type": "PEOPLE",
          "interval": "DAILY",
          "startTimeMs": thirty_days_ago_ms,
          "endTimeMs": now_ms,
          "timeZone": "America/Los_Angeles"
      }
  )

  # Response is CSV text, not JSON
  with open("people_count_report.csv", "w") as f:
      f.write(response.text)
  print("Exported report to people_count_report.csv")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const thirtyDaysAgo = now - (30 * 24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/export/countReports', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      scope: 'LOCATION',
      uuidList: ['YOUR_LOCATION_UUID'],
      type: 'PEOPLE',
      interval: 'DAILY',
      startTimeMs: thirtyDaysAgo,
      endTimeMs: now,
      timeZone: 'America/Los_Angeles'
    })
  });

  // Response is CSV text, not JSON
  const csv = await response.text();
  console.log(csv);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/export/countReports \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "scope": "LOCATION",
      "uuidList": ["YOUR_LOCATION_UUID"],
      "type": "PEOPLE",
      "interval": "DAILY",
      "startTimeMs": 1710028800000,
      "endTimeMs": 1712620800000,
      "timeZone": "America/Los_Angeles"
    }' \
    -o people_count_report.csv
  ```
</CodeGroup>

<Note>
  Because the response body is CSV, read it as text (`response.text` / `.text()`) or write it straight to a file with the `-o` flag in cURL. Do not attempt to parse it as JSON.
</Note>

To export raw people-count readings instead of aggregated reports, use `/api/export/peopleCountEvents` with a `startInterval` and `endInterval` (epoch milliseconds). It returns CSV the same way.

## Enum reference

Reports are described by a small set of fixed enums. There is no endpoint that lists these at runtime — the values below are the complete set.

### ReportType

Values accepted by the `types` array (V2) and single `type` field (v1 and export).

| Value             | Counts                              |
| ----------------- | ----------------------------------- |
| `CROWD`           | Crowd-density detections            |
| `PEOPLE`          | People detections / people counting |
| `FACES`           | Face detections                     |
| `MOTION`          | Motion events                       |
| `BANDWIDTH`       | Device bandwidth usage              |
| `VEHICLES`        | Vehicle detections                  |
| `LICENSEPLATES`   | License-plate reads                 |
| `ALERTS`          | Alert / policy events               |
| `AM_VERIFICATION` | Alarm-monitoring verifications      |
| `DWELL`           | Dwell-time detections               |

### ReportInterval

Bucket size for each data point.

| Value           | Bucket         |
| --------------- | -------------- |
| `MINUTELY`      | Per minute     |
| `QUARTERHOURLY` | Per 15 minutes |
| `HOURLY`        | Per hour       |
| `DAILY`         | Per day        |
| `WEEKLY`        | Per week       |
| `MONTHLY`       | Per month      |

### ReportScope

Aggregation level for a count report. Provide a matching `uuid` for `LOCATION`, `DEVICE`, or `REGION`; omit it for `ORG`.

| Value      | Aggregates over         |
| ---------- | ----------------------- |
| `ORG`      | The entire organization |
| `LOCATION` | A single location       |
| `DEVICE`   | A single device         |
| `REGION`   | A configured region     |

### CrossingObject

Object class for `getThresholdCrossingCounts`.

| Value        | Object                   |
| ------------ | ------------------------ |
| `HUMAN`      | People                   |
| `VEHICLE`    | Vehicles                 |
| `FACE`       | Faces                    |
| `LPR`        | License plates           |
| `POSE`       | Pose detections          |
| `CLIP_EMBED` | Visual-embedding matches |
| `UNKNOWN`    | Unclassified             |

## Use cases

* **Foot-traffic dashboards** — chart hourly or daily `PEOPLE` counts per location with `getCountReportV2` to compare stores or track trends over time.
* **Occupancy monitoring** — combine `getMostRecentPeopleCountEvents` (live reading) with `getOccupancyCountsV2` (trend) to show current and historical occupancy on one screen.
* **Entrance and lane counting** — use `getThresholdCrossingCounts` with `crossingObject: "HUMAN"` or `"VEHICLE"` to count people through a doorway or cars through a lane.
* **Scheduled reporting** — run `/api/export/countReports` on a cron and drop the CSV into a BI tool or data warehouse for weekly and monthly reporting.

## Advanced: AI Scene Query analytics

Rhombus also offers **Scene Query**, an AI feature that counts custom, natural-language-defined events (for example, "forklifts without a spotter"). Scene Query is configured through the `/api/scenequery/*` endpoints and reported via `/api/report/getCustomEventsReport`. It is a distinct, licensed capability rather than part of the core reporting workflow above — treat it as an optional extension when standard report types don't capture what you need to measure.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Empty timeSeriesDataPoints or all-zero counts">
    Confirm that the device actually produces the analytic you requested — a camera without people counting enabled returns no `PEOPLE` data. Also verify your time range is in **epoch milliseconds** (not seconds) and that the `scope`/`uuid` pair is correct.
  </Accordion>

  <Accordion title="Buckets are offset from local time">
    Set the `timeZone` field to the relevant IANA zone (for example, `America/Chicago`). Without it, bucket boundaries and `dateLocal` fall on UTC.
  </Accordion>

  <Accordion title="Export request is rejected">
    CSV export requires the `REPORT_ADMINISTRATION` permission. Check the API key's permissions in the Rhombus Console, and remember the export body uses a single `type` field rather than the `types` array used by `getCountReportV2`.
  </Accordion>

  <Accordion title="Export response looks like garbage JSON">
    The export endpoints return `text/csv`, not JSON. Read the response as text or write it to a file rather than calling `.json()`.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Faces & People Counting" icon="users" href="/implementations/faces-people-counting">
    Enroll people, query face events, and dig deeper into people-counting analytics
  </Card>

  <Card title="LPR & Vehicles" icon="car" href="/implementations/lpr-vehicle">
    Query license-plate reads and vehicle detections that feed the vehicle report types
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/overview">
    Explore complete request and response schemas for every report and export endpoint
  </Card>
</CardGroup>
