---
title: "GET /v1/jobs/{jobId}/qc"
description: "Read a job's plate QC badge"
full: true
---

**Auth:** required. Send an `ivy_` API key (`Authorization: Bearer ivy_…` or `X-Ivy-Api-Key`), a Clerk session JWT (`Authorization: Bearer …`) or the Clerk `__session` cookie (browser sessions). See [Authentication](/docs/api/authentication).

Computes a quality badge for a job you can read from the `concentration_uM` values saved on its plate. `cv` is the sample standard deviation of those values divided by the absolute value of their mean. The badge is `excellent` below 0.1, `good` below 0.2, `fair` below 0.3 and `poor` otherwise. With fewer than two concentration values, or a mean of zero, `cv` is `null` and the badge is `unknown`.

If the values cannot be read or the computation fails, the route still returns 200 with `success: false` and `badge: "unknown"`, so check `success`. The response is sent with `Cache-Control: no-store`; a computed result also sets `X-QC-Badge` and, when `cv` is not null, `X-QC-CV`.

## Request

#### Path parameters

- `jobId` (string (uuid)) —
Job UUID.

## Responses

### `200` OK

The badge, or `success: false` with an `unknown` badge when it could not be computed

Response shape:

- `success` (boolean) —
`false` when the badge could not be computed; `badge` is then `unknown` and `cv` is absent.

- `badge` (enum (&quot;excellent&quot; | &quot;good&quot; | &quot;fair&quot; | &quot;poor&quot; | &quot;unknown&quot;)) —

- `cv` (number) —
Coefficient of variation of the plate's concentration values, or `null` when it cannot be computed.

### `400` Bad Request

The job id is missing

Response shape: `object`

### `401` Unauthorized

Authentication required

Response shape: `object`

### `403` Forbidden

You cannot read the job, or it is outside your API key's project scope. This route answers 403 here, not 404, so it does not hide whether the job exists; `code` is `UNAUTHORIZED` and `message` is `Forbidden`.

Response shape: `object`

### `405`

The method is not `GET`; the `Allow` header says `GET`

Response shape: `object`

### `429` Too Many Requests

Rate limit exceeded

Response shape: `object`

**curl**

```bash
curl -X GET 'https://ivybiosciences.com/api/v1/jobs/{jobId}/qc' \
  -H "Authorization: Bearer $IVY_API_KEY"
```

**JavaScript**

```js
const res = await fetch('https://ivybiosciences.com/api/v1/jobs/{jobId}/qc', {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${process.env.IVY_API_KEY}`,
  },
});
const data = await res.json();
```

**Python**

```python
import os, requests

res = requests.get(
    "https://ivybiosciences.com/api/v1/jobs/{jobId}/qc",
    headers={"Authorization": f"Bearer {os.environ['IVY_API_KEY']}"},
)
data = res.json()
```
