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

# Fairness

> Evaluate group-fairness metrics over decision traces or inline samples, and export an EU AI Act conformity report.

The Fairness API computes group-fairness metrics (demographic parity, disparate-impact ratio,
four-fifths rule, equal-opportunity and equalized-odds gaps) over either caller-supplied samples or
a slice of decision traces joined to a protected attribute. Every evaluation writes an `AuditLog`
row for EU AI Act traceability.

Both endpoints are tenant-scoped (authenticate with an API key or session). They are **not**
role-gated. They are rate limited per tenant and fail closed.

## POST /api/v1/fairness/evaluate

Compute a fairness report. Rate limit: 20 requests / 60 s.

### Query parameters

| Parameter | Values              | Default | Description                                                                                                                                               |
| --------- | ------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `metrics` | `basic`, `advanced` | `basic` | `advanced` adds intersectional analysis, mitigation recommendations, per-group Gini and KS tests, and (with a `modelKey`) counterfactual + LIME analysis. |

### Request body

A discriminated union on `mode`, plus optional advanced auto-run fields.

**Inline mode** — pass samples directly:

```json theme={null}
{
  "mode": "inline",
  "samples": [
    { "group": "A", "prediction": true, "label": true },
    { "group": "B", "prediction": false, "label": true }
  ]
}
```

| Field                            | Type       | Required | Description                                                                                      |
| -------------------------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------ |
| `mode`                           | `"inline"` | Yes      | Selects inline mode.                                                                             |
| `samples[].group`                | string     | Yes      | Protected-group label.                                                                           |
| `samples[].prediction`           | boolean    | Yes      | Whether the customer got a positive decision.                                                    |
| `samples[].label`                | boolean    | No       | Ground-truth label (enables equal-opportunity / equalized-odds).                                 |
| `samples[].intersectionalGroups` | object     | No       | `{ axis: value }` map for advanced intersectional analysis.                                      |
| `samples[].attributes`           | object     | No       | Feature map used for counterfactual + LIME when `metrics=advanced` and a `modelKey` is supplied. |

**Trace-join mode** — pull decision traces in a window and match by customer:

```json theme={null}
{
  "mode": "trace-join",
  "from": "2026-06-01T00:00:00Z",
  "to": "2026-07-01T00:00:00Z",
  "offerId": "off_...",
  "groupLookup": { "cust_1": "A", "cust_2": "B" },
  "labelLookup": { "cust_1": true },
  "maxTraces": 5000
}
```

| Field                  | Type              | Required | Description                                                       |
| ---------------------- | ----------------- | -------- | ----------------------------------------------------------------- |
| `mode`                 | `"trace-join"`    | Yes      | Selects trace-join mode.                                          |
| `from` / `to`          | string (ISO-8601) | Yes      | Trace window.                                                     |
| `offerId`              | string            | No       | Positive = this offer was selected. Omitted = any offer selected. |
| `groupLookup`          | object            | Yes      | `customerId → group` map.                                         |
| `labelLookup`          | object            | No       | `customerId → boolean` ground-truth map.                          |
| `intersectionalLookup` | object            | No       | `customerId → { axis: value }` map.                               |
| `maxTraces`            | integer (1-20000) | No       | Cap on traces scanned. Default `5000`.                            |

**Advanced auto-run fields** (only used with `metrics=advanced`): `modelKey`, `modelGroupKey`,
`counterfactualGroup`, `limeBaseline`, `limeOptions` (`{ samples, seed }`).

### Response `200`

```json theme={null}
{
  "groups": [
    { "group": "A", "count": 120, "positiveRate": 0.62 },
    { "group": "B", "count": 118, "positiveRate": 0.41 }
  ],
  "demographicParityGap": 0.21,
  "disparateImpactRatio": 0.66,
  "fourFifthsRuleViolated": true,
  "equalOpportunityGap": 0.18,
  "equalizedOddsGap": 0.2,
  "warnings": ["disparate impact ratio 0.66 below the 0.8 four-fifths threshold"],
  "sampleSize": 238,
  "meta": { "mode": "inline", "sampleCount": 238, "metricsTier": "basic" }
}
```

When `metrics=advanced`, the response may also include `intersectional`, `mitigations`,
`giniByGroup`, `ksByGroup`, `counterfactualFairness`, and `lime`. Any advanced primitive that could
not run (e.g., no `modelKey`, no intersectional groups) is listed by reason in
`advancedAwaitingConfig`.

### Errors

| Code  | Reason                                      |
| ----- | ------------------------------------------- |
| `400` | Request body failed validation.             |
| `429` | Rate limit exceeded (20 / 60 s per tenant). |
| `500` | Trace-join query failed.                    |

## POST /api/v1/fairness/report

Run the same evaluation and return a formatted **EU AI Act conformity report** instead of JSON.
Rate limit: 10 requests / 60 s.

### Request body

The same `inline` / `trace-join` body as `/evaluate`, plus:

| Field      | Type              | Default  | Description                  |
| ---------- | ----------------- | -------- | ---------------------------- |
| `format`   | `"csv"`, `"html"` | `"html"` | Output format.               |
| `title`    | string (max 200)  | —        | Report title (HTML only).    |
| `subtitle` | string (max 300)  | —        | Report subtitle (HTML only). |

### Response `200`

* `format: "csv"` → `text/csv` attachment (`fairness-report-<ts>.csv`).
* `format: "html"` → `text/html` document, suitable for headless-Chromium PDF rendering.

Not a JSON response. A `fairness_report` audit-log row is written on every generation so it is
discoverable in DSAR exports.
