# Data Health

**Summary:** Endpoints for Data Health

- Role: [Developers](https://www.subrite.no/developers)
- Source: https://www.subrite.no/developers/data-health
- Updated: 2026-10-13
- Markdown index: https://www.subrite.no/developers/llms.txt

<a id="get-api-v1-data-health-scans"></a>
## List health scans for the tenant (paginated)

`GET /api/v1/data-health/scans`

**Authentication:** Bearer token (JWT)

### Parameters

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `page` | query | `number` | Default: `1` · `minimum`: `1` |
| `take` | query | `number` | Default: `10` · `minimum`: `1`, `maximum`: `50` |
| `orderBy` | query | `string` | Allowed values: `"createdAt"`, `"id"`, `"updatedAt"` · Default: `"createdAt"` |
| `orderDirection` | query | `string` | Allowed values: `"asc"`, `"desc"` · Default: `"desc"` |

### Responses

#### 200

Content type: `application/json` · `HealthScanSummaryDtoPaginated`

| Name | Type | Description |
| --- | --- | --- |
| `items` (Required) | `array of HealthScanSummaryDto` |   |
| `items[].id` (Required when parent is present) | `number` |   |
| `items[].status` (Required when parent is present) | `string` | Allowed values: `"running"`, `"completed"`, `"failed"` |
| `items[].triggeredBy` (Required when parent is present) | `string` | Allowed values: `"schedule"`, `"manual"` |
| `items[].startedAt` (Required when parent is present) | `string (date-time)` |   |
| `items[].finishedAt` (Required when parent is present) | `string (date-time)` | Can be null |
| `items[].durationMs` (Required when parent is present) | `number` | Can be null |
| `items[].recordsScanned` (Required when parent is present) | `number` |   |
| `items[].issuesFound` (Required when parent is present) | `number` |   |
| `items[].checksTotal` (Required when parent is present) | `number` |   |
| `items[].checksFailing` (Required when parent is present) | `number` |   |
| `meta` (Required) | `PageMeta` |   |
| `meta.page` (Required) | `number` |   |
| `meta.take` (Required) | `number` |   |
| `meta.count` (Required) | `number` |   |
| `meta.pageCount` (Required) | `number` |   |
| `meta.hasPreviousPage` (Required) | `boolean` |   |
| `meta.hasNextPage` (Required) | `boolean` |   |

#### 401

unauthorized

#### 403

Content type: `application/json` · `ErrorResponse`

forbiddenResource

| Name | Type | Description |
| --- | --- | --- |
| `messageCode` (Required) | `string` |   |
| `message` | `string` |   |
| `errors` (Required) | `array of FieldError` |   |
| `errors[].field` (Required when parent is present) | `string` |   |
| `errors[].fieldValue` (Required when parent is present) | `string` |   |
| `errors[].identifier` (Required when parent is present) | `string` |   |
| `errors[].identifierValue` (Required when parent is present) | `string` |   |
| `errors[].messageCode` (Required when parent is present) | `string` |   |
| `errors[].message` | `string` |   |
| `errors[].errorType` (Required when parent is present) | `string` |   |

**Example response**

`application/json`

```json
{
  "messageCode": "string",
  "message": "string",
  "errors": [
    {}
  ]
}
```

#### 500

Content type: `application/json` · `ErrorResponse`

internalServerError

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

### Example request

```bash
curl https://api.subrite.no/api/v1/data-health/scans \
  --header 'Authorization: Bearer <token>'
```

### Example response

200 · `application/json`

```json
{
  "items": [
    {}
  ],
  "meta": {
    "page": 0,
    "take": 0,
    "count": 0,
    "pageCount": 0,
    "hasPreviousPage": true,
    "hasNextPage": true
  }
}
```

<a id="post-api-v1-data-health-scans"></a>
## Trigger an on-demand health scan for the tenant

`POST /api/v1/data-health/scans`

**Authentication:** Bearer token (JWT)

### Responses

#### 201

Content type: `application/json` · `TriggerHealthScanResponseDto`

| Name | Type | Description |
| --- | --- | --- |
| `workflowId` (Required) | `string` |   |

#### 401

unauthorized

#### 403

Content type: `application/json` · `ErrorResponse`

forbiddenResource

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

**Example response**

`application/json`

```json
{
  "messageCode": "string",
  "message": "string",
  "errors": [
    {}
  ]
}
```

#### 500

Content type: `application/json` · `ErrorResponse`

internalServerError

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

### Example request

```bash
curl https://api.subrite.no/api/v1/data-health/scans \
  --request POST \
  --header 'Authorization: Bearer <token>'
```

### Example response

201 · `application/json`

```json
{
  "workflowId": "string"
}
```

<a id="get-api-v1-data-health-scans-scanid"></a>
## Get a health scan with its per-check results

`GET /api/v1/data-health/scans/{scanId}`

**Authentication:** Bearer token (JWT)

### Parameters

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `scanId` (Required) | path | `number` |   |

### Responses

#### 200

Content type: `application/json` · `HealthScanDetailDto`

| Name | Type | Description |
| --- | --- | --- |
| `id` (Required) | `number` |   |
| `status` (Required) | `string` | Allowed values: `"running"`, `"completed"`, `"failed"` |
| `triggeredBy` (Required) | `string` | Allowed values: `"schedule"`, `"manual"` |
| `startedAt` (Required) | `string (date-time)` |   |
| `finishedAt` (Required) | `string (date-time)` | Can be null |
| `durationMs` (Required) | `number` | Can be null |
| `recordsScanned` (Required) | `number` |   |
| `issuesFound` (Required) | `number` |   |
| `checksTotal` (Required) | `number` |   |
| `checksFailing` (Required) | `number` |   |
| `checks` (Required) | `array of HealthCheckResultDto` |   |
| `checks[].checkKey` (Required when parent is present) | `string` |   |
| `checks[].name` (Required when parent is present) | `string` |   |
| `checks[].description` (Required when parent is present) | `string` |   |
| `checks[].category` (Required when parent is present) | `string` | Allowed values: `"subscriptions"`, `"payments"`, `"members"` |
| `checks[].status` (Required when parent is present) | `string` | Allowed values: `"passing"`, `"failing"`, `"error"` |
| `checks[].flaggedCount` (Required when parent is present) | `number` |   |
| `checks[].recordsScanned` (Required when parent is present) | `number` |   |
| `checks[].errorMessage` (Required when parent is present) | `string` | Can be null |

#### 401

unauthorized

#### 403

Content type: `application/json` · `ErrorResponse`

forbiddenResource

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

**Example response**

`application/json`

```json
{
  "messageCode": "string",
  "message": "string",
  "errors": [
    {}
  ]
}
```

#### 500

Content type: `application/json` · `ErrorResponse`

internalServerError

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

### Example request

```bash
curl 'https://api.subrite.no/api/v1/data-health/scans/{scanId}' \
  --header 'Authorization: Bearer <token>'
```

### Example response

200 · `application/json`

```json
{
  "id": 0,
  "status": "running",
  "triggeredBy": "schedule",
  "startedAt": "2019-08-24T14:15:22Z",
  "finishedAt": "2019-08-24T14:15:22Z",
  "durationMs": 0,
  "recordsScanned": 0,
  "issuesFound": 0,
  "checksTotal": 0,
  "checksFailing": 0,
  "checks": [
    {}
  ]
}
```

<a id="get-api-v1-data-health-scans-scanid-checks-checkkey"></a>
## Get a check result and its flagged records for a scan (paginated)

`GET /api/v1/data-health/scans/{scanId}/checks/{checkKey}`

**Authentication:** Bearer token (JWT)

### Parameters

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `scanId` (Required) | path | `number` |   |
| `checkKey` (Required) | path | `string` |   |
| `page` | query | `number` | Default: `1` · `minimum`: `1` |
| `take` | query | `number` | Default: `10` · `minimum`: `1`, `maximum`: `50` |
| `orderBy` | query | `string` | Allowed values: `"createdAt"`, `"id"`, `"updatedAt"` · Default: `"createdAt"` |
| `orderDirection` | query | `string` | Allowed values: `"asc"`, `"desc"` · Default: `"desc"` |

### Responses

#### 200

Content type: `application/json` · `HealthCheckRecordsDto`

| Name | Type | Description |
| --- | --- | --- |
| `check` (Required) | `HealthCheckResultDto` |   |
| `check.checkKey` (Required) | `string` |   |
| `check.name` (Required) | `string` |   |
| `check.description` (Required) | `string` |   |
| `check.category` (Required) | `string` | Allowed values: `"subscriptions"`, `"payments"`, `"members"` |
| `check.status` (Required) | `string` | Allowed values: `"passing"`, `"failing"`, `"error"` |
| `check.flaggedCount` (Required) | `number` |   |
| `check.recordsScanned` (Required) | `number` |   |
| `check.errorMessage` (Required) | `string` | Can be null |
| `scanStartedAt` (Required) | `string (date-time)` |   |
| `records` (Required) | `Paginate` |   |
| `records.items` (Required) | `array of object` |   |
| `records.meta` (Required) | `PageMeta` |   |
| `records.meta.page` (Required) | `number` |   |
| `records.meta.take` (Required) | `number` |   |
| `records.meta.count` (Required) | `number` |   |
| `records.meta.pageCount` (Required) | `number` |   |
| `records.meta.hasPreviousPage` (Required) | `boolean` |   |
| `records.meta.hasNextPage` (Required) | `boolean` |   |

#### 401

unauthorized

#### 403

Content type: `application/json` · `ErrorResponse`

forbiddenResource

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

**Example response**

`application/json`

```json
{
  "messageCode": "string",
  "message": "string",
  "errors": [
    {}
  ]
}
```

#### 500

Content type: `application/json` · `ErrorResponse`

internalServerError

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

### Example request

```bash
curl 'https://api.subrite.no/api/v1/data-health/scans/{scanId}/checks/{checkKey}' \
  --header 'Authorization: Bearer <token>'
```

### Example response

200 · `application/json`

```json
{
  "check": {
    "checkKey": "<checkKey>",
    "name": "string",
    "description": "string",
    "category": "subscriptions",
    "status": "passing",
    "flaggedCount": 0,
    "recordsScanned": 0,
    "errorMessage": "string"
  },
  "scanStartedAt": "2019-08-24T14:15:22Z",
  "records": {
    "items": [
      {}
    ],
    "meta": {}
  }
}
```

<a id="get-api-v1-data-health-scans-scanid-checks-checkkey-records-issueid"></a>
## Get a single flagged record (drill-in detail)

`GET /api/v1/data-health/scans/{scanId}/checks/{checkKey}/records/{issueId}`

**Authentication:** Bearer token (JWT)

### Parameters

| Name | In | Type | Description |
| --- | --- | --- | --- |
| `scanId` (Required) | path | `number` |   |
| `checkKey` (Required) | path | `string` |   |
| `issueId` (Required) | path | `number` |   |

### Responses

#### 200

Content type: `application/json` · `HealthFlaggedRecordDto`

| Name | Type | Description |
| --- | --- | --- |
| `issueId` (Required) | `number` |   |
| `entityId` (Required) | `string` |   |
| `memberId` (Required) | `string` | Can be null |
| `detail` (Required) | `string` |   |
| `detectedAt` (Required) | `string (date-time)` |   |
| `context` (Required) | `object with any values` | Can be null |

#### 401

unauthorized

#### 403

Content type: `application/json` · `ErrorResponse`

forbiddenResource

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

**Example response**

`application/json`

```json
{
  "messageCode": "string",
  "message": "string",
  "errors": [
    {}
  ]
}
```

#### 500

Content type: `application/json` · `ErrorResponse`

internalServerError

Same fields as [List health scans for the tenant (paginated) (403)](https://www.subrite.no/developers/data-health?md=true#get-api-v1-data-health-scans).

### Example request

```bash
curl 'https://api.subrite.no/api/v1/data-health/scans/{scanId}/checks/{checkKey}/records/{issueId}' \
  --header 'Authorization: Bearer <token>'
```

### Example response

200 · `application/json`

```json
{
  "issueId": 0,
  "entityId": "string",
  "memberId": "string",
  "detail": "string",
  "detectedAt": "2019-08-24T14:15:22Z",
  "context": {}
}
```
