# Cancel a change to your CRM

Source: https://help.ruuster.com/api/crm-change-cancel

```http
POST https://api.ruuster.com/v1/crm/changes/{changeId}/cancel
```

Stops a change that hasn't finished. A preview that was never applied is closed; a change still applying stops, and the people it hadn't reached yet are marked cancelled. Anyone already changed stays changed (preview an undo to reverse them).

- Authentication: `x-api-key` and `x-email` headers of an owner or admin
- Rate limit: 120 requests per minute per key

Closes a `proposed` or `applying` change from [Preview a change to your CRM](https://help.ruuster.com/api/crm-change-preview). Nothing is written to your CRM by cancelling. People the change already reached stay as they are; to put tags, stages or assignments back, preview an `undo` of the change. The cancel is recorded with the change. No CRM key is needed.

## Path parameters

| Name | Type | Description |
|---|---|---|
| `changeId` | string | The change, `crmchg_…`, from Preview a change to your CRM |

## Response

| Field | Description |
|---|---|
| `changeId` | The change |
| `status` | `cancelled` |
| `counts` | `done` (already changed before the cancel), `failed`, `skipped`, `cancelled` |

## Example request

cURL:

```bash
curl -s -X POST "https://api.ruuster.com/v1/crm/changes/crmchg_7Qm2VbX9kLp4RtYz/cancel" \
  -H "x-api-key: $RUUSTER_API_KEY" \
  -H "x-email: $RUUSTER_EMAIL"
```

Node.js:

```javascript
const res = await fetch("https://api.ruuster.com/v1/crm/changes/crmchg_7Qm2VbX9kLp4RtYz/cancel", {
  method: "POST",
  headers: {
    "x-api-key": process.env.RUUSTER_API_KEY,
    "x-email": process.env.RUUSTER_EMAIL,
  },
});
const body = await res.json();
if (!body.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.requestId})`);
console.log(body.data);
```

Python:

```python
import os
import requests

res = requests.post(
    "https://api.ruuster.com/v1/crm/changes/crmchg_7Qm2VbX9kLp4RtYz/cancel",
    headers={"x-api-key": os.environ["RUUSTER_API_KEY"], "x-email": os.environ["RUUSTER_EMAIL"]},
    timeout=30,
)
body = res.json()
if not body["ok"]:
    raise RuntimeError(f'{body["error"]["code"]}: {body["error"]["message"]} ({body.get("requestId")})')
print(body["data"])
```

## Example response

```json
{
  "ok": true,
  "data": {
    "changeId": "crmchg_7Qm2VbX9kLp4RtYz",
    "status": "cancelled",
    "counts": { "done": 0, "failed": 0, "skipped": 0, "cancelled": 2 }
  },
  "meta": { "brokerageId": "41c73a1a-1dde-42e9-a9c9-0da74502b50e" }
}
```
