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

# Reports API

> The numbers on the OrbitForms Reports page from code or an AI agent: pipeline by stage, win rate, stage conversion, time in stage, deals created and won, activity by rep and lead response time, with the records behind every number.

The **Reports** page in OrbitForms is one fixed sales dashboard. Every report on it is available here with the same filters and the same definitions, and so is the list of deals, activities or contacts behind any number. The [MCP server](https://docs.orbitforms.ai/mcp/tools.md) exposes the same numbers through one tool, `get_sales_report`.

> [!NOTE]
>
> **Numbers follow the credential owner's record access.** A rep limited to their own records gets their own numbers, exactly as on the Reports page. Records in Recently deleted never count.

## Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/api/v1/reports/sales/:report` | One report: `pipeline`, `win_rate`, `conversion`, `stage_time`, `deal_flow`, `activity` or `response`. Answers `{ data, previous? }`; `data.period` is the range it covers |
| `GET` | `/api/v1/reports/sales/:report/rows` | The records behind one number, newest first (`page`, `per_page` up to 100). Answers `{ data, meta: { kind, total, page, per_page, total_pages, currency, period } }`; `kind` is `deals`, `activities` or `contacts` |

## Scopes

Each report needs the read scope of the data it summarizes: `deals:read` for `pipeline`, `win_rate`, `conversion`, `stage_time` and `deal_flow`; `activities:read` for `activity`; `contacts:read` for `response`.

## Filters

| Parameter | Description |
| - | - |
| `period` | `last_7_days`, `last_30_days`, `last_90_days`, `this_week`, `last_week`, `this_month`, `last_month`, `this_quarter` (default), `last_quarter`, `this_year`, `last_year` or `custom`. Quarters and years follow the fiscal year (`fiscal_year_start_month` in the deal settings) |
| `from`, `to` | A custom range: inclusive dates, `YYYY-MM-DD` (implies `period=custom`) |
| `time_zone` | IANA time zone for days and periods, e.g. `America/New_York` (default `UTC`) |
| `interval` | `day`, `week` (from Monday), `month` or `quarter`; chosen from the range when left out |
| `pipeline_id` | One pipeline (the deal reports) |
| `owner_id` | A deal or contact owner, or the rep who did the activity: user IDs or `me` (repeat, or comma-separate) |
| `group_id` | A team (member group): its members' records |
| `compare` | `true` adds `previous`: the same report for the period before. A running period ("this month") is compared with the same stretch of the one before |

```bash theme={null}
curl "https://orbitforms.ai/api/v1/reports/sales/win_rate?period=last_quarter&time_zone=America/New_York&compare=true" \
  -H "Authorization: Bearer $ORBIT_API_KEY"
```

```json theme={null}
{
  "data": {
    "report": "win_rate",
    "totals": { "won": 12, "lost": 18, "won_amount": 184000, "lost_amount": 251000, "win_rate": 0.4, "average_won_amount": 15333.33, "average_days_to_close": 34.5, "other_currency_count": 0 },
    "by_owner": [ { "owner_id": "4a3c…", "name": "Rex Ortega", "email": "rex@acme.com", "won": 5, "lost": 4, "won_amount": 72000, "win_rate": 0.5556 } ],
    "by_period": [ { "period": "2026-07-01", "won": 4, "lost": 7, "won_amount": 51000, "win_rate": 0.3636 } ],
    "range": { "from": "2026-07-01T04:00:00Z", "to": "2026-10-01T04:00:00Z", "time_zone": "America/New_York", "interval": "week" },
    "currency": "USD",
    "fiscal_year_start_month": 1,
    "period": { "preset": "last_quarter", "start_date": "2026-07-01", "end_date": "2026-09-30" }
  },
  "previous": { "totals": { "won": 9, "lost": 17, "win_rate": 0.3462 }, "period": { "start_date": "2026-04-01", "end_date": "2026-06-30" } }
}
```

## Definitions

Amounts are in the workspace's default deal currency; deals in another currency are counted, their amounts left out and counted in `other_currency_count`. Rates are fractions (`0.4` is 40%), `null` when there is nothing to divide by. Durations are seconds.

| Report | What it measures |
| - | - |
| `pipeline` | Open deals right now, per open stage: `deal_count`, `amount`, and `weighted_amount` (amount × the stage's probability ÷ 100). A snapshot: the date range doesn't apply |
| `win_rate` | Deals closed in the period, by the day they closed: won ÷ (won + lost). Also per owner and per period, the average won amount, and the average of each won deal's whole days from creation to close |
| `conversion` | Per open stage: the deals that **first** entered it in the period (`entered`), how many of them later entered the next stage (`to_next`; after the last open stage, the won stage) and how many were later won (`to_won`, in a won stage of the same pipeline). Re-entering a stage never counts a deal twice; skipping the next stage doesn't count as moving to it |
| `stage_time` | The same deals per stage, and the time each spent in it, every visit added up (the time the deal page shows): `average_seconds`, `median_seconds`, and `in_stage_now` (still there; their time counts to now) |
| `deal_flow` | Deals created in the period and deals won in it, per period and per `source` (`manual`, `workflow`, `import`, `api`) |
| `activity` | Per rep: emails sent (one-to-one, sequence, and logged or synced outbound emails), calls (dialer calls that connected, were busy or unanswered, and logged calls), meetings (booked meetings that have started, and logged meetings) and tasks completed. Only activity on records the credential owner can open counts. Email synced from Gmail or Outlook follows the same visibility rule as the [activities API](https://docs.orbitforms.ai/developers/api/crm.md) |
| `response` | Contacts created in the period (imports left out), from creation to the first outreach by a person: a one-to-one email (including one an agent sends as a person through the API or MCP), a dialer call, or a logged or synced outbound email, call or text (automated sequence and workflow sends don't count; synced email follows the activities API's visibility rule). Per owner: `leads`, `contacted`, `not_contacted`, `median_seconds`, `average_seconds` |

## Rows behind a number

Pass the report's filters plus what the number is about:

| Report | Parameters |
| - | - |
| `pipeline` | `stage_id`, `owner` |
| `win_rate` | `status` (`won` or `lost`), `owner`, `period_start` |
| `deal_flow` | `measure` (`created` or `won`, required), `period_start`, `source`, `owner` |
| `conversion` | `stage_id`, `outcome` (`next` or `won`), `owner` |
| `stage_time` | `stage_id`, `state` (`in_stage` or `moved_on`), `owner` |
| `activity` | `kind` (`email`, `call`, `meeting` or `task`), `owner` |
| `response` | `state` (`contacted` or `waiting`), `owner` |

`owner` is a user ID, or `none` for records without one. `period_start` is a period's first date as the report lists it in `by_period`. A linked contact, company or deal is only named in an activity row when the credential owner can open it and the credential also holds `contacts:read`, `companies:read` or `deals:read` respectively.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.