## Update a ticket

`PATCH /v1/feedback/:id`

Changes a ticket's status and resolution. A full update is available to a key with the `vibe:feedback` scope. An author with a regular key can only withdraw their own ticket — with the body `{ "status": "WITHDRAWN" }`.

## Parameters

| Parameter | Type | Required | Description |
|-----------|------|:--------:|-------------|
| `id` (path) | string | yes | Ticket UUID |

## Request fields (body)

| Field | Type | Required | Description |
|-------|------|:--------:|-------------|
| `status` | string | no | New status: `NEW`, `REVIEWING`, `AWAITING_USER`, `NEEDS_REVIEW`, `RESOLVED`, `ARCHIVED`, `WITHDRAWN` |
| `resolution` | string | no | Resolution text. Recommended when moving to `RESOLVED` |

## Statuses

| Status | Meaning |
|--------|---------|
| `NEW` | The ticket was just created |
| `REVIEWING` | The ticket is being triaged |
| `AWAITING_USER` | A reply or clarification from the author is needed |
| `NEEDS_REVIEW` | Requires another round of triage |
| `RESOLVED` | The ticket is closed with a resolution. An email is sent to the author |
| `ARCHIVED` | The ticket is closed without a resolution — a duplicate or out of scope |
| `WITHDRAWN` | The ticket was withdrawn by the author |

## Examples

### curl — personal key

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/feedback/a1b2c3d4-1111-2222-3333-444455556666 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "RESOLVED",
    "resolution": "Fixed in release 2026-04-19. Empty filter now returns 200 with an empty array."
  }'
```

### curl — OAuth application

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/feedback/a1b2c3d4-1111-2222-3333-444455556666 \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "RESOLVED",
    "resolution": "Fixed in release 2026-04-19. Empty filter now returns 200 with an empty array."
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch(
  'https://vibecode.bitrix24.com/v1/feedback/a1b2c3d4-1111-2222-3333-444455556666',
  {
    method: 'PATCH',
    headers: { 'X-Api-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      status: 'RESOLVED',
      resolution: 'Fixed in release 2026-04-19. Empty filter now returns 200 with an empty array.',
    }),
  },
)
const { data } = await res.json()
```

### JavaScript — OAuth application

```javascript
const res = await fetch(
  'https://vibecode.bitrix24.com/v1/feedback/a1b2c3d4-1111-2222-3333-444455556666',
  {
    method: 'PATCH',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      status: 'RESOLVED',
      resolution: 'Fixed in release 2026-04-19. Empty filter now returns 200 with an empty array.',
    }),
  },
)
const { data } = await res.json()
```

## Withdrawing a ticket

The ticket author can withdraw it with the regular key it was created with — with the body strictly `{ "status": "WITHDRAWN" }`. Withdrawal is available while the ticket is not closed.

```bash
curl -X PATCH https://vibecode.bitrix24.com/v1/feedback/a1b2c3d4-1111-2222-3333-444455556666 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "WITHDRAWN" }'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Always `true` on success |
| `data.id` | string | Ticket UUID |
| `data.category` | string | Category |
| `data.title` | string | Title |
| `data.status` | string | Updated status |
| `data.resolution` | string · null | Current resolution |
| `data.resolvedAt` | string · null | Closing date. Set on transition to `RESOLVED` or `WITHDRAWN`, and cleared when the ticket returns from them to an active status |

## Response example

```json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-1111-2222-3333-444455556666",
    "category": "BUG",
    "title": "POST /v1/deals/search returns 500 on empty filter",
    "status": "RESOLVED",
    "resolution": "Fixed in release 2026-04-19. Empty filter now returns 200 with an empty array.",
    "resolvedAt": "2026-04-19T12:00:00.000Z"
  }
}
```

## Error response example

403 — update without the `vibe:feedback` scope:

```json
{
  "success": false,
  "error": {
    "code": "FEEDBACK_SCOPE_REQUIRED",
    "message": "Requires management key or vibe:feedback scope to update feedback"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|------|-------------|
| 403 | `FEEDBACK_SCOPE_REQUIRED` | Updating status or resolution without the `vibe:feedback` scope |
| 404 | `NOT_FOUND` | The ticket does not exist or is not accessible to the key |
| 409 | `FEEDBACK_CLOSED` | The author tries to withdraw an already closed ticket (`RESOLVED`, `ARCHIVED`, or `WITHDRAWN`) |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |

For the full list of common API errors, see [Errors](/docs/errors).

## Known specifics

**Moving to `RESOLVED` notifies the author.** On closing, `resolvedAt` and `resolvedBy` are set, and the author receives an email with the resolution text if their profile has an email. Move to `RESOLVED` only after the fix is available — otherwise the author gets a "fixed" email before the fix itself.

**Returning to an active status clears the closing mark.** A transition from `RESOLVED` or `WITHDRAWN` to one of the active statuses — `NEW`, `REVIEWING`, `AWAITING_USER`, `NEEDS_REVIEW` — clears `resolvedAt`, `resolvedBy`, and `resolution`. A transition to `ARCHIVED` keeps these fields, and so does a transition between active statuses. If the same request carries a `resolution` field, the passed value applies.

**Terminal states depend on the key.** For an author with a regular key, `WITHDRAWN`, `RESOLVED`, and `ARCHIVED` are terminal states. A key with the `vibe:feedback` scope can change the status of an already closed ticket.

## See also

- [Get a ticket](/docs/feedback/get)
- [Add a comment](/docs/feedback/comments)
- [Feedback](/docs/feedback)
- [Errors](/docs/errors)
