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

> ## Agent Instructions
> Use the public API base URL: https://api.teamfollowup.ai/api.
> Authenticate public API requests with Authorization: Bearer YOUR_API_KEY.
> Use product-owned terms: agents, campaigns, projects (GoHighLevel sub-accounts), contacts, calls, outcomes, skills, cadences, phone numbers.
> Scope requests by locationId rather than projectName.
> Read the guide linked from each API reference group before recommending an endpoint.

# Metrics and how they are calculated

> Every number the analytics endpoints return, what it counts, and what it divides by. Booking rate divides by leads. Conversion rates divide by conversations.

A booking rate is only useful if you know what it divides by. This page defines
every figure `GET /api/dashboard/analytics` returns, so a number you show a
client is a number you can explain.

## The counts

| Field                  | Counts                                                               |
| ---------------------- | -------------------------------------------------------------------- |
| `totalLeads`           | Unique contacts the agent actually dialled.                          |
| `totalCalls`           | Dial attempts, including ones nobody answered.                       |
| `totalAppointments`    | Appointments booked.                                                 |
| `totalCallbacks`       | Callback requests recorded.                                          |
| `totalTransfers`       | Live transfers that connected.                                       |
| `totalFailedTransfers` | Live transfers that did not connect.                                 |
| `attemptedTransfers`   | `totalTransfers` plus `totalFailedTransfers`.                        |
| `killSwitch`           | Opt-outs.                                                            |
| `avgCallDuration`      | Average call length in seconds.                                      |
| `callsPerLead`         | `totalCalls` divided by unique phone numbers.                        |
| `pickups`              | Calls a human answered. The count behind `pickupRate`.               |
| `conversations`        | Answered calls over 30 seconds. The count behind `conversationRate`. |
| `inboundCalls`         | Calls the lead placed.                                               |
| `outboundCalls`        | Calls the agent placed.                                              |

<Note>
  `inboundCalls` and `outboundCalls` can sum to less than `totalCalls`. A call
  recorded without a direction counts in neither, and a sub-account disconnected
  before September 2026 contributes its calls to `totalCalls` from an archived
  summary that stored no direction.
</Note>

## The rates

Two families, and the difference matters. **Lead rates** divide by
`totalLeads`. **Conversion rates** divide by conversations, where a
conversation is a call that lasted longer than 30 seconds. A conversion rate
tells you how the agent does once it is actually talking to someone. A lead
rate tells you how the whole campaign does per person dialled.

| Field                       | Formula                                                                          |
| --------------------------- | -------------------------------------------------------------------------------- |
| `pickupRate`                | Calls a human answered, as a percentage of `totalCalls`.                         |
| `conversationRate`          | Calls that became a conversation, as a percentage of `totalCalls`.               |
| `conversationToPickupRate`  | Conversations as a percentage of pickups.                                        |
| `bookingRate`               | `totalAppointments` as a percentage of `totalLeads`.                             |
| `transferRate`              | `attemptedTransfers` as a percentage of `totalLeads`.                            |
| `transferSuccessRate`       | `totalTransfers` as a percentage of `attemptedTransfers`.                        |
| `appointmentConversionRate` | `totalAppointments` as a percentage of conversations.                            |
| `transferConversionRate`    | `attemptedTransfers` as a percentage of conversations.                           |
| `combinedConversionRate`    | `totalAppointments` plus `attemptedTransfers`, as a percentage of conversations. |

All rates are percentages, to two decimal places.

## The window

`dateFromUTC` and `dateToUTC` set the reporting window. Send a UTC timestamp
with `Z` or an offset, or a plain `YYYY-MM-DD`. A plain date covers that whole
day. A timestamp without a zone is rejected rather than read as server time.

The response carries `window`, the range actually used, as inclusive calendar
days. Days, not instants: the underlying rows record the local calendar day the
call happened, so a bound carrying a time is widened to cover its whole day.

## Scoping the figures

| To report on                                                            | Send                                                                                                                          |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| One project                                                             | `locationId` (preferred) or `projectName`. A stale name returns a zeroed summary, not an error.                               |
| One campaign                                                            | `campaignId`                                                                                                                  |
| One [master agent](/master-agent/overview), across every linked project | `masterCampaignId`. Mutually exclusive with `campaignId`, because a master agent is fanned out into one campaign per project. |
| One [split-test variant](/split-testing/overview)                       | `agentVariantId`, together with `campaignId`. Call it once per variant and compare.                                           |

Contacts you have marked as [your own test leads](/contacts/overview#your-own-test-leads)
are excluded from every figure here.

## Per-project comparisons

Two endpoints return one row per project you can see, so an agency can compare
clients:

* `GET /api/dashboard/booking-rate-by-project`: `project`, `leads`,
  `appointments`, `bookingRate`.
* `GET /api/dashboard/transfer-rate-by-project`: `project`, `leads`,
  `transfers`, `transferRate`.

Both take the same window and scope parameters, plus `agency`, `projects` and
`excludeProjects` for agency-level filtering.

## Boundaries

* `cached`, `queryTime` and `generatedAt` describe the server, not your data.
  Do not build on them.
* Only activity from the current platform carries campaign attribution, so a
  `campaignId` filter cannot reach calls placed before that.
* These endpoints need the `dashboard:read` scope.

## In the API

* [Get analytics summary](/api-reference/analytics/get-analytics-summary)
* [Get booking rate by project](/api-reference/analytics/get-booking-rate-by-project)
* [Get transfer rate by project](/api-reference/analytics/get-transfer-rate-by-project)
* Every field above is defined in the [Glossary](/glossary#analytics)

## Related

* [Call records](/calls/overview) are the rows these figures are built from.
* [Run a split test](/split-testing/run-a-split-test) uses `agentVariantId` to
  compare two versions of an agent.
