---
title: "PATCH /v1/jobs/{jobId}/fit-curves"
description: Refit curves with exclusions and decisions
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).

Refits the named compounds of a job after you exclude dose points, optionally switching the model, and stores each result with the exclusions and any decision (`finalize`, `notes`). This needs write access to the job.

`channel` and `normalize` choose and normalize the readouts as for `POST`. Each entry of `updates` names a compound by `target.compound_label` (or `target.well`) and is processed on its own: the response lists one `{ target, ok }` result per entry, and `ok` is `false` for an entry with no target or one whose store failed. A compound with no readout points is still stored as an empty fit.

The same per-user rate limits as `POST` apply. With a project-scoped API key, a job outside the key's projects returns 404.

## Request

#### Path parameters

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

#### Request body

- `channel` (string) —

- `normalize` (enum (&quot;none&quot; | &quot;percent_control&quot; | &quot;percent_inhibition&quot;)) —

- `updates` (object[]) —

##### Example

```json
{
  "channel": "primary",
  "updates": [
    {
      "target": {
        "compound_label": "CMP-001"
      },
      "model": "4PL",
      "excluded_points": [
        {
          "concentration_uM": 100
        }
      ],
      "decisions": {
        "finalize": true,
        "notes": "Top dose excluded"
      }
    }
  ]
}
```

## Responses

### `200` OK

Per-entry results

Response shape:

- `success` (enum (true)) —

- `updates` (object[]) —
One result per entry of `updates`, in order

### `400` Bad Request

The job id is empty, or `updates` is missing or empty

Response shape: `object`

### `401` Unauthorized

Authentication required

Response shape: `object`

### `404` Not Found

The job does not exist, you cannot write to it, or it is outside your API key's project scope. All of these return an error body with `NOT_FOUND`.

Response shape: `object`

### `405`

The method is not `POST` or `PATCH`; the `Allow` header says `POST, PATCH`

Response shape: `object`

### `429` Too Many Requests

Too many requests; `Retry-After` says how long to wait

Response shape: `object`

### `500` Internal Server Error

Refitting failed

Response shape: `object`

**curl**

```bash
curl -X PATCH 'https://ivybiosciences.com/api/v1/jobs/{jobId}/fit-curves' \
  -H "Authorization: Bearer $IVY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "channel": "primary",
  "updates": [
    {
      "target": {
        "compound_label": "CMP-001"
      },
      "model": "4PL",
      "excluded_points": [
        {
          "concentration_uM": 100
        }
      ],
      "decisions": {
        "finalize": true,
        "notes": "Top dose excluded"
      }
    }
  ]
}'
```

**JavaScript**

```js
const res = await fetch('https://ivybiosciences.com/api/v1/jobs/{jobId}/fit-curves', {
  method: 'PATCH',
  headers: {
    'Authorization': `Bearer ${process.env.IVY_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
  "channel": "primary",
  "updates": [
    {
      "target": {
        "compound_label": "CMP-001"
      },
      "model": "4PL",
      "excluded_points": [
        {
          "concentration_uM": 100
        }
      ],
      "decisions": {
        "finalize": true,
        "notes": "Top dose excluded"
      }
    }
  ]
}),
});
const data = await res.json();
```

**Python**

```python
import os, requests

res = requests.patch(
    "https://ivybiosciences.com/api/v1/jobs/{jobId}/fit-curves",
    headers={"Authorization": f"Bearer {os.environ['IVY_API_KEY']}"},
    json={
  "channel": "primary",
  "updates": [
    {
      "target": {
        "compound_label": "CMP-001"
      },
      "model": "4PL",
      "excluded_points": [
        {
          "concentration_uM": 100
        }
      ],
      "decisions": {
        "finalize": True,
        "notes": "Top dose excluded"
      }
    }
  ]
},
)
data = res.json()
```
