> For the complete documentation index, see [llms.txt](https://docs.humblytics.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.humblytics.com/external-analytics-api.md).

# External Analytics API

Our External Analytics API lets you pull Humblytics data programmatically — traffic, pages, clicks, forms, and funnels — using the same property-scoped API keys that power the in-app dashboards. This guide covers authentication, required parameters, endpoints, and typical responses.

> **Base URL**: `https://app.humblytics.com/api/external/v1`

## In-App API Access Page

The Humblytics dashboard includes a dedicated **API Access** page (sidebar → **Utilities** → **API**) that serves as your activation console for the API and AI coding agents.

The page walks you through a four-step guided flow:

1. **Generate key** — create a property-scoped API key (shown once at creation)
2. **Pick your agent** — copy a secure install prompt for Claude Code, Cursor, or a generic agent
3. **Install the skills** — copy a setup prompt to install all 12 [humblytics-marketing-skills](https://github.com/Humblytics/humblytics-marketing-skills) from GitHub
4. **Verify it works** — run a live `GET /traffic/summary` test and confirm your connection

A sticky **Your setup** pane on the right keeps your Property ID, Base URL, and one-click copy actions (install prompt, skills setup, first test command) always visible. Below the steps you will find a reference curl example and a collapsible endpoint list grouped by the CRO loop (Read → Decide → Ship → Onboard).

See [API Access & Agent Setup](/api-access-and-agents.md) for the full walkthrough, skills catalog, security practices, and workflow examples.

***

## Authentication

* Generate an API key for your property in the Humblytics app (sidebar → **Utilities** → **API**).
* Include the key in every request using the `Authorization` header:

```http
Authorization: Bearer <your_api_key>
```

* Keys are property-scoped. The `propertyId` in the request path must match the property linked to the API key, otherwise the API returns `403`.
* Ensure the key has the `metrics` permission enabled.

## API Access by Plan

API key management is available on the **Plus** plan and above. Generate API keys from the API Access page under **Utilities** in the sidebar.

* **Plus, Business, Scale**: API access included
* **Enterprise**: Full API access with custom endpoints and priority support

## Versioning

All external endpoints live under `/api/external/v1`. Future versions will be published side-by-side (for example, `/api/external/v2`) so you can migrate when ready.

## Common Parameters

| Name       | Type   | Required              | Notes                                                                                                           |
| ---------- | ------ | --------------------- | --------------------------------------------------------------------------------------------------------------- |
| `start`    | string | Yes                   | ISO-8601 timestamp or date (e.g. `2024-05-01` or `2024-05-01T00:00:00Z`).                                       |
| `end`      | string | Yes                   | ISO-8601 timestamp or date that occurs after `start`.                                                           |
| `timezone` | string | No                    | IANA zone name (defaults to `UTC`). Determines bucket boundaries and how timestamps are formatted in responses. |
| `limit`    | number | No                    | Maximum results to return (default: 50).                                                                        |
| `page`     | string | For details endpoints | URL path to filter (e.g. `/pricing`). Required for detail endpoints.                                            |
| `source`   | string | No                    | Filter forms by source.                                                                                         |

Requests that cannot be parsed—invalid dates, unsupported timezones, `end` before `start`, ranges that are too large—return `400` with a descriptive error payload.

***

## Traffic Trends

```
GET /properties/{propertyId}/traffic/trends
```

Returns time-series metrics for page views and unique visitors within a specified range.

### Query Parameters

| Name          | Type | Required | Default | Notes                                            |
| ------------- | ---- | -------- | ------- | ------------------------------------------------ |
| `granularity` | enum | No       | `day`   | Accepted values: `hour`, `day`, `week`, `month`. |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/traffic/trends?start=2024-05-01&end=2024-05-07&granularity=day&timezone=America/New_York"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T04:00:00.000Z",
    "end": "2024-05-07T03:59:59.000Z",
    "granularity": "day",
    "timezone": "America/New_York",
    "bucket_count": 7
  },
  "data": [
    {
      "bucket_start": "2024-05-01T00:00:00-04:00",
      "bucket_end": "2024-05-01T23:59:59-04:00",
      "page_views": 1523,
      "unique_visitors": 682
    }
  ],
  "summary": {
    "page_views": 9056,
    "unique_visitors": 3142
  }
}
```

### Notes

* Buckets include zero-filled entries when no activity occurred so charting remains continuous.
* Maximum of 500 buckets per request. Very granular windows (for example, hourly over multiple months) return `400`.
* The API excludes known bots automatically to align with the dashboard totals.

***

## Traffic Summary

```
GET /properties/{propertyId}/traffic/summary
```

Returns aggregate traffic metrics for a specified range, including total page views, sessions, bounce rate, and average session duration.

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/traffic/summary?start=2024-05-01&end=2024-05-07&timezone=America/New_York"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T04:00:00.000Z",
    "end": "2024-05-07T03:59:59.000Z",
    "timezone": "America/New_York"
  },
  "data": {
    "page_views": 9056,
    "sessions": 3142,
    "unique_visitors": 2418,
    "bounce_rate": 0.423,
    "avg_session_duration": 184.5
  }
}
```

### Notes

* `bounce_rate` is expressed as a decimal (e.g. `0.423` = 42.3%).
* `avg_session_duration` is in seconds.
* Bot traffic is excluded automatically.

***

## Traffic Realtime

```
GET /properties/{propertyId}/traffic/realtime
```

Returns the current live visitor count and a feed of recent visitor activity. This endpoint does **not** require `start`, `end`, or `timezone` parameters.

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/traffic/realtime"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID"
  },
  "data": {
    "active_visitors": 23,
    "feed": [
      {
        "page": "/pricing",
        "referrer": "google",
        "device": "desktop",
        "country": "US",
        "timestamp": "2024-05-07T14:32:18.000Z"
      }
    ]
  }
}
```

### Notes

* This endpoint returns a snapshot of current activity — no date range parameters are needed.
* The `feed` array shows the most recent visitor events in reverse chronological order.
* `active_visitors` reflects sessions active within the last few minutes.

***

## Traffic Breakdown

```
GET /properties/{propertyId}/traffic/breakdown
```

Returns the top traffic segments (UTM attributes, countries, devices, landing pages, and referrers) for a specified range.

### Query Parameters

| Name    | Type   | Required | Default | Notes                                                      |
| ------- | ------ | -------- | ------- | ---------------------------------------------------------- |
| `limit` | number | No       | 10      | Maximum entries per segment (maximum supported value: 50). |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/traffic/breakdown?start=2024-05-01T00:00:00Z&end=2024-05-31T23:59:59Z&timezone=UTC&limit=20"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-31T23:59:59.000Z",
    "timezone": "UTC",
    "limit": 20,
    "totals": {
      "sessions": 1982,
      "page_views": 5478
    }
  },
  "data": {
    "utm": [
      {
        "source": "google",
        "medium": "cpc",
        "campaign": "spring_launch",
        "sessions": 412,
        "page_views": 921,
        "share": 0.208
      }
    ],
    "countries": [
      {
        "country": "US",
        "sessions": 982,
        "page_views": 2015,
        "share": 0.495
      }
    ],
    "devices": [
      {
        "device": "desktop",
        "sessions": 1045,
        "page_views": 2684,
        "share": 0.527
      }
    ],
    "landing_pages": [
      {
        "path": "/pricing",
        "sessions": 213,
        "page_views": 425,
        "share": 0.107
      }
    ],
    "referrers": [
      {
        "referrer": "google",
        "sessions": 643,
        "page_views": 1580,
        "share": 0.324
      }
    ]
  }
}
```

### Notes

* `share` represents the fraction of total sessions contributed by each row.
* Null or missing values are returned as `"unknown"` so you do not need to special-case missing fields.
* Device values are normalized (`desktop`, `mobile`, `unknown`) using Humblytics’ device classification.

***

## Traffic Entry & Exit Pages

```
GET /properties/{propertyId}/traffic/entry-exit-pages
```

Returns the top entry pages (where sessions begin) and exit pages (where sessions end) for a specified range.

### Query Parameters

| Name    | Type   | Required | Default | Notes                                                   |
| ------- | ------ | -------- | ------- | ------------------------------------------------------- |
| `limit` | number | No       | 10      | Maximum entries per list (maximum supported value: 50). |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/traffic/entry-exit-pages?start=2024-05-01&end=2024-05-31&timezone=UTC&limit=10"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-31T23:59:59.000Z",
    "timezone": "UTC",
    "limit": 10
  },
  "data": {
    "entry_pages": [
      {
        "path": "/",
        "sessions": 982,
        "share": 0.495
      },
      {
        "path": "/pricing",
        "sessions": 312,
        "share": 0.157
      }
    ],
    "exit_pages": [
      {
        "path": "/pricing",
        "sessions": 534,
        "share": 0.269
      },
      {
        "path": "/blog",
        "sessions": 289,
        "share": 0.146
      }
    ]
  }
}
```

### Notes

* `share` represents the fraction of total sessions for each entry or exit page.
* Entry pages indicate where visitors first land; exit pages indicate the last page viewed before leaving.

***

## Pages Breakdown

```
GET /properties/{propertyId}/pages/breakdown
```

Returns performance metrics for all pages, including views, unique visitors, average scroll depth, and bounce rate.

### Query Parameters

| Name    | Type   | Required | Default | Notes                                                    |
| ------- | ------ | -------- | ------- | -------------------------------------------------------- |
| `limit` | number | No       | 10      | Maximum entries to return (maximum supported value: 50). |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/pages/breakdown?start=2024-05-01&end=2024-05-31&timezone=UTC&limit=20"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-31T23:59:59.000Z",
    "timezone": "UTC",
    "limit": 20
  },
  "data": [
    {
      "path": "/",
      "page_views": 3245,
      "unique_visitors": 2108,
      "avg_scroll_depth": 0.62,
      "bounce_rate": 0.38
    },
    {
      "path": "/pricing",
      "page_views": 1823,
      "unique_visitors": 1456,
      "avg_scroll_depth": 0.74,
      "bounce_rate": 0.29
    }
  ]
}
```

### Notes

* `avg_scroll_depth` is a decimal representing the average percentage of the page scrolled (e.g. `0.62` = 62%).
* `bounce_rate` is page-level, not site-level.
* Results are sorted by `page_views` in descending order by default.

***

## Pages Details

```
GET /properties/{propertyId}/pages/details
```

Returns a deep dive for a single page, including UTM attribution, device breakdown, and country breakdown.

### Query Parameters

| Name    | Type   | Required | Default | Notes                                           |
| ------- | ------ | -------- | ------- | ----------------------------------------------- |
| `page`  | string | Yes      | N/A     | The page path to get details for (URL-encoded). |
| `limit` | number | No       | 10      | Maximum entries per breakdown (maximum: 50).    |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/pages/details?page=%2Fpricing&start=2024-05-01&end=2024-05-31&timezone=UTC"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "page": "/pricing",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-31T23:59:59.000Z",
    "timezone": "UTC"
  },
  "data": {
    "page_views": 1823,
    "unique_visitors": 1456,
    "avg_scroll_depth": 0.74,
    "bounce_rate": 0.29,
    "utm": [
      {
        "source": "google",
        "medium": "cpc",
        "campaign": "spring_launch",
        "page_views": 412,
        "share": 0.226
      }
    ],
    "devices": [
      {
        "device": "desktop",
        "page_views": 1102,
        "share": 0.604
      }
    ],
    "countries": [
      {
        "country": "US",
        "page_views": 845,
        "share": 0.463
      }
    ]
  }
}
```

### Notes

* Use URL encoding for the `page` parameter (e.g. `/pricing page` becomes `%2Fpricing%20page`).
* Breakdowns (UTM, devices, countries) are specific to the requested page.
* Combines aggregate page metrics with dimensional breakdowns in a single response.

***

## Clicks Breakdown

```
GET /properties/{propertyId}/clicks/breakdown
```

Returns aggregated click event data grouped by page and click target, along with trend data over time.

### Query Parameters

| Name          | Type   | Required | Default | Notes                                                      |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------- |
| `granularity` | enum   | No       | `day`   | Accepted values: `hour`, `day`, `week`, `month`.           |
| `limit`       | number | No       | 10      | Maximum entries per segment (maximum supported value: 50). |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/clicks/breakdown?start=2024-05-01&end=2024-05-07&granularity=day&timezone=UTC&limit=20"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-07T23:59:59.000Z",
    "timezone": "UTC",
    "granularity": "day",
    "limit": 20,
    "bucket_count": 7
  },
  "data": [
    {
      "page": "/pricing",
      "target": "Get Started Button",
      "clicks": 342,
      "unique_clicks": 289
    },
    {
      "page": "/home",
      "target": "Sign Up Link",
      "clicks": 128,
      "unique_clicks": 115
    }
  ],
  "trend": [
    {
      "bucket_start": "2024-05-01T00:00:00.000Z",
      "bucket_end": "2024-05-01T23:59:59.000Z",
      "clicks": 412,
      "unique_clicks": 352
    }
  ],
  "summary": {
    "total_clicks": 2849,
    "total_unique_clicks": 2341
  }
}
```

### Notes

* Returns both page-level click aggregations and time-series trend data in a single response.
* Click targets are automatically extracted from tracked click events.
* `unique_clicks` counts distinct sessions that performed the click action.

***

## Clicks Details

```
GET /properties/{propertyId}/clicks/details
```

Returns detailed click event breakdown for a specific page, showing which elements were clicked.

### Query Parameters

| Name          | Type   | Required | Default | Notes                                                |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------- |
| `page`        | string | Yes      | N/A     | The page path to get click details for (URL-encoded) |
| `granularity` | enum   | No       | `day`   | Accepted values: `hour`, `day`, `week`, `month`.     |
| `limit`       | number | No       | 10      | Maximum entries to return (maximum: 50).             |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/clicks/details?page=%2Fpricing&start=2024-05-01&end=2024-05-07&granularity=day&timezone=UTC&limit=20"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "page": "/pricing",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-07T23:59:59.000Z",
    "timezone": "UTC",
    "granularity": "day",
    "limit": 20,
    "bucket_count": 7
  },
  "data": {
    "clicks": [
      {
        "target": "Get Started Button",
        "clicks": 342,
        "unique_clicks": 289,
        "share": 0.473
      },
      {
        "target": "Learn More Link",
        "clicks": 128,
        "unique_clicks": 115,
        "share": 0.177
      }
    ]
  },
  "summary": {
    "total_clicks": 723,
    "total_unique_clicks": 615
  }
}
```

### Notes

* Use URL encoding for the `page` parameter (e.g., `/pricing page` becomes `%2Fpricing%20page`).
* `share` represents the proportion of total clicks on that page attributed to each target.
* Returns only clicks that occurred on the specified page.

***

## Forms Breakdown

```
GET /properties/{propertyId}/forms/breakdown
```

Returns aggregated form submission data grouped by page and form target, along with trend data over time.

### Query Parameters

| Name          | Type   | Required | Default | Notes                                                      |
| ------------- | ------ | -------- | ------- | ---------------------------------------------------------- |
| `granularity` | enum   | No       | `day`   | Accepted values: `hour`, `day`, `week`, `month`.           |
| `limit`       | number | No       | 10      | Maximum entries per segment (maximum supported value: 50). |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/forms/breakdown?start=2024-05-01&end=2024-05-07&granularity=day&timezone=UTC&limit=20"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-07T23:59:59.000Z",
    "timezone": "UTC",
    "granularity": "day",
    "limit": 20,
    "bucket_count": 7
  },
  "data": [
    {
      "page": "/contact",
      "target": "Contact Form",
      "submissions": 89,
      "unique_submissions": 82
    },
    {
      "page": "/signup",
      "target": "Registration Form",
      "submissions": 156,
      "unique_submissions": 147
    }
  ],
  "trend": [
    {
      "bucket_start": "2024-05-01T00:00:00.000Z",
      "bucket_end": "2024-05-01T23:59:59.000Z",
      "submissions": 34,
      "unique_submissions": 31
    }
  ],
  "summary": {
    "total_submissions": 245,
    "total_unique_submissions": 229
  }
}
```

### Notes

* Returns both page-level submission aggregations and time-series trend data in a single response.
* Form targets are automatically extracted from tracked form submission events.
* `unique_submissions` counts distinct sessions that submitted a form.

***

## Forms Details

```
GET /properties/{propertyId}/forms/details
```

Returns detailed form submission breakdown for a specific page, showing which forms were submitted.

### Query Parameters

| Name          | Type   | Required | Default | Notes                                               |
| ------------- | ------ | -------- | ------- | --------------------------------------------------- |
| `page`        | string | Yes      | N/A     | The page path to get form details for (URL-encoded) |
| `granularity` | enum   | No       | `day`   | Accepted values: `hour`, `day`, `week`, `month`.    |
| `limit`       | number | No       | 10      | Maximum entries to return (maximum: 50).            |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/forms/details?page=%2Fcontact&start=2024-05-01&end=2024-05-07&granularity=day&timezone=UTC&limit=20"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "page": "/contact",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-07T23:59:59.000Z",
    "timezone": "UTC",
    "granularity": "day",
    "limit": 20,
    "bucket_count": 7
  },
  "data": {
    "forms": [
      {
        "target": "Contact Form",
        "submissions": 89,
        "unique_submissions": 82,
        "share": 0.687
      },
      {
        "target": "Newsletter Signup",
        "submissions": 41,
        "unique_submissions": 39,
        "share": 0.313
      }
    ]
  },
  "summary": {
    "total_submissions": 130,
    "total_unique_submissions": 121
  }
}
```

### Notes

* Use URL encoding for the `page` parameter (e.g., `/contact us` becomes `%2Fcontact%20us`).
* `share` represents the proportion of total form submissions on that page attributed to each form.
* Returns only form submissions that occurred on the specified page.

***

## Funnels

```
GET /properties/{propertyId}/funnels
```

Runs a funnel query across a defined sequence of steps, returning conversion rates between each step.

### Query Parameters

| Name          | Type   | Required | Default     | Notes                                                                                 |
| ------------- | ------ | -------- | ----------- | ------------------------------------------------------------------------------------- |
| `steps`       | JSON   | Yes      | N/A         | JSON array of funnel step definitions (URL-encoded).                                  |
| `mode`        | enum   | No       | `unbounded` | `unbounded` (steps in any order) or `sequential` (steps must occur in defined order). |
| `breakdownBy` | string | No       | N/A         | Optional dimension to break results down by (e.g. `device`, `country`, `utm_source`). |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/funnels?start=2024-05-01&end=2024-05-31&timezone=UTC&steps=%5B%7B%22page%22%3A%22%2F%22%7D%2C%7B%22page%22%3A%22%2Fpricing%22%7D%2C%7B%22page%22%3A%22%2Fsignup%22%7D%5D&mode=sequential"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-31T23:59:59.000Z",
    "timezone": "UTC",
    "mode": "sequential"
  },
  "data": {
    "steps": [
      {
        "step": 1,
        "page": "/",
        "sessions": 3142,
        "conversion_rate": 1.0
      },
      {
        "step": 2,
        "page": "/pricing",
        "sessions": 1256,
        "conversion_rate": 0.4
      },
      {
        "step": 3,
        "page": "/signup",
        "sessions": 314,
        "conversion_rate": 0.25
      }
    ],
    "overall_conversion_rate": 0.1
  }
}
```

### Notes

* The `steps` parameter must be a JSON-encoded array. URL-encode it when passing as a query parameter.
* `conversion_rate` at each step is relative to the previous step. `overall_conversion_rate` is step 1 → last step.
* Use `mode=sequential` when order matters (e.g. homepage → pricing → signup). Use `unbounded` for unordered funnels.

***

## Funnels Sankey

```
GET /properties/{propertyId}/funnels/sankey
```

Returns path flow data for a funnel in a Sankey diagram format, showing how sessions move between steps.

### Query Parameters

Accepts all the same parameters as the `/funnels` endpoint, plus:

| Name          | Type   | Required | Default | Notes                                        |
| ------------- | ------ | -------- | ------- | -------------------------------------------- |
| `maxPaths`    | number | No       | 20      | Maximum number of paths to return.           |
| `minSessions` | number | No       | 1       | Minimum sessions a path must have to appear. |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/funnels/sankey?start=2024-05-01&end=2024-05-31&timezone=UTC&steps=%5B%7B%22page%22%3A%22%2F%22%7D%2C%7B%22page%22%3A%22%2Fpricing%22%7D%2C%7B%22page%22%3A%22%2Fsignup%22%7D%5D&mode=sequential&maxPaths=10&minSessions=5"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "start": "2024-05-01T00:00:00.000Z",
    "end": "2024-05-31T23:59:59.000Z",
    "timezone": "UTC",
    "mode": "sequential",
    "maxPaths": 10,
    "minSessions": 5
  },
  "data": {
    "paths": [
      {
        "nodes": ["/", "/pricing", "/signup"],
        "sessions": 245
      },
      {
        "nodes": ["/", "/pricing", "(drop-off)"],
        "sessions": 892
      },
      {
        "nodes": ["/", "(drop-off)"],
        "sessions": 1024
      }
    ]
  }
}
```

### Notes

* `(drop-off)` nodes indicate where sessions exited the funnel.
* Use `maxPaths` and `minSessions` to control the granularity of the output.
* Useful for visualizing where users leave the funnel and which alternative paths they take.

***

## Funnels Suggestions

```
GET /properties/{propertyId}/funnels/suggestions
```

Returns AI-generated funnel suggestions for a specific page, based on traffic patterns and user behavior.

### Query Parameters

| Name   | Type   | Required | Default | Notes                                        |
| ------ | ------ | -------- | ------- | -------------------------------------------- |
| `page` | string | Yes      | N/A     | The page path to get funnel suggestions for. |

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/funnels/suggestions?page=/pricing"
```

### Sample Response

```json
{
  "meta": {
    "property_id": "PROPERTY_ID",
    "page": "/pricing"
  },
  "data": [
    {
      "name": "Pricing to Signup Flow",
      "steps": [
        { "page": "/pricing" },
        { "page": "/signup" },
        { "page": "/welcome" }
      ],
      "rationale": "62% of signups visit the pricing page first. This funnel tracks the primary conversion path."
    }
  ]
}
```

### Notes

* Suggestions are based on your actual traffic data, not generic templates.
* Each suggestion includes a human-readable `rationale` explaining why the funnel is recommended.
* Use these suggestions as a starting point — you can modify the steps before saving.

***

## Saved Funnels

### List Saved Funnels

```
GET /properties/{propertyId}/saved-funnels
```

Returns all saved funnel configurations for the property.

### Sample Request

```bash
curl \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/saved-funnels"
```

### Sample Response

```json
{
  "data": [
    {
      "id": "funnel_abc123",
      "name": "Homepage to Signup",
      "steps": [
        { "page": "/" },
        { "page": "/pricing" },
        { "page": "/signup" }
      ],
      "created_at": "2024-05-01T10:00:00.000Z"
    }
  ]
}
```

### Create or Update a Saved Funnel

```
POST /properties/{propertyId}/saved-funnels
```

Creates a new saved funnel configuration. Include `id` in the body to update an existing funnel.

### Request Body

| Field   | Type   | Required | Notes                                            |
| ------- | ------ | -------- | ------------------------------------------------ |
| `id`    | string | No       | Include to update an existing saved funnel.      |
| `name`  | string | Yes      | A descriptive name for the funnel.               |
| `steps` | array  | Yes      | Array of step objects, each with a `page` field. |

### Sample Request

```bash
curl -X POST \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Homepage to Signup",
    "steps": [
      { "page": "/" },
      { "page": "/pricing" },
      { "page": "/signup" }
    ]
  }' \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/saved-funnels"
```

### Sample Response (201 Created)

```json
{
  "id": "funnel_abc123",
  "name": "Homepage to Signup",
  "steps": [
    { "page": "/" },
    { "page": "/pricing" },
    { "page": "/signup" }
  ],
  "created_at": "2024-05-01T10:00:00.000Z"
}
```

### Delete a Saved Funnel

```
DELETE /properties/{propertyId}/saved-funnels/{funnelId}
```

Deletes a saved funnel configuration.

### Sample Request

```bash
curl -X DELETE \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  "https://app.humblytics.com/api/external/v1/properties/PROPERTY_ID/saved-funnels/funnel_abc123"
```

### Notes

* Deleting a saved funnel does not affect historical funnel query results.
* Saved funnels are property-scoped — they are visible to all API keys for the same property.

***

## Multi-Property Aggregate

These `POST` endpoints let you query data across multiple properties in a single request. Send a JSON body with `{ "propertyIds": [...] }` along with the same query parameters used by the corresponding single-property endpoints.

All aggregate endpoints require the API key to have access to every property listed in the request.

| Endpoint                                              | Description                                        |
| ----------------------------------------------------- | -------------------------------------------------- |
| `POST /properties/aggregate/traffic/trends`           | Aggregate traffic trends across properties.        |
| `POST /properties/aggregate/traffic/summary`          | Aggregate traffic summary across properties.       |
| `POST /properties/aggregate/traffic/breakdown`        | Aggregate traffic breakdowns across properties.    |
| `POST /properties/aggregate/traffic/realtime`         | Aggregate realtime visitor data across properties. |
| `POST /properties/aggregate/traffic/entry-exit-pages` | Aggregate entry/exit pages across properties.      |
| `POST /properties/aggregate/clicks/breakdown`         | Aggregate click data across properties.            |
| `POST /properties/aggregate/forms/breakdown`          | Aggregate form submission data across properties.  |

### Sample Request

```bash
curl -X POST \
  -H "Authorization: Bearer $HUMBLYTICS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "propertyIds": ["prop_abc123", "prop_def456"]
  }' \
  "https://app.humblytics.com/api/external/v1/properties/aggregate/traffic/summary?start=2024-05-01&end=2024-05-31&timezone=UTC"
```

### Notes

* Response format matches the corresponding single-property endpoint, with data aggregated across all specified properties.
* The `meta` object will include a `property_ids` array instead of a single `property_id`.
* The realtime aggregate endpoint does not require date parameters, same as the single-property version.

***

## Errors

| Status | Code              | When it happens                                                                       |
| ------ | ----------------- | ------------------------------------------------------------------------------------- |
| `400`  | `invalid_request` | Bad dates, unsupported timezone or granularity, ranges that are too large.            |
| `401`  | `unauthorized`    | Missing or invalid API key header.                                                    |
| `403`  | `forbidden`       | Property ID does not match the API key or the key does not have `metrics` permission. |
| `429`  | `rate_limited`    | Too many requests in a short window (limits will evolve with usage).                  |
| `500`  | `internal_error`  | Unexpected server error. Retry later or contact support.                              |

Error payloads follow this structure:

```json
{
  "error": {
    "code": "invalid_request",
    "message": "Unsupported granularity: minute",
    "details": {
      "field": "granularity"
    }
  }
}
```

***

## Best Practices

* Store API keys securely (environment variables or a secret manager) and rotate them periodically.
* Use the `timezone` parameter to align data with the local reporting context you care about.
* Cache responses when possible—trend and breakdown data only changes when new traffic arrives.
* Start with coarser granularity (e.g. `day`) for large ranges, then request narrower windows for detailed analysis.
* Use the **Multi-Property Aggregate** endpoints to consolidate reporting across multiple sites without making separate requests per property.
* Save frequently-used funnel definitions with the **Saved Funnels** endpoints so they can be re-run without redefining steps each time.
* **Looking for A/B testing endpoints?** See the [Split Testing API](/split-testing-api.md) to get AI-powered test recommendations, create no-code experiments, and manage running tests programmatically.
