---
title: "Get a filtered participant breakdown"
method: GET
path: "/v1/participants/mix"
tags: ["Participants"]
---

# Get a filtered participant breakdown

`GET /v1/participants/mix`

## Request

- Base URL: `https://api.peppolstatus.com`
- URL: `https://api.peppolstatus.com/v1/participants/mix`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

The participant set broken down by country, entity type, NACE Rev. 2.1 division, size class, region and serving Access Point, over a FILTERED slice — so a breakdown stays true while the list is cut down. The filters are the same names and shapes as `GET /v1/participants`.

TWO SOURCES, one shape, named by `source`. A request that narrows on NOTHING is answered from the hourly rollup (`source: "rollup"`, with `refreshed_at`) — the whole-network breakdown, no scan. A request that narrows is computed live (`source: "slice"`).

BOUNDED BY DESIGN. A live slice is computed only while it is narrow (under an internal cap of 10,000 participants). A slice wider than the cap, or a request carrying a filter this endpoint cannot express (`doctype`, `transport_profile`, `q`, `host`, `sub_provider`), answers `degraded: true` with every mix null — never a wrong number and never an error. Callers fall back to the whole-network breakdown on `GET /v1/stats/participants`.

Counts are sparse the same way the rollup facets are: company enrichment covers a handful of registers, so every mix except `country_mix` sums BELOW `participant_count` and the un-enriched remainder is derived from the total rather than served as a bucket. `ap_mix` names the busiest Access Point Seats and folds the rest into one `__other__` bucket.

## Query parameters

- `country` string[]
- `scheme` string[]
- `smp` string[]
- `ap` string[]
- `registered` boolean
- `provenance` string[]
- `entity_type` string[]
- `sector` string[]
- `size` string[]
- `region` string[]
- `postcode` string[]
- `vat_liable` boolean
- `not_country` string[]
- `not_smp` string[]
- `not_entity_type` string[]
- `not_sector` string[]
- `not_size` string[]
- `not_region` string[]

## Response `200`

The filtered participant breakdowns, the whole-network rollup when nothing was narrowed, or a degraded answer when they cannot be computed honestly.

- ParticipantsMix: The participant breakdowns over a filtered slice, or over the whole network. Either computed (`degraded: false`, every mix non-null) or degraded (`degraded: true`, every count and mix null) — the two states never mix.
  - `source` 'slice' | 'rollup', required: Which population the numbers describe: `slice` when the request narrowed and the breakdowns were computed live, `rollup` when it narrowed on nothing and the hourly whole-network facets answered. Callers should show it.
  - `degraded` boolean, required: True when the breakdowns could not be computed honestly — the request carried a filter this endpoint cannot express, or selected a slice wider than the internal cap. Every mix and the count are then null and the caller falls back to the whole-network breakdown on GET /v1/stats/participants.
  - `participant_count` integer, nullable, required: Exact size of the population the mixes describe (not an estimate, not capped). On `source: "rollup"` this is the rollup's `total_count`. Null when degraded.
  - `refreshed_at` string, date-time, nullable, required: When the rollup behind a `source: "rollup"` answer was last built. Null on a live slice and when degraded.
  - `country_mix` ApMixBucket[], nullable, required: Participants per country, count desc. Card country, falling back to the ICD-implied one.
    - `value` string, required
    - `count` integer, required
    - `label` string: Display label of `value`, on the buckets of a `size_mix` and a `region_mix` only: the English size band label (21 → "50–99 employees") and the region name in the local language (84 → "Auvergne-Rhône-Alpes"). Equal to `value` when the code is unknown. Filter on `value`.
  - `entity_type_mix` ApMixBucket[], nullable, required: Participants per company legal-form family, count desc. Sparse: sums below participant_count by the un-enriched remainder.
    - `value` string, required
    - `count` integer, required
    - `label` string: Display label of `value`, on the buckets of a `size_mix` and a `region_mix` only: the English size band label (21 → "50–99 employees") and the region name in the local language (84 → "Auvergne-Rhône-Alpes"). Equal to `value` when the code is unknown. Filter on `value`.
  - `sector_mix` ApMixBucket[], nullable, required: Participants per 2-digit NACE Rev. 2.1 division, count desc. Sparse.
    - `value` string, required
    - `count` integer, required
    - `label` string: Display label of `value`, on the buckets of a `size_mix` and a `region_mix` only: the English size band label (21 → "50–99 employees") and the region name in the local language (84 → "Auvergne-Rhône-Alpes"). Equal to `value` when the code is unknown. Filter on `value`.
  - `size_mix` ApMixBucket[], nullable, required: Participants per company size band code, count desc; each bucket carries its `label`. Sparse.
    - `value` string, required
    - `count` integer, required
    - `label` string: Display label of `value`, on the buckets of a `size_mix` and a `region_mix` only: the English size band label (21 → "50–99 employees") and the region name in the local language (84 → "Auvergne-Rhône-Alpes"). Equal to `value` when the code is unknown. Filter on `value`.
  - `region_mix` ApMixBucket[], nullable, required: Participants per company region code, count desc; each bucket carries its `label`. Sparse.
    - `value` string, required
    - `count` integer, required
    - `label` string: Display label of `value`, on the buckets of a `size_mix` and a `region_mix` only: the English size band label (21 → "50–99 employees") and the region name in the local language (84 → "Auvergne-Rhône-Alpes"). Equal to `value` when the code is unknown. Filter on `value`.
  - `ap_mix` ParticipantsApMixBucket[], nullable, required: Participants per serving Access Point Seat, count desc. The busiest Seats are named; on a live slice the rest fold into one `__other__` bucket, while a rollup answer is truncated to the same length (its facet is already a top-N, so a remainder over it would be unknowable). Participants no Seat serves are not a bucket.
    - `value` string, required
    - `count` integer, required
    - `label` string
    - `slug` string
    - `remainder` boolean: Present and true only on the `__other__` bucket folding every Seat outside the named top ones. Not a filterable SeatID.

## Other responses

- `400`: An invalid `country` / `not_country` code, `registered`, or `vat_liable`.

---

[API](https://skmtc.dev/peppolstatus/apis/peppolstatus-api.md) · [All operations](https://skmtc.dev/peppolstatus/apis/peppolstatus-api/llms.txt) · [OpenAPI document](https://skmtc.dev/peppolstatus/apis/peppolstatus-api/revisions/7e74fb32f23c?raw)
