---
title: "Get a form's insights"
method: GET
path: "/api/v1/manage/forms/{form}/insights"
tags: ["Insights"]
---

# Get a form's insights

`GET /api/v1/manage/forms/{form}/insights`

## Request

- Base URL: `https://fillo.so`
- URL: `https://fillo.so/api/v1/manage/forms/{form}/insights`
- Auth: HTTP bearer

The numbers the dashboard's Insights page shows, from the same core: totals, median completion time, seven-day change, the daily timeline, source and surface breakdowns, the drop-off funnel, open drafts, and every question's distribution. Filters use the same grammar as the responses list, so the numbers and the rows always describe the same set. Accepted responses only. Every question's distribution quotes respondent answers verbatim as labels, so this is a response read wearing an analytics shape: it needs forms:read AND responses:read, the second asserted after authentication and named in its own 403.

## Path parameters

- `form` string, required

## Query parameters

- `range` '7d' | '30d' | '90d' | 'all'
- `q` string
- `source` string
- `respondent` string
- `where` string[]
- `by` string
- `op` 'eq' | 'answered' | 'not_answered'
- `eq` string

## Response `200`

The form's insights for the requested window and filters.

- FormInsights: The same computation the dashboard's Insights page renders. Epoch-millisecond timestamps.
  - `range` '7d' | '30d' | '90d' | 'all', required
  - `total` integer, required
  - `firstAt` integer, nullable
  - `lastAt` integer, nullable
  - `medianDurationMs` integer, nullable
  - `durationCount` integer
  - `lastSevenDays` integer
  - `previousSevenDays` integer
  - `sevenDayChange` number, nullable
  - `sampled` boolean
  - `versionCount` integer
  - `legacyHistoryIncomplete` boolean
  - `timeline` object[], required
    - `day` string, required
    - `count` integer, required
  - `sources` InsightBreakdownRow[], required
    - `key` string, required
    - `label` string, required
    - `count` integer, required
    - `pct` number, required
  - `surfaces` InsightBreakdownRow[], required
    - `key` string, required
    - `label` string, required
    - `count` integer, required
    - `pct` number, required
  - `funnel` object, nullable: started, completed, excluded, completionRate, multiPage, and a per-page reached/pct list.
  - `drafts` object, nullable: open, identified, and byPage — the same counts the drafts endpoint returns.
  - `fields` object[], required: One entry per field ever answered: id, label, kind, inCurrentSchema, answered, skipped, fillRate, and a `summary` discriminated on `type` (choice, multi, ranking, scale, number, boolean, matrix, text, date, file, generic).
  - `segment` object, nullable: Present when `by` is supplied: the cohort's size, share, its own `fields`, and the `differences` that separate it from the baseline.
  - `segmentIgnored` boolean: True when `by` named a field the current data cannot segment on.

## Other responses

- `400`: Invalid request (e.g. a body on a GET/DELETE, or a missing required query parameter).
- `401`: Missing, malformed, unknown, revoked, or expired key.
- `403`: The key is valid but lacks the required scope.
- `404`: No such resource in this project (returned instead of 403 for ids in other projects).
- `429`: Per-key (120/min), per-workspace (240/min), or per-IP (300/min) rate limit exceeded. Retry after the Retry-After header.

---

[API](https://skmtc.dev/fillo/apis/fillo-management-api.md) · [All operations](https://skmtc.dev/fillo/apis/fillo-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fillo/apis/fillo-management-api/revisions/867f943f04f5?raw)
