Sales analytics
pdcli ships a handful of read-only analytics commands. Each fetches deals (and
stages/activities or goals where needed) and computes the numbers locally, so they work
against any account without extra setup. All accept the global --output/--jq/--fields
flags.
metrics velocity
Section titled “metrics velocity”The Sales Velocity Equation: how much deal value your pipeline produces per day.
velocity/day = (open opportunities × win rate × avg won value) / avg cycle daysThe four levers are measured over a trailing window (--period, default 90d, accepts
Nd or Nm), scoped optionally to a --pipeline and/or --owner:
- Open opportunities — count of currently open deals.
- Win rate — won / (won + lost) among deals decided in the window, keyed on
won_time/lost_time. - Avg won value — mean value of deals won in the window.
- Avg cycle days — mean of
won_time − add_timefor those won deals.
pdcli metrics velocity --period 30d --pipeline 1┌────────────────────┬───────────────────┐│ Metric │ Value │├────────────────────┼───────────────────┤│ Open opportunities │ 58 ││ Win rate (30d) │ 41.2% (7W/10L) ││ Avg won value │ 8200 ││ Avg cycle (days) │ 34.5 ││ Velocity / day │ 5676 │└────────────────────┴───────────────────┘If a lever can't be computed (no decided deals, no won deals, or a zero cycle), it shows
n/a and velocity is n/a rather than a misleading zero.
deal summary
Section titled “deal summary”A one-call rollup of deal value, computed server-side: Pipedrive returns per-currency totals, a probability-weighted total, and a deal count, so there's no list to page through. It's the cheapest way to ask "what's my pipeline worth right now?"
pdcli deal summarypdcli deal summary --status open --pipeline 1┌──────────┬─────────┬──────────┬───────┐│ Currency │ Total │ Weighted │ Count │├──────────┼─────────┼──────────┼───────┤│ EUR │ €148000 │ €132000 │ 24 ││ USD │ $52000 │ $41600 │ 9 │└──────────┴─────────┴──────────┴───────┘Narrow the set with --status (open/won/lost), --pipeline, --stage, or a saved
--filter. Totals come pre-formatted per currency from the API; --output json returns the
raw summary object (per-currency totals, grand totals, and counts) for scripting.
funnel
Section titled “funnel”Stage-to-stage conversion. This is an approximation, stated honestly: Pipedrive doesn't hand back per-deal stage history in a single cheap call, so the funnel infers stage reach from each closed deal's final stage — a deal counts as having reached every stage up to and including the one it ended in, and won deals count for every stage. Accurate per-stage flow would need per-deal history mining; this stays one list call per status.
Closed deals are taken over --period (default 90d). The current open distribution per
stage is shown alongside.
pdcli funnel --pipeline 1 --period 180d┌──────────────────────┬──────────────────────────┬─────────────────┬──────────┬────────────┐│ Stage │ Reached (closed, 180d) │ Conv. from prev │ Open now │ Open value │├──────────────────────┼──────────────────────────┼─────────────────┼──────────┼────────────┤│ Qualified │ 120 │ │ 54 │ 4391545 ││ Proposal Made │ 64 │ 53% │ 12 │ 980000 ││ Negotiations Started │ 28 │ 44% │ 2 │ 81909 │└──────────────────────┴──────────────────────────┴─────────────────┴──────────┴────────────┘When your account has more than one pipeline, --pipeline <id> is required — without it
pdcli lists the pipeline IDs and exits 64. With a single pipeline it's inferred.
Exact transitions: --exact
Section titled “Exact transitions: --exact”When the approximation isn't good enough, --exact mines the real stage transitions from
each deal's changelog instead of inferring reach from the final stage. A deal counts as
entering a stage only when it was actually observed there: every stage the deal moved into,
plus its starting stage. A deal created directly in stage 3 — with no stage transitions —
counts as entering stage 3 only, not stages 1 and 2.
pdcli funnel --pipeline 1 --exactThe accuracy costs one request per deal. Above 100 deals, pdcli warns on stderr about the
request volume before it starts mining (the rate limiter then paces the calls); the table
trades the approximate Reached / Open columns for an observed Entered count, with the
won total reported on a single summary line under the table. The per-stage ratio is labelled
Entered vs prev rather than a conversion percentage, because exact entries are
non-monotonic and the ratio can exceed 100%.
In --exact mode, --period scopes only the closed (won/lost) deals it mines; open deals
are always included regardless of the window. If a single deal's changelog can't be fetched,
that deal is skipped (not the whole run) and pdcli notes how many were skipped on stderr.
Time intelligence
Section titled “Time intelligence”Three commands answer questions Pipedrive's UI simply doesn't: where are deals rotting?
(metrics aging), which close dates keep slipping? (metrics slippage), and what's the
real transition graph between stages, backward edges and all? (metrics conversion-matrix).
All three reconstruct stage and close-date history by mining each deal's changelog — one
request per deal, 20 tokens each. That's the cost of accuracy: the changelog is the only
source that records when a deal actually entered a stage or had its close date moved. Above
100 deals, pdcli warns on stderr before it starts (the rate limiter then paces the calls);
a deal whose changelog can't be fetched is skipped, counted, and reported on stderr rather
than aborting the run. --pipeline <id> is required when the account has more than one
pipeline, inferred otherwise.
metrics aging
Section titled “metrics aging”Days-in-current-stage for every open deal, bucketed, so you can see at a glance how much value is going stale and where. For each stage it also mines the completed dwell distribution (entry → next-entry across all deals) and reports per-stage p50/p90, then flags how many open deals have now sat in the stage longer than its own p90 — the deals most likely to be quietly dying.
pdcli metrics aging --pipeline 1 --buckets 30,60,90┌──────────────────────┬───────────┬───────────┬───────────┬───────────┬──────────────────┐│ Stage │ 0-30 │ 30-60 │ 60-90 │ 90+ │ > p90 dwell │├──────────────────────┼───────────┼───────────┼───────────┼───────────┼──────────────────┤│ Qualified │ 31 (820000) │ 12 (410000) │ 6 (180000) │ 5 (240000) │ 4 (p90 47d) ││ Proposal Made │ 7 (390000) │ 3 (120000) │ 1 (60000) │ 1 (80000) │ 2 (p90 22d) ││ Negotiations Started │ 1 (40000) │ 1 (42000) │ 0 │ 0 │ — │└──────────────────────┴───────────┴───────────┴───────────┴───────────┴──────────────────┘Each bucket cell is count (summed value); 0 when empty. Buckets are 0-N1 / N1-N2 / … / last+ with the lower bound inclusive and the upper exclusive, so a deal sitting exactly 30
days lands in 30-60. The > p90 dwell column shows the count past p90 with the threshold
itself (— when the stage has no completed-dwell history to learn a p90 from).
One limitation, stated honestly: a deal's starting stage shows an Unknown dwell.
The changelog records stage transitions, and a deal is created in its first stage — there
is no entry-transition into it — so pdcli can't timestamp when it arrived. Those deals are
counted in an Unknown column (shown only when present) rather than bucketed against a guess.
metrics slippage
Section titled “metrics slippage”Open deals whose expected_close_date keeps getting pushed out. pdcli walks each deal's
close-date changes, counts the forward pushes, and reports the net days slipped
(original → current). --min-pushes (default 1) filters to the serial offenders — the deals
whose timeline you can no longer trust.
pdcli metrics slippage --pipeline 1 --min-pushes 2┌──────┬──────────────────┬───────┬────────┬──────────────────┬──────────────────────────┐│ Deal │ Title │ Owner │ Pushes │ Net days slipped │ Close date │├──────┼──────────────────┼───────┼────────┼──────────────────┼──────────────────────────┤│ 204 │ Acme renewal │ 42 │ 4 │ 96 │ 2026-02-15 → 2026-05-22 ││ 311 │ Globex expansion │ 17 │ 3 │ 61 │ 2026-03-01 → 2026-05-01 │└──────┴──────────────────┴───────┴────────┴──────────────────┴──────────────────────────┘A high push count with a large net slip is the classic "always closing next month" deal.
Owner is a user ID — resolve it with user find / user list (see the
audit guide).
metrics conversion-matrix
Section titled “metrics conversion-matrix”The real stage-transition graph. Unlike funnel, which hides backward moves and collapses
re-entries, this counts every stage_id hop as a directed edge and reports its occurrence
count — so a deal that bounces 1→2→1→2 contributes two 1→2 edges and one 2→1 edge. Won/Lost
are added as terminal columns, attributed to the stage the deal sat in when it closed. The
full source×destination grid is too wide to read, so the table renders a long-format edge
list with a forward/backward tag, plus a per-source forward-rate summary underneath.
pdcli metrics conversion-matrix --pipeline 1┌──────────────────────┬──────────────────────┬───────┬───────────┐│ From │ To │ Edges │ Direction │├──────────────────────┼──────────────────────┼───────┼───────────┤│ Qualified │ Proposal Made │ 64 │ forward ││ Qualified │ Lost │ 22 │ forward ││ Proposal Made │ Negotiations Started │ 28 │ forward ││ Proposal Made │ Qualified │ 9 │ backward ││ Negotiations Started │ Won │ 18 │ forward ││ Negotiations Started │ Proposal Made │ 4 │ backward │└──────────────────────┴──────────────────────┴───────┴───────────┘┌──────────────────────┬───────────┬───────────┐│ Source stage │ Edges out │ Forward % │├──────────────────────┼───────────┼───────────┤│ Qualified │ 86 │ 100% ││ Proposal Made │ 41 │ 78% ││ Negotiations Started │ 22 │ 82% │└──────────────────────┴───────────┴───────────┘--output json returns the raw object — sources, destinations, the dense matrix, and
the edges / backwardEdges lists — for feeding into a graph or a spreadsheet. The backward
edges are the ones worth a second look: they're deals your reps walked back down the
pipeline, often the precursor to a slip or a loss.
The process-compliance side of this same changelog data — gate-skips and regressions with
actor attribution — lives in audit stage-skips.
metrics coverage
Section titled “metrics coverage”Are you carrying enough pipeline to hit your number? metrics coverage weighs your open
pipeline against the revenue still needed to reach a quota and reports the coverage ratio.
The classic 3× rule is defined on raw pipeline value, so that drives the verdict; a
probability-weighted coverage figure (same weighting pipeline health uses) is shown
alongside as the risk-adjusted view.
The quota comes from your active revenue goal via the Goals API,
measured over --period (default 90d). --target <amount> overrides it with a manual
number and skips the Goals API entirely — useful when no goal is configured.
Coverage collapses open value into a single ratio, so it can't mix currencies. If the
pipeline holds deals in more than one currency the command exits 64; scope it to one
with --currency <code> (e.g. --currency USD).
pdcli metrics coverage --pipeline 1pdcli metrics coverage --target 500000┌────────────────────┬──────────┐│ Metric │ Value │├────────────────────┼──────────┤│ Open pipeline │ 1480000 ││ Weighted pipeline │ 1320000 ││ Quota │ 500000 ││ Progress │ 180000 ││ Remaining │ 320000 ││ Coverage ratio │ 4.6x ││ Weighted coverage │ 4.1x ││ Verdict │ healthy │└────────────────────┴──────────┘The verdict applies the classic 3× rule of thumb against open pipeline ÷ remaining gap:
≥ 3× is healthy, 2–3× is borderline, below 2× is low (and covered once progress
already meets the quota). When there's no active revenue goal and you didn't pass --target,
the command exits 64 with guidance to create a goal or supply a target.
pipeline health
Section titled “pipeline health”A per-stage snapshot of your open deals — what's there, what it's worth, and what's neglected.
pdcli pipeline health --pipeline 1┌──────────────────────┬──────┬────────────┬──────────┬────────────┬──────────────┬────────────┐│ Stage │ Open │ Value │ Weighted │ Stale >14d │ No next step │ Past close │├──────────────────────┼──────┼────────────┼──────────┼────────────┼──────────────┼────────────┤│ Qualified │ 54 │ 4391545 │ 878309 │ 12 │ 31 │ 4 ││ Proposal Made │ 12 │ 980000 │ 490000 │ 3 │ 5 │ 1 ││ Negotiations Started │ 2 │ 81909 │ 65527 │ 1 │ 2 │ 0 │└──────────────────────┴──────┴────────────┴──────────┴────────────┴──────────────┴────────────┘Column by column:
| Column | Meaning |
|---|---|
| Open | Open deals currently in the stage. |
| Value | Sum of those deals' value. |
| Weighted | Value × probability. Per-deal probability wins; otherwise the stage's deal_probability; otherwise 100%. |
| Stale >14d | Open deals not updated in more than 14 days. |
| No next step | Open deals with no future, not-done activity scheduled. |
| Past close | Open deals whose expected_close_date is before today. |
Like funnel, --pipeline is required when there's more than one pipeline and inferred
otherwise.
These same hygiene signals drive the data-hygiene audit — audit
applies them account-wide with severities and a CI gate.
metrics forecast
Section titled “metrics forecast”Pipedrive's forecast view is UI-only. metrics forecast reconstructs it on the command
line: your open pipeline bucketed by close-month into three views.
- Commit — full value of deals whose effective win-probability clears
--commit-threshold(default70): the deals you're confident will close. - Best case — every open deal at full value: the optimistic ceiling.
- Weighted — each deal's value × probability (
deal probability ?? stage default ?? 100).
Values are segregated per currency — a USD deal and an EUR deal are different units, so
they are never summed together (the same rule metrics coverage and deal summary follow).
A deal with no expected_close_date lands in a no-date bucket; one with no currency under
(none).
pdcli metrics forecast --pipeline 1pdcli metrics forecast --commit-threshold 80 --output json┌─────┬─────────┬───────┬──────────┬──────────┐│ Cur │ Month │ Deals │ Commit │ Best case│ … Weighted├─────┼─────────┼───────┼──────────┼──────────┤│ EUR │ 2026-07 │ 2 │ 40000 │ 55000 │ 48200│ USD │ 2026-07 │ 6 │ 120000 │ 180000 │ 142500│ USD │ 2026-08 │ 4 │ 90000 │ 140000 │ 101000│ USD │ no-date │ 1 │ 0 │ 20000 │ 12000└─────┴─────────┴───────┴──────────┴──────────┘
Totals by currency:…--pipeline is required only when the account has more than one. For quota-vs-pipeline
coverage, see metrics coverage; to combine forecast with everything
else in one shot, see digest.
rep scorecard
Section titled “rep scorecard”Per-rep performance across all pipelines (narrow with --pipeline/--owner). It reuses
the velocity equation per owner and adds the hygiene a manager actually chases.
pdcli rep scorecard --period 90dpdcli rep scorecard --owner 42 --output json┌───────┬────────┬──────┬───────────────────┬───────────┬────────────┬───────┬────────────┬─────────┬────────────┐│ Rep │ Active │ Open │ Win rate │ Cycle (d) │ Velocity/d │ Stale │ Past close │ No date │ No contact │├───────┼────────┼──────┼───────────────────┼───────────┼────────────┼───────┼────────────┼─────────┼────────────┤│ Alice │ yes │ 14 │ 58% (11W/8L) │ 34 │ 2380 │ 2 │ 1 │ 0 │ 0 ││ Bob │ no │ 9 │ n/a │ n/a │ n/a │ 4 │ 2 │ 3 │ 1 │└───────┴────────┴──────┴───────────────────┴───────────┴────────────┴───────┴────────────┴─────────┴────────────┘Win rate and cycle are decided over the trailing --period (default 90d). Owners with no
matching user fall back to #<id>; deals with no owner roll up under Unassigned. Reps
are ordered by velocity per day (those with too little data to compute it sort last).
digest
Section titled “digest”The Monday packet in one command. A single pipeline-scoped fetch is fanned into velocity, pipeline health, coverage, funnel, forecast and the must-fix hygiene checks — no need to run six commands.
pdcli digest --pipeline 1 # structured table in the terminalpdcli digest --output json # the whole packet for agentspdcli digest --deep # + changelog-mined aging/slippage/stage-skipspdcli digest --format md --out monday.md # shareable markdown artifactpdcli digest --format html --out monday.htmlBy default digest skips changelog mining and stays cheap. --deep mines each deal's
history (one request per deal, the usual >100-deal warning applies) to add aging, close-date
slippage and stage-skip sections. The quota comes from your revenue goal over --period, or
--target <amount>; if no goal is configured the coverage section is simply omitted (the
digest never fails for that reason).
--format md|html renders the packet as a shareable document — pipe it to Slack/email from
cron, or write it to a file with --out. These artifact formats are distinct from the global
--output table|json|yaml|csv (which stays for scripting the structured packet).