---
title: get_mutation_status
description: Find out how a change on Meta ended, after a write tool started it.
---

Ask whether a change on Meta is done. Each write tool gives back a change id before the change reaches Meta, and this tool tells how that change ended.

> Did the budget change on Spring Prospecting go through?

The agent calls `get_mutation_status` with the id of that change, and it asks again while the change runs. Then you see whether Meta applied the change, or why the change did not apply. For a change of an object that exists, it also gives the value that the change replaced, so the agent can put it back. For a copy, it gives the id of the copy and the budget that the copy carries. [Change what runs on Meta](/mcp/tools/change-what-runs-on-meta) lists each outcome.

## Reference

Check whether a mutation started by a write tool (e.g. meta_set_status) has finished. Pass the `workflowId` that tool returned. Returns `running`, `complete` (with the result), or `errored`. For a change to an object that exists, it also returns `priorValue`: the values that the change replaced. To undo the change, call the same tool again with them.

### Input

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `workflowId` | string | yes | The `workflowId` returned by a write tool. |

### Output

A successful call returns this object in `structuredContent`.

| Field | Type | Always present | Description |
| --- | --- | --- | --- |
| `priorValue` | map of any | no | The values that the change replaced, read from Meta just before the change. It uses the field names and units of the arguments that you sent: `{ "dailyBudget": 800 }` for a budget, `{ "status": "ACTIVE" }` for a status, `{ "bidStrategy": "COST_CAP", "costCap": 4 }` for a bid, `{ "startTime": "2026-10-01T00:00:00+0200", "endTime": null }` for a schedule with no end, `{ "name": "Spring sale" }` for a name. To undo the change, call the same tool again with these values. A bid change on a campaign also gives the amount of each ad set in `adsets`: undo it on each ad set. It is present for a change to an object that exists, in each status. A create and a copy have none. |
| `result` | object | no | How the change ended. It is present when `status` is `complete`. `ok` tells whether Meta applied the change. When `ok` is false, `error` holds the code of the refusal. |
| `result.ok` | `true` or `false` | yes | `true`: Meta applied the change. `false`: The change did not apply. |
| `result.result` | object | yes | Only when `ok` is `true`. What Meta gave back. A create gives `id`. A copy gives `id` and `budget`. A change of an object that exists gives `success`. |
| `result.result.budget` | object or `campaign` or `adset` | yes | Only in form 1 of 3. The budget that the copy carries, read from its source: what the copy can spend after you activate it. Change it with `meta_update_budget` on the paused copy. |
| `result.result.budget.dailyBudget` | number | yes | Only in form 1 of 2. The daily budget, in whole units of the account currency. |
| `result.result.budget.lifetimeBudget` | number | yes | Only in form 2 of 2. The lifetime budget, in whole units of the account currency. |
| `result.result.id` | string | yes | Only in form 1 of 3. The Meta id of the copy. |
| `result.result.id` | string | yes | Only in form 2 of 3. The Meta id of the object that a create made. |
| `result.result.deliveryStartsAgain` | `true` | no | Only in form 3 of 3. Present on a schedule change that gave an ACTIVE ad set that had ended a new end time, or no end. The ad set delivers again, and it spends again. |
| `result.result.success` | boolean | yes | Only in form 3 of 3. Whether Meta accepted a change of an object. |
| `result.error` | one of `budget_cap_exceeded`, `invalid_request`, `missing_write_access`, `not_found`, `provider_error`, `provider_not_connected`, `wrong_level` | yes | Only when `ok` is `false`. Why the change did not apply, as a stable code. |
| `result.message` | string | yes | Only when `ok` is `false`. Why the change did not apply, in one sentence for a person. For `provider_error`, the sentence holds the words of Meta. |
| `status` | one of `running`, `complete`, `errored` | yes | `running`: the change has not ended. Call again. `complete`: the change ended. `result` tells how. A refused change is also `complete`. `errored`: the run itself stopped. AdCrunch cannot tell whether Meta applied the change. Read the object at Meta before you send the change again. |

### Failure codes

A failed call has `isError` set, and `structuredContent.error` holds one of these codes. [Errors](/mcp/errors) describes the shape of a failed call.

- `not_found`
- `forbidden`
- `invalid_request`
- `internal_error`

### Scope

The token must hold `mutation:write`. [Auth & scopes](/mcp/auth) lists each scope.

### Annotations

A client reads these hints. A hint that the tool does not declare has the default value of the MCP specification.

- **Read-only.** The tool changes nothing.
- **Open world.** The tool reaches a system outside AdCrunch, such as an ad platform.

### Example

The arguments:

```json
{
  "workflowId": "3f9c2b7e-8a41-4d6e-9b05-c1e7a2d4f860"
}
```

The result, in `structuredContent`:

```json
{
  "result": {
    "ok": true,
    "result": {
      "id": "120215678901234567"
    }
  },
  "status": "complete"
}
```
