# Held plugin updates

Plugin updates that stopped a site working were put back automatically; list them and ask for one to be tried again.

## List held plugin updates

`GET /plugin-updates/held` · scope `updates:read`

Every plugin update we held back across your sites because it stopped the site working (the same list as the "Held plugin updates" page). "holding" = tried again on the next update run; "blocked" = it broke the site twice, so it waits for a newer version or for you to ask us to try again.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | query | integer | no | Only this site. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/plugin-updates/held" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/plugin-updates/held", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/plugin-updates/held", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": [
    {
      "id": 312,
      "site_id": 12345,
      "domain": "example.com",
      "plugin": "elementor",
      "name": "Elementor",
      "kept_at_version": "4.2.4",
      "breaking_version": "4.3.0",
      "state": "blocked",
      "times_it_broke": 2,
      "first_seen": "2026-09-23T08:00:00Z",
      "last_seen": "2026-09-24T08:00:00Z",
      "next": "Held until the plugin's makers release a newer version",
      "can_try_again": true
    }
  ]
}
```

Errors: `rate_limited`, `scope_missing`, `unauthorized`

## Held plugin updates of one site

`GET /sites/{site_id}/plugin-updates/held` · scope `updates:read`

The held plugin updates of one site (the site page's "Plugin updates" section).

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `site_id` | path | integer | yes | The site id (see GET /sites). |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/sites/123/plugin-updates/held" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/plugin-updates/held", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/plugin-updates/held", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": [
    {
      "id": 312,
      "site_id": 12345,
      "domain": "example.com",
      "plugin": "elementor",
      "name": "Elementor",
      "kept_at_version": "4.2.4",
      "breaking_version": "4.3.0",
      "state": "blocked",
      "times_it_broke": 2,
      "first_seen": "2026-09-23T08:00:00Z",
      "last_seen": "2026-09-24T08:00:00Z",
      "next": "Held until the plugin's makers release a newer version",
      "can_try_again": true
    }
  ]
}
```

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`

## Try a held plugin update again

`POST /plugin-updates/held/{hold_id}/try-again` · scope `updates:write`

The "Try again" button. Nothing is installed now: the site's next update run tries this version again, loading the site before and after. If it stops the site working again we put it straight back, as before.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `hold_id` | path | integer | yes | The held update id. |

### Example

```bash
curl -s -X POST "https://app.pbn.ltd/api/v1/plugin-updates/held/hold_id/try-again" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/plugin-updates/held/hold_id/try-again", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/plugin-updates/held/hold_id/try-again", {
  method: "POST",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "id": 312,
    "site_id": 12345,
    "domain": "example.com",
    "plugin": "elementor",
    "name": "Elementor",
    "kept_at_version": "4.2.4",
    "breaking_version": "4.3.0",
    "state": "released",
    "times_it_broke": 2,
    "first_seen": "2026-09-23T08:00:00Z",
    "last_seen": "2026-09-24T08:00:00Z",
    "next": "We will try it again on the next update run",
    "can_try_again": false
  }
}
```

Errors: `conflict`, `not_found`, `rate_limited`, `scope_missing`, `unauthorized`
