Reporting API
Breakdowns
Every Account metrics response also breaks the six metrics down by lead source and by channel.
const res = await fetch(
"https://app.onepath.ai/api/reporting/v1/accounts/42/metrics?from=2026-08-01&to=2026-08-31",
{ headers: { Authorization: "Bearer YOUR_KEY" } }
).then((r) => r.json());
for (const row of res.by_source) {
console.log(row.source.name, row.metrics.leads, row.metrics.booking_rate);
}
How the rows add up
by_source and by_channel each add up to metrics. Every lead came from one lead source and in on one channel, so nothing is counted twice or left out.
- Counts add up exactly.
- Money adds up within rounding: each row is rounded to the cent on its own.
- A row appears only when one of its numbers is not zero.
- Rows are ordered by leads, then appointments.
Lead source rows
A lead source is where the account's leads came from: Yelp, Google Ads, their website. Each lead keeps the source it arrived with.
| Field | Meaning |
|---|---|
| id | the source's id in this account |
| handle | a short key, like yelp or google_ads |
| name | the account's own name for the source |
| kind | system (built into OnePath), platform (a lead platform) or custom (added by the account) |
| category | paid_search, paid_social, organic_search, organic_social, marketplace, pay_per_lead, outreach, direct, email or other |
| platform | the lead platform the source is tied to, or null |
| archived | true when the account archived the source; it keeps the rows its leads earned |
Join accounts on handle only for built-in sources
For system and platform sources the handle is the same in every account, so you can add Yelp across clients by handle. A custom source's handle changes when the account renames it: use its id, which is per account.
Leads OnePath could not attribute count under the account's other source. If the account has none, that row still appears, with id null.
An account can move a campaign's past leads to a different source. A range you pull again later can then be grouped differently. The totals never change.
Channel rows
A channel is how the lead reached the account: the web scheduler, a text, a call.
| Field | Meaning |
|---|---|
| type | the channel's key, like web_scheduler or inbound_voice |
| name | its name, like Web Scheduler or Inbound Voice |
Every channel a lead came in on has a row. Channel names can differ slightly from the account's Dashboard labels.
Adding one source across accounts
const yelp = rows
.flatMap((r) => r.by_source)
.filter((row) => row.source.handle === "yelp")
.reduce((sum, row) => sum + row.metrics.leads, 0);
Recompute rates from your sums, as on Account metrics, rather than averaging them.