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

# RFP performance

> Query bounded, privacy-protected aggregate RFP quality, efficiency, and commercial metrics.

`get_rfp_performance` is the Seller Account's aggregate RFP reporting query.
Use `get({ "kind": "rfp", "id": "..." })` for an individual RFP's response,
evaluation, feedback, outcome, and receipt. This query returns grouped metrics,
not per-RFP records.

<Note>
  The default population is live production RFPs. Draft and evaluation RFPs
  enter a report only when you explicitly include their `purpose`. Commercial
  metrics always use live, released RFPs.
</Note>

## Run a query

Choose 1–6 metrics, up to three group-by dimensions, an inclusive UTC range,
and optional exact-match filters and ordering. This example is also the checked-in
MCP documentation fixture:

```json theme={null}
{
  "metrics": ["rfp_count", "pass_rate", "cache_hit_rate", "win_rate"],
  "dimensions": ["week", "selected_posture"],
  "filters": { "purpose": ["live"] },
  "range": {
    "startDate": "2026-08-01",
    "endDate": "2026-08-24"
  },
  "orderBy": [{ "field": "week", "direction": "asc" }],
  "limit": 5
}
```

Each metric value has an `available` or `unavailable` status, its own
`population`, `freshness.dataThrough`, and `finality`. Unavailable data includes
a reason; missing observations are never invented as zero.

## Metrics

All metrics use terminal lifecycle turns created within the requested range.
Quality and efficiency follow the purposes you selected. Commercial metrics
exclude drafts, evaluations, and unreleased turns regardless of that selection.

### Quality

| Metric                     | Calculation and availability                                                        |
| -------------------------- | ----------------------------------------------------------------------------------- |
| `rfp_count`                | Distinct selected RFPs; zero is available                                           |
| `response_ready_rate`      | Ready turns / selected turns                                                        |
| `pass_rate`                | Passed turns / selected turns                                                       |
| `needs_clarification_rate` | Needs-clarification turns / selected turns                                          |
| `failure_rate`             | Failed turns / selected turns                                                       |
| `average_grade`            | Sum of latest numeric feedback grades / turns with a grade; missing grades excluded |
| `correction_rate`          | Turns with an observed correction / turns with explicit correction evidence         |
| `revision_rate`            | Distinct RFPs with a selected turn after turn 1 / distinct selected RFPs            |
| `seller_intervention_rate` | Observed seller interventions / turns with explicit intervention evidence           |
| `truth_drop_rate`          | Observed truth-gate drops / turns with truth-drop evidence                          |
| `feedback_agreement_rate`  | Agreeing observations / turns with explicit agreement evidence                      |

### Efficiency

| Metric                          | Calculation and availability                                              |
| ------------------------------- | ------------------------------------------------------------------------- |
| `average_processing_latency_ms` | Sum of terminal-minus-created milliseconds / selected turns               |
| `p95_processing_latency_ms`     | Nearest-rank p95 of terminal-minus-created milliseconds                   |
| `average_generation_cost`       | Sum of observed receipt generation cost in USD / turns with cost evidence |
| `full_compose_rate`             | Full-compose cache misses / turns with cache evidence                     |
| `cache_hit_rate`                | Hydrated or customized cache hits / turns with cache evidence             |
| `retry_rate`                    | Retried or reclaimed turns / selected turns                               |

### Commercial

| Metric                  | Calculation and availability                                                        |
| ----------------------- | ----------------------------------------------------------------------------------- |
| `buyer_response_rate`   | Live released turns with an outcome / live released turns                           |
| `acceptance_rate`       | Recognized accepted or won outcomes / live released turns with a recognized outcome |
| `win_rate`              | Recognized won final outcomes / live released turns with a recognized final outcome |
| `booked_budget`         | Sum of outcome-denominated budget on recognized won live released turns             |
| `average_booked_budget` | Booked budget / recognized won live released turns with numeric budget evidence     |

Commercial rates and money require at least three observations. A money datum
is unavailable with `missing_currency` if any included booked value lacks an
outcome-level denomination; request or response currency is never substituted.
Multiple denominations make it unavailable with `mixed_currency`.
Each booked amount must also be finite, nonnegative, and no greater than
JavaScript's safe numeric maximum, with no more precision than its currency's
minor units. Invalid or unrepresentable values make the datum unavailable with
`invalid_booked_budget` or `unrepresentable_booked_budget`. Reporting converts
valid values to integer minor units, sums them exactly, and publishes only a
numeric total that round-trips to that same integer. Precision-losing or
over-bound totals fail with `unrepresentable_booked_budget_total` instead of
appearing available with a wrong or null value.

`record_outcome` accepts any nonempty result. Aggregate reporting applies one
closed normalization taxonomy: `accepted`; `booked`, `delivered`, `won`, or
`closed_won` → won; `lost`, `closed_lost`, `rejected`, `declined`,
`declined_fit`, or `declined_policy` → lost; and `pending`. Matching ignores
case and treats spaces or hyphens like underscores. An unknown value makes
acceptance, win, and money metrics unavailable with `unknown_outcome` instead
of silently counting it as false. `responded` and `not_live` are brief
dispositions, not commercial synonyms.

For each metric, `population.eligible` is the selected turn or RFP population
before that metric's exclusions, `observed` is the denominator or aggregate
input, `excluded` is their difference, and `exclusionReasons` partitions the
missing grade, feedback, receipt, cache, outcome, release, purpose, budget, or
currency evidence. Row-level provenance remains the shared lifecycle authority
and explicit turn attribution.

## Dimensions and filters

You can group by `date`, `week`, `selected_posture`, `playbook_version`,
`material`, `quick_preset`, `category`, `location`, `market`, `channel`,
`origin`, `purpose`, `buyer`, `advertiser`, `product`,
`response_recipe_version`, `model_version`, `judge_version`, `cache_mode`, or
`currency`. These values come from the selected turn's immutable request,
origin, response, evaluation, and composition receipt.

Exact-match filters are `purpose`, `origin`, `selectedPosture`,
`playbookVersion`, `material`, `quickPreset`, `category`, `location`, `market`,
`channel`, `buyer`, `advertiser`, `product`, `responseRecipeVersion`,
`modelVersion`, `judgeVersion`, `cacheMode`, `currency`, `responseState`,
`evaluationState`, and `outcome`. The camel-case filter names map to the
corresponding snake-case dimensions, such as `selectedPosture` to
`selected_posture` and `quickPreset` to `quick_preset`. Values within one
filter are OR-matched; different filters combine with AND. Each filter accepts
at most 10 unique values, with at most 20 values across all filters. Input and
returned labels are capped at 128 characters; stored labels above the cap use a
deterministic hash suffix.

Select at most one multivalue dimension from `material`, `channel`, and
`product` so one turn cannot create an unbounded cross-product. A turn appears
in every matching group for that selected dimension, so those grouped rows are
not additive. Run the query again without that dimension for an overall total.
`quick_preset` is the saved Quick origin preset identity, while `cache_mode`
states whether the response was composed from scratch, reused and hydrated, or
reused with customization.

## Privacy and pagination

Buyer or advertiser grouping and filtering suppresses groups backed by fewer
than three distinct RFPs. The response reports whether counterparty rows were
suppressed. Empty and below-threshold counterparty queries share the same
suppression signal, and the operation never exposes the underlying RFP IDs.

Ranges are limited to 366 inclusive days. The service first scans terminal
turns for the Seller Account, date range, and snapshot, then applies optional
filters; if that initial population exceeds 50,000, shorten the date range.
Pages contain at most five rows. The first page fixes `snapshotAt`; pass its
opaque `nextCursor` back with the exact same query. The cursor is bound to the
query, snapshot, and last grouped row. Later lifecycle changes do not leak into
a continuation, and changed or stale cursors are rejected rather than silently
restarting.

The structured response is guarded at 40,000 UTF-8 bytes and 10,000 estimated
tokens. A checked maximum-schema fixture (six metrics, three dimensions, 20
maximum-length filter labels, maximum returned labels, all exclusion fields,
five rows, and a maximum cursor) measures 37,282 bytes and 7,136 estimated
tokens.
