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

# Benchmark

> Where a value sits among its peers: count, quartiles, median and the place of an entity or a value

## Overview

Compares one numeric field across a set of peers and returns the distribution: how many peers, the minimum, the first quartile, the median, the third quartile and the maximum, and, when you give an entity or a value, where it sits (its percentile). One tool serves every data tool that declares a field for it. `attribute` names the data tool, `field` the number to compare, and `peers` the filters that choose the peer set.

Results return in the response, with no polling.

## What the peers are

Benchmark reads the facts we recorded: the current, public (shared) record of each entity. It never reads a private record, for any caller, and never a stored search.

Every answer states how many peers were compared (`count`) and what they are (`population`):

* `looked_up`: the peers are only the entities that someone has looked up. It is a sample of the source, skewed toward what people ask about, not the whole population.
* `complete`: the source is also loaded on a schedule, so the peers are the source's whole population.

A peer set of fewer than 20 is refused, not answered. Read `count` and `population` before you rely on a percentile.

## Authentication

Requires x402 payment in the `payment-signature` header.

## Request Body

<ParamField body="attribute" type="string" required>
  The name of a data tool whose facts can be benchmarked, for example `vehicle_complaints`. A name that cannot be benchmarked, or that has no recorded facts yet, is refused before payment and the response lists the names that can.
</ParamField>

<ParamField body="field" type="string" required>
  The numeric field to compare, one the data tool declares for Benchmark. For `vehicle_complaints`: `total`, `crashes`, `fires`, `injuries`, `deaths`. For `vehicle_recalls` and `place_disasters`: `total`.
</ParamField>

<ParamField body="peers" type="object">
  Filters that choose the peer set, each a field the data tool declares for grouping: `make` and `model_year` for `vehicle_complaints` and `vehicle_recalls`, `state` for `place_disasters`. Values match without regard to case. Up to 5 filters. Without any, every recorded entity of the attribute is a peer.
</ParamField>

<ParamField body="key" type="string">
  The entity key of an entity inside the peer set, to place its own value. Give at most one of `key` and `value`. A key that is not one of the peers is refused.
</ParamField>

<ParamField body="value" type="number">
  A value to place in the distribution. It need not belong to any entity.
</ParamField>

<ParamField body="source" type="string">
  The source to read when the attribute has facts from more than one. Without it, such a request is refused and the response lists the sources.
</ParamField>

<Snippet file="audit-context-params.mdx" />

## Response (200)

<ResponseField name="data.count" type="integer">
  How many peers were compared. Never fewer than 20.
</ResponseField>

<ResponseField name="data.min, data.p25, data.median, data.p75, data.max" type="number">
  The distribution of `field` over the peers. Quartiles are interpolated.
</ResponseField>

<ResponseField name="data.as_of" type="string">
  When the newest peer fact was last seen (ISO 8601)
</ResponseField>

<ResponseField name="data.coverage" type="string">
  Which entities the source covers
</ResponseField>

<ResponseField name="data.population" type="string">
  `looked_up` or `complete`, as above
</ResponseField>

<ResponseField name="data.value" type="number | null">
  The value placed: the one you gave, or the entity's own. `null` when you gave neither.
</ResponseField>

<ResponseField name="data.percentile" type="number | null">
  Where `value` sits among the peers, 0 to 100: the share of peers below it plus half the share equal to it. `null` when you gave neither `key` nor `value`.
</ResponseField>

The response also repeats `attribute`, `field`, `peers` and `source`.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://win.oneshotagent.com/v1/tools/benchmark \
    -H "Content-Type: application/json" \
    -H "payment-signature: <base64 x402 payment>" \
    -d '{
      "attribute": "vehicle_complaints",
      "field": "total",
      "peers": { "model_year": 2019 },
      "key": "HONDA:CR-V:2019"
    }'
  ```

  ```typescript SDK theme={null}
  import { OneShot } from "@oneshot-agent/sdk";

  const agent = new OneShot({ privateKey: process.env.AGENT_PRIVATE_KEY });

  const result = await agent.tool("benchmark", {
    attribute: "vehicle_complaints",
    field: "total",
    peers: { model_year: 2019 },
    key: "HONDA:CR-V:2019",
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "request_id": "6f1c2a94-0d1e-4b53-9d0e-2f6f0c1f7a11",
      "status": "completed",
      "tool": "benchmark",
      "attribute": "vehicle_complaints",
      "field": "total",
      "peers": { "model_year": 2019 },
      "source": null,
      "count": 42,
      "min": 0,
      "p25": 6,
      "median": 19,
      "p75": 52.5,
      "max": 311,
      "as_of": "2026-09-30T12:00:00.000Z",
      "coverage": "Vehicles sold in the United States",
      "population": "looked_up",
      "value": 37,
      "percentile": 66.67
    }
  }
  ```
</ResponseExample>

<Info>See [Pricing](/pricing) for the price of a call.</Info>

## Errors

Refused before any payment:

* `400 invalid_input`: the attribute is not a data tool or cannot be benchmarked, `field` is not one it declares, or a `peers` filter is not one it declares. The response lists the attributes that can be benchmarked.
* `400 no_data`: nothing is recorded for the attribute yet. The response lists the attributes that have recorded facts.
* `400 invalid_request`: a field has the wrong shape, both `key` and `value` were given, or there are more than 5 peer filters.

Found only after the read, once payment is taken. The call is recorded as failed and the response carries its `request_id` and `receipt_id`; a failed call of this kind is refunded automatically:

* `400 too_few_peers`: fewer than 20 peers. The response gives `count`, `minimum` and `population`. Widen the `peers` filters.
* `400 not_in_population`: `key` is not one of the peers, or has no number in `field`.
* `400 invalid_input` with `sources`: the peers have facts from several sources and `source` is missing.


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