# Execute API delete operation (`execute_delete`)

Runs one deleting Sign Customiser API operation, named by the stable operation id search_operations returns. It reaches every delete operation and nothing else: a create, an update or a read is refused with the tool that does run it. Every operation it reaches removes a record or releases a stored file, so every call needs confirm: true and an idempotency_key. Call it first with dry_run: true to see what still references the target without removing it. It requires the mcp:advanced scope plus the write scope the operation itself declares.

- Source URL: https://www.signcustomiser.com/help/mcp/tools/execute_delete/
- Markdown URL: https://www.signcustomiser.com/help/mcp/tools/execute_delete.md
- MCP endpoint: https://web.signcustomiser.com/mcp
- Required scope: none beyond a connected store
- Only visible to a connection granted `mcp:advanced`. Naming it without that scope answers `insufficient_scope`.
- Behaviour: destructive write

## Purpose

Remove anything the partner API can remove, including the resources no curated tool covers, one operation per call.

## Annotations

| Hint | Value |
| --- | --- |
| readOnlyHint | false |
| destructiveHint | true |
| idempotentHint | true |
| openWorldHint | false |

## Prerequisites

- An operation id from search_operations.
- A merchant has connected this store and approved mcp:advanced plus the write scope that operation requires.
- A dry run first, wherever the operation has a validate twin: it enumerates what still references the target.
- The merchant has agreed to the deletion: confirm: true is required on every call.

## Side effects

- Removes the record the path addresses, permanently.
- Releases any stored file that record owned.
- Claims the idempotency_key for at least 24 hours where the operation requires one.

## Arguments

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `operation_id` | string | yes | The stable id of the operation to run, from search_operations. It is the only way to name an operation: this tool accepts no URL, no path and no HTTP method. |
| `path` | object | no | The operation path parameters, by name, exactly as search_operations lists them under parameters.path. An identifier the operation does not address is refused. |
| `query` | object | no | The query parameters, by name, as search_operations lists them under parameters.query. Only read operations take any; a nested object such as filter is sent as the API expects it. |
| `body` | object | no | The JSON request body, matching the operation request_schema from search_operations. It is passed to the API unchanged, so a member the operation does not accept comes back as unknown_field naming its pointer. A GET or a DELETE operation takes no body and refuses one. |
| `confirm` | boolean | no | Must be true to apply the change, because every operation this tool reaches removes a record or releases a stored file permanently. Without it the call returns a confirmation_required error and changes nothing. A dry run does not need it. |
| `dry_run` | boolean | no | When true, the operation validate twin, which reports what still references the target is checked and nothing is written: the result is the same verdict the apply would have reached, and a problem the apply would have raised comes back as the same tool error. Defaults to false. |
| `idempotency_key` | string | no | An optional client-generated key unique to this logical write, such as a UUID. Repeating the call with the same key and the same arguments replays the original result; the route does not require one. |

## Result

Whether the record was removed, and the operation own response data where it publishes the record as it was.

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `request_id` | string | yes | The API request id, for support. |
| `store` | object | yes | The Store this connection resolved to. |
| `store.id` | integer | no |  |
| `store.name` | string | no |  |
| `operation_id` | string | yes | The operation that ran. |
| `status` | integer | yes | The HTTP status the operation answered with. |
| `dry_run` | boolean | no | Present and true when nothing was written. |
| `valid` | boolean | no | Present and true on a passing dry run. A failing dry run is a tool error carrying the problem the apply would have raised, never a verdict saying false. |
| `verdict` | object | no | What the validate twin reported about the operation. |
| `deleted` | boolean | no | Present and true when the record was removed. |
| `data` | object | no | The operation own response data, where it publishes the record as it was. |

## Error cases

| Code | Recovery |
| --- | --- |
| `confirmation_required` | Send confirm: true. Nothing was removed. Call again with dry_run: true first if you need to see what depends on the record. |
| `insufficient_scope` | The connection holds mcp:advanced but not the write scope this operation needs. |
| `missing_idempotency_key` | The operation requires idempotency_key. Retrying with the same key replays the original success after the record is gone. |
| `resource_in_use` | Other records still reference this one. Run the same call with dry_run: true to enumerate them. |
| `resource_not_found` | The record does not exist in this store, or it was already removed. |
| `unsupported_value` | The id names an operation of another class, or has no validate twin for the dry run that was asked for. |

## Example: Delete a font tier no curated tool covers

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "execute_delete",
    "arguments": {
      "operation_id": "deleteFontTier",
      "path": {
        "customiser_id": 42,
        "font_tier_id": 3
      },
      "confirm": true,
      "idempotency_key": "11112222-3333-4444-5555-666677778888"
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "operation_id": "deleteFontTier",
      "status": 200,
      "deleted": true,
      "data": {
        "object": "font_tier",
        "id": 3,
        "deleted": true
      }
    }
  }
}
```

## Example: Without confirmation nothing is deleted (error)

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "execute_delete",
    "arguments": {
      "operation_id": "deleteFontTier",
      "path": {
        "customiser_id": 42,
        "font_tier_id": 3
      },
      "idempotency_key": "11112222-3333-4444-5555-666677778888"
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "confirmation_required",
        "title": "Confirmation required",
        "detail": "Running deleteFontTier changes store data irreversibly. It is one of 309 operations this tool can reach, so the confirmation is asked for every one of them.",
        "recovery": "This operation changes something consequential. Send confirm: true once the merchant has agreed to it.",
        "parameter": "confirm",
        "allowed_values": [
          "true"
        ]
      }
    }
  }
}
```
