---
title: "POST /v1/jobs/{jobId}/undo"
description: "Undo a job's last plate update"
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).

Restores the plate rows changed by one recorded plate update on a job you can write to. With no body it takes the most recent event in the job's plate history; pass `eventId` to take a specific event. For each well the event changed, the well is set back to the compound, volume and concentration the event recorded as its previous values, or to empty when it recorded none.

The event stays in the plate history, so sending the same request again applies the same restore again. Only events of type `plate_update` can be undone. A project viewer cannot use this route.

## Request

#### Path parameters

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

#### Request body

- `eventId` (string) —
The `event_id` of the plate-history event to undo. Defaults to the most recent event.

## Responses

### `200` OK

The event was undone

Response shape:

- `success` (enum (true)) —

- `undone_event_id` (string) —
The `event_id` of the event that was restored, or `null` when the event has none

### `400` Bad Request

The job id is empty, or the chosen event is not a plate update that can be undone

Response shape: `object`

### `401` Unauthorized

Authentication required

Response shape: `object`

### `404` Not Found

The job does not exist, you cannot write to it (a project viewer cannot), or it is outside your API key's project scope; or the job has no stored manifest, the manifest cannot be read, it has no plate history, or `eventId` matches no event. The `message` says which of the last cases.

Response shape: `object`

### `405`

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

Response shape: `object`

### `429` Too Many Requests

Rate limit exceeded

Response shape: `object`

### `500` Internal Server Error

The job or its manifest could not be loaded, storage is not configured, or the restore failed

Response shape: `object`

**curl**

```bash
curl -X POST 'https://ivybiosciences.com/api/v1/jobs/{jobId}/undo' \
  -H "Authorization: Bearer $IVY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{}'
```

**JavaScript**

```js
const res = await fetch('https://ivybiosciences.com/api/v1/jobs/{jobId}/undo', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.IVY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({}),
});
const data = await res.json();
```

**Python**

```python
import os, requests

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