---
title: "POST /v1/jobs/{jobId}/readouts"
description: Save readouts for a job
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).

Saves readout rows for a job you can write to. By default each row is upserted into the job's legacy readouts table, keyed by row, column and channel; a row needs a `row` and `col`, or a `well` name they can be derived from, and is dropped otherwise. `channel` defaults to `primary`. The endpoint name, if you send `endpointName` or it can be inferred from the job's parameters, is stored in each row's `meta.endpoint`.

With `useNew: true`, rows are instead inserted into the newer readouts table, which requires an endpoint name (from `endpointName` or inferred from the job's parameters); `value` is stored as the response and `meta` as the raw payload. A row without a `well` or a `row` and `col` is dropped.

Rows are stored under the job's own project. If you send `projectId` and it differs from the job's project, the request returns 400 and nothing is saved. A project viewer cannot save; saving returns 403 for them.

## Request

#### Path parameters

- `jobId` (string (uuid)) —
UUID of the job.

#### Request body

- `rows` (object[]) —
Readouts to save. Must not be empty.

- `projectId` (string) —
Optional. If sent, it must equal the job's project; it does not choose the project.

- `useNew` (boolean) —
Insert into the newer readouts table instead of upserting into the legacy one.

- `endpointName` (string) —
Assay endpoint name. Inferred from the job's parameters when omitted; required with `useNew` if it cannot be inferred.

##### Example

```json
{
  "rows": [
    {
      "well": "A1",
      "channel": "primary",
      "value": 0.82,
      "unit": "RFU"
    }
  ]
}
```

## Responses

### `200` OK

The rows were saved; `upserted` or `inserted` is set according to the target table

Response shape:

- `success` (enum (true)) —

- `upserted` (integer) —
Rows upserted. Present when `target` is `job_outputs_readouts`.

- `inserted` (integer) —
Rows inserted. Present when `target` is `readouts`.

- `target` (enum (&quot;job_outputs_readouts&quot; | &quot;readouts&quot;)) —

### `400` Bad Request

The job id is missing; `rows` is missing or empty; `projectId` does not match the job's project; `useNew` is set and no endpoint name was given or could be inferred; or no row was valid. `code` is `INVALID_REQUEST`.

Response shape: `object`

### `401` Unauthorized

Authentication required

Response shape: `object`

### `403` Forbidden

You cannot write to the job, or it is outside your API key's project scope; `code` is `FORBIDDEN`

Response shape: `object`

### `429` Too Many Requests

Rate limit exceeded

Response shape: `object`

### `500` Internal Server Error

The job row could not be loaded, or saving failed

Response shape: `object`

**curl**

```bash
curl -X POST 'https://ivybiosciences.com/api/v1/jobs/{jobId}/readouts' \
  -H "Authorization: Bearer $IVY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "rows": [
    {
      "well": "A1",
      "channel": "primary",
      "value": 0.82,
      "unit": "RFU"
    }
  ]
}'
```

**JavaScript**

```js
const res = await fetch('https://ivybiosciences.com/api/v1/jobs/{jobId}/readouts', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.IVY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "rows": [
    {
      "well": "A1",
      "channel": "primary",
      "value": 0.82,
      "unit": "RFU"
    }
  ]
}),
});
const data = await res.json();
```

**Python**

```python
import os, requests

res = requests.post(
    "https://ivybiosciences.com/api/v1/jobs/{jobId}/readouts",
    headers={"Authorization": f"Bearer {os.environ['IVY_API_KEY']}"},
    json={
  "rows": [
    {
      "well": "A1",
      "channel": "primary",
      "value": 0.82,
      "unit": "RFU"
    }
  ]
},
)
data = res.json()
```
