---
title: "Statistics calculator: mean, median, standard deviation, quartiles and percentiles"
method: GET
path: "/v1/num/stats"
tags: ["deterministic", "no-api-key", "num", "numbers", "statistics"]
---

# Statistics calculator: mean, median, standard deviation, quartiles and percentiles

`GET /v1/num/stats`

## Request

- Base URL: `https://api.duoleads.com`
- URL: `https://api.duoleads.com/v1/num/stats`
- Auth: none declared

Statistics calculator for a numeric array in one call: count, sum, mean, median, mode, variance and standard deviation honouring ddof (default 1, the sample form; 0 gives the population form) plus always-population *_population fields, min, max, range, the quartiles and interquartile range, skewness, kurtosis, and any requested percentiles. Percentiles use a named interpolation method so the result is reproducible rather than implementation-defined.

**Output (`data`):** n, sum (number|null), mean (number|null), median (number|null), mode ([] or null, null when every value is distinct), ddof (integer), variance (number|null: n-ddof divisor, null when n <= ddof), stdev (number|null, null when n <= ddof), variance_population (number|null), stdev_population (number|null), min, max, range (number|null), q1 (number|null), q3 (number|null), iqr (number|null), skewness (number|null, null when n < 3 or the variance is 0), kurtosis_excess (number|null, null when n < 4 or the variance is 0), percentiles {<p>: number|null}, method, outliers_tukey []. Any computed number is null when the result is not finite, i.e. overflows the double range (e.g. values=1e308,1e308)

Deterministic: identical input returns identical output, so the response is served with `Cache-Control: private, max-age=31536000, immutable` (the paying client may cache it indefinitely; shared caches must not, because the response is paid).

Price: $0.05 USDC per call (x402, Base). Route contract version 1.0.0. Docs: https://api.duoleads.com/docs#num-stats

## Query parameters

- `values` string, required
- `percentiles` string
- `method` 'linear' | 'nearest' | 'lower' | 'higher' | 'midpoint'
- `ddof` integer

## Response `200`

Paid and settled. `data` is route-specific; a route that judges its input returns 200 with `data.valid: false` for a bad value.

- object
  - `ok` unknown, required
  - `route` '/v1/num/stats', required
  - `version` '1.0.0', required
  - `data` object, required: n, sum (number|null), mean (number|null), median (number|null), mode ([] or null, null when every value is distinct), ddof (integer), variance (number|null: n-ddof divisor, null when n <= ddof), stdev (number|null, null when n <= ddof), variance_population (number|null), stdev_population (number|null), min, max, range (number|null), q1 (number|null), q3 (number|null), iqr (number|null), skewness (number|null, null when n < 3 or the variance is 0), kurtosis_excess (number|null, null when n < 4 or the variance is 0), percentiles {<p>: number|null}, method, outliers_tukey []. Any computed number is null when the result is not finite, i.e. overflows the double range (e.g. values=1e308,1e308)
    - `n` integer, required
    - `sum` number, nullable, required
    - `mean` number, nullable, required
    - `median` number, nullable, required
    - `mode` number[], nullable, required
    - `ddof` integer, required
    - `variance` number, nullable, required
    - `stdev` number, nullable, required
    - `variance_population` number, nullable, required
    - `stdev_population` number, nullable, required
    - `min` number, required
    - `max` number, required
    - `range` number, nullable, required
    - `q1` number, nullable, required
    - `q3` number, nullable, required
    - `iqr` number, nullable, required
    - `skewness` number, nullable, required
    - `kurtosis_excess` number, nullable, required
    - `percentiles` object, required: keyed by caller-chosen names
    - `method` string, required
    - `outliers_tukey` number[], required
  - `meta` Meta, required
    - `disclaimer` string, required: Legal short disclaimer, identical on every response.
    - `request_id` string, required: ULID.
    - `computed_at` string, date-time, required: RFC 3339 UTC with milliseconds.
    - `price_usd` string, required: Decimal string, "0.05".
    - `deterministic` boolean, required
    - `sources` object[]: Present only on routes that read a vendored dataset: the exact edition that answered.
      - `id` string, required
      - `version` string, required
      - `published` string, required
      - `attribution` string
      - `licence` string

## Other responses

- `400`: MISSING_PARAM, INVALID_PARAM or UNSUPPORTED_VALUE. Not charged: validation runs before the paywall.
- `402`: Payment required. No valid PAYMENT-SIGNATURE was supplied: read the base64 PAYMENT-REQUIRED header (or this body) for the price ($0.05 = 50000 atomic USDC on eip155:8453), sign an EIP-3009 authorization and retry. Also returned when settlement is declined (PAYMENT_FAILED). Nothing is charged on a 402.
- `404`: NOT_FOUND: unknown path. Not charged.
- `405`: METHOD_NOT_ALLOWED: only GET and HEAD are served. Not charged.
- `413`: INPUT_TOO_LARGE: a parameter exceeded its documented maximum length. Not charged.
- `500`: INTERNAL: a server bug. Not charged.

---

[API](https://skmtc.dev/duoleads/apis/duo-data-utilities-iban-isin-vat-tax-id-barcode-timezone-geo.md) · [All operations](https://skmtc.dev/duoleads/apis/duo-data-utilities-iban-isin-vat-tax-id-barcode-timezone-geo/llms.txt) · [OpenAPI document](https://skmtc.dev/duoleads/apis/duo-data-utilities-iban-isin-vat-tax-id-barcode-timezone-geo/revisions/18790d59615e?raw)
