---
title: Insights API | TestingBot API Documentation
description: 'Read-only analytics over your TestingBot test results: pass/fail trends,
  headline summaries, top errors and per-test flakiness.'
source_url:
  html: https://testingbot.com/support/api/insights
  md: https://testingbot.com/support/api/insights.md
---

# Insights

The data behind the Test Analytics dashboard, exposed so you can build your own reporting.

- **Endpoint:** api.testingbot.com
- **Version:** v1
- **Format:** JSON
- **Auth:** [HTTP Basic](https://testingbot.com/support/api#authentication)

## Insights API

The Insights API exposes read-only analytics over your test results so you can build your own dashboards. It returns the same data that powers the [Test Analytics](https://testingbot.com/members/tests) page in your dashboard: daily pass/fail trends, a headline summary, top failure messages, per-test flakiness, and the filter values to drive it all. For a raw list of individual test executions, use [GET /v1/tests](https://testingbot.com/support/api/tests#tests) instead.

Every endpoint accepts a period via `start` and `end` (ISO-8601 or UNIX timestamps), or the `time_range` shorthand (`7d`, `30d`), defaulting to the last 30 days. Filter with `status`, `browser`, `build`, `group_ids` and `team` (comma-separated IDs discoverable via [GET /v1/insights/filters](https://testingbot.com#insights-filters)). Dates in results follow the server timezone (UTC).

GET `/v1/insights/trends`

## Test trends
 Time-bucketed success / failure / unknown counts for your tests, the same series that powers the Test Analytics chart in the dashboard. Use `group_by` to aggregate by day (default), by browser (coverage), or as a single status roll-up. Filter by date range, status, browser, build, group and team. 
### Arguments

- **`start` string:** Period start. ISO-8601 (2026-06-01 or 2026-06-01T00:00:00Z) or a UNIX timestamp. Defaults to 30 days before `end`.
- **`end` string:** Period end. ISO-8601 or a UNIX timestamp. Defaults to now.
- **`time_range` string:** Relative window as a shorthand for `start`: 24h, 7d, 4w (units h/d/w). Ignored when `start` is given.
- **`status` string:** Filter by test status. One of all (default), success, failure, unknown.
- **`browser` array:** Filter by test environment (browser/OS/device) IDs, comma-separated. Discover IDs via /v1/insights/filters.
- **`build` array:** Filter by build IDs, comma-separated.
- **`group_ids` array:** Filter by group ("My Groups") IDs, comma-separated.
- **`team` array:** Filter by team member user IDs (who ran the test), comma-separated.
- **`name` string:** Filter to an exact test name.
- **`group_by` string:** Aggregation dimension: date (daily buckets, default), browser, or status.

### Response fields

- **`data` array of insight trend bucket objects:** Series buckets, newest first.
- **`meta` insight trend meta object:** —

GET `/v1/insights/trends`
[cURL](https://testingbot.com#) [NodeJS](https://testingbot.com#) [Python](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/insights/trends?group_by=date&time_range=30d" \
-u key:secret
```

```javascript
const auth = Buffer.from(`${key}:${secret}`).toString('base64');
const res = await fetch(
  'https://api.testingbot.com/v1/insights/trends?group_by=date&time_range=30d',
  { headers: { Authorization: `Basic ${auth}` } }
);
const trends = await res.json();
```

```python
import requests
res = requests.get(
  'https://api.testingbot.com/v1/insights/trends',
  params={'group_by': 'date', 'time_range': '30d'},
  auth=(key, secret))
trends = res.json()
```

Response

```json
{
  "data": [
    { "date": "2026-06-30", "success": 8, "failure": 0, "unknown": 0, "total": 8 },
    { "date": "2026-06-26", "success": 2, "failure": 6, "unknown": 0, "total": 8 }
  ],
  "meta": {
    "group_by": "date",
    "start": "2026-06-04T00:00:00Z",
    "end": "2026-07-04T10:37:00Z",
    "status": "all",
    "success": 300, "failure": 190, "unknown": 22, "total": 512,
    "pass_rate": 0.5859
  }
}
```

GET `/v1/insights/summary`

## Test summary
 Headline totals (success, failure, unknown) plus pass and failure rates for the selected period and filters. Ideal for a single-number dashboard tile. 
### Arguments

- **`start` string:** Period start. ISO-8601 (2026-06-01 or 2026-06-01T00:00:00Z) or a UNIX timestamp. Defaults to 30 days before `end`.
- **`end` string:** Period end. ISO-8601 or a UNIX timestamp. Defaults to now.
- **`time_range` string:** Relative window as a shorthand for `start`: 24h, 7d, 4w (units h/d/w). Ignored when `start` is given.
- **`status` string:** Filter by test status. One of all (default), success, failure, unknown.
- **`browser` array:** Filter by test environment (browser/OS/device) IDs, comma-separated. Discover IDs via /v1/insights/filters.
- **`build` array:** Filter by build IDs, comma-separated.
- **`group_ids` array:** Filter by group ("My Groups") IDs, comma-separated.
- **`team` array:** Filter by team member user IDs (who ran the test), comma-separated.
- **`name` string:** Filter to an exact test name.

### Response fields

- **`start` timestamp:** Period start (ISO-8601, UTC).
- **`end` timestamp:** Period end (ISO-8601, UTC).
- **`status` string:** Status filter applied.
- **`total` integer:** Total tests in the period.
- **`success` integer:** Passed tests.
- **`failure` integer:** Failed tests.
- **`unknown` integer:** Unknown-status tests.
- **`pass_rate` number:** success / total, 0..1.
- **`failure_rate` number:** failure / total, 0..1.

GET `/v1/insights/summary`
[cURL](https://testingbot.com#) [NodeJS](https://testingbot.com#) [Python](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/insights/summary?time_range=30d" \
-u key:secret
```

```javascript
const auth = Buffer.from(`${key}:${secret}`).toString('base64');
const res = await fetch(
  'https://api.testingbot.com/v1/insights/summary?time_range=30d',
  { headers: { Authorization: `Basic ${auth}` } }
);
const summary = await res.json();
```

```python
import requests
res = requests.get(
  'https://api.testingbot.com/v1/insights/summary',
  params={'time_range': '30d'},
  auth=(key, secret))
summary = res.json()
```

Response

```json
{
  "start": "2026-06-04T00:00:00Z",
  "end": "2026-07-04T10:37:00Z",
  "status": "all",
  "total": 512,
  "success": 300,
  "failure": 190,
  "unknown": 22,
  "pass_rate": 0.5859,
  "failure_rate": 0.3711
}
```

GET `/v1/insights/errors`

## Top failure messages
 Groups failed tests by their status message and returns the most common failures with occurrence counts. Always operates on failed tests, so the `status` filter is ignored. Paginated with offset/count. 
### Arguments

- **`start` string:** Period start. ISO-8601 (2026-06-01 or 2026-06-01T00:00:00Z) or a UNIX timestamp. Defaults to 30 days before `end`.
- **`end` string:** Period end. ISO-8601 or a UNIX timestamp. Defaults to now.
- **`time_range` string:** Relative window as a shorthand for `start`: 24h, 7d, 4w (units h/d/w). Ignored when `start` is given.
- **`status` string:** Filter by test status. One of all (default), success, failure, unknown.
- **`browser` array:** Filter by test environment (browser/OS/device) IDs, comma-separated. Discover IDs via /v1/insights/filters.
- **`build` array:** Filter by build IDs, comma-separated.
- **`group_ids` array:** Filter by group ("My Groups") IDs, comma-separated.
- **`team` array:** Filter by team member user IDs (who ran the test), comma-separated.
- **`name` string:** Filter to an exact test name.
- **`offset` integer:** Skip this many error groups.
- **`count` integer max=`500`:** Number of error groups to return .

### Response fields

- **`data` array of insight error objects:** Error groups, most frequent first.
- **`meta` insight error meta object:** —

GET `/v1/insights/errors`
[cURL](https://testingbot.com#) [NodeJS](https://testingbot.com#) [Python](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/insights/errors?time_range=7d&count=10" \
-u key:secret
```

```javascript
const auth = Buffer.from(`${key}:${secret}`).toString('base64');
const res = await fetch(
  'https://api.testingbot.com/v1/insights/errors?time_range=7d&count=10',
  { headers: { Authorization: `Basic ${auth}` } }
);
const errors = await res.json();
```

```python
import requests
res = requests.get(
  'https://api.testingbot.com/v1/insights/errors',
  params={'time_range': '7d', 'count': 10},
  auth=(key, secret))
errors = res.json()
```

Response

```json
{
  "data": [
    { "error": "Element not found: #login", "count": 42 },
    { "error": "Timeout after 30s waiting for element", "count": 17 }
  ],
  "meta": {
    "start": "2026-06-27T10:37:00Z",
    "end": "2026-07-04T10:37:00Z",
    "total_failures": 190,
    "distinct_errors": 12,
    "offset": 0,
    "count": 10
  }
}
```

GET `/v1/insights/test-cases`

## Test cases
 Groups your test runs by test name and returns per-test statistics: total runs, success/failure/unknown counts, pass rate, a flaky flag (both passes and failures seen), and average duration in seconds. Sort by total (default), pass\_rate, failure, flaky or avg\_duration. Paginated with offset/count. 
### Arguments

- **`start` string:** Period start. ISO-8601 (2026-06-01 or 2026-06-01T00:00:00Z) or a UNIX timestamp. Defaults to 30 days before `end`.
- **`end` string:** Period end. ISO-8601 or a UNIX timestamp. Defaults to now.
- **`time_range` string:** Relative window as a shorthand for `start`: 24h, 7d, 4w (units h/d/w). Ignored when `start` is given.
- **`status` string:** Filter by test status. One of all (default), success, failure, unknown.
- **`browser` array:** Filter by test environment (browser/OS/device) IDs, comma-separated. Discover IDs via /v1/insights/filters.
- **`build` array:** Filter by build IDs, comma-separated.
- **`group_ids` array:** Filter by group ("My Groups") IDs, comma-separated.
- **`team` array:** Filter by team member user IDs (who ran the test), comma-separated.
- **`name` string:** Filter to an exact test name.
- **`sort` string:** Sort field.
- **`sort_order` string:** Sort direction.
- **`offset` integer:** Skip this many test cases.
- **`count` integer max=`500`:** Number of test cases to return .

### Response fields

- **`data` array of insight test case objects:** Per-test-name statistics.
- **`meta` insight test case meta object:** —

GET `/v1/insights/test-cases`
[cURL](https://testingbot.com#) [NodeJS](https://testingbot.com#) [Python](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/insights/test-cases?sort=flaky&count=20" \
-u key:secret
```

```javascript
const auth = Buffer.from(`${key}:${secret}`).toString('base64');
const res = await fetch(
  'https://api.testingbot.com/v1/insights/test-cases?sort=flaky&count=20',
  { headers: { Authorization: `Basic ${auth}` } }
);
const testCases = await res.json();
```

```python
import requests
res = requests.get(
  'https://api.testingbot.com/v1/insights/test-cases',
  params={'sort': 'flaky', 'count': 20},
  auth=(key, secret))
test_cases = res.json()
```

Response

```json
{
  "data": [
    {
      "name": "Login::testValidLogin",
      "total": 120,
      "success": 110,
      "failure": 8,
      "unknown": 2,
      "pass_rate": 0.9167,
      "flaky": true,
      "avg_duration": 34.2
    }
  ],
  "meta": {
    "start": "2026-06-04T00:00:00Z",
    "end": "2026-07-04T10:37:00Z",
    "total": 87,
    "offset": 0,
    "count": 50,
    "sort": "flaky",
    "sort_order": "desc"
  }
}
```

GET `/v1/insights/filters`

## Available filter values
 Returns the browsers, builds, groups and team members available on your account, so a dashboard can populate its filter dropdowns. The returned IDs are the values to pass to the other Insights endpoints (browser, build, group\_ids, team). 
### Response fields

- **`browsers` array of insight filter option objects:** Test environments used recently (pass ids as `browser`).
- **`builds` array of object:** Builds ({id, identifier}); pass ids as `build`.
- **`groups` array of insight filter option objects:** User-defined groups (pass ids as `group_ids`).
- **`team_members` array of insight filter option objects:** Account owner + team members (pass ids as `team`).
- **`statuses` array of string:** Valid status filter values.

GET `/v1/insights/filters`
[cURL](https://testingbot.com#) [NodeJS](https://testingbot.com#) [Python](https://testingbot.com#)
Request

```bash
$ curl "https://api.testingbot.com/v1/insights/filters" \
-u key:secret
```

```javascript
const auth = Buffer.from(`${key}:${secret}`).toString('base64');
const res = await fetch(
  'https://api.testingbot.com/v1/insights/filters',
  { headers: { Authorization: `Basic ${auth}` } }
);
const filters = await res.json();
```

```python
import requests
res = requests.get(
  'https://api.testingbot.com/v1/insights/filters',
  auth=(key, secret))
filters = res.json()
```

Response

```json
{
  "browsers": [
    { "id": 1234, "name": "Chrome 126, Windows 11" },
    { "id": 1288, "name": "Safari 17, macOS Sonoma" }
  ],
  "builds": [{ "id": 4331, "identifier": "ci-run-42" }],
  "groups": [{ "id": 7, "name": "smoke" }],
  "team_members": [{ "id": 9, "name": "Jane Doe" }],
  "statuses": ["success", "failure", "unknown"]
}
```

[Previous Tests & Builds](https://testingbot.com/support/api/tests) [Next Screenshots](https://testingbot.com/support/api/screenshots)
