# Update customiser pricing (`update_customiser_pricing`)

Changes a customiser pricing document, either replacing it wholesale with mode replace or applying a JSON merge patch to it with mode merge. Amounts are integer minor units in the store currency and the document is validated against the customiser pricing model, so a rate the model does not use is refused rather than stored. Read the document with get_customiser_pricing first. It requires the pricing:write scope, takes an optional idempotency_key for replay, and supports dry_run with mode replace.

- Source URL: https://www.signcustomiser.com/help/mcp/tools/update_customiser_pricing/
- Markdown URL: https://www.signcustomiser.com/help/mcp/tools/update_customiser_pricing.md
- MCP endpoint: https://web.signcustomiser.com/mcp
- Required scope: `pricing:write`
- Behaviour: write

## Purpose

Change what a customiser charges: its rates, modifiers, minimums and rounding rules.

## Annotations

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

## Prerequisites

- A customiser id from list_customisers.
- The current document from get_customiser_pricing, because a replace must be complete and a patch must be built against what is there now.
- A merchant has connected this store and approved the pricing:write scope.

## Side effects

- Changes what one customiser charges for every future design.
- Clears the customiser cached storefront configuration.

## Arguments

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `customiser_id` | integer | yes | The customiser id, from list_customisers. |
| `mode` | string | yes | replace writes the whole document and requires document; merge applies an RFC 7396 merge patch and requires patch. One of: `replace`, `merge`. |
| `document` | object | no | The complete canonical pricing document, required with mode replace. Every amount is an integer in the store currency minor units. |
| `patch` | object | no | The merge patch to apply, required with mode merge. Only the members present change; a member set to null clears a nullable field. |
| `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. |
| `dry_run` | boolean | no | When true, the document is checked against the customiser pricing model and the records it references 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. |

## Result

The whole pricing document as it now stands, in the same shape get_customiser_pricing returns. A dry run returns the validation verdict instead and writes nothing.

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `request_id` | string | yes |  |
| `store` | object | yes |  |
| `store.id` | integer | yes |  |
| `store.name` | string | yes |  |
| `customiser_id` | integer | yes |  |
| `pricing_model` | string | no | The pricing model the document is written against. One of: `simple_letter`, `advanced_letter`, `frame_fit`. |
| `currency` | string or null | no | The ISO 4217 currency every amount in the document is expressed in, as integer minor units. |
| `document` | object | no | The pricing document as it now stands, the same shape get_customiser_pricing returns. Absent on a dry run. |
| `dry_run` | boolean | no | Present and true only when dry_run was requested. |
| `valid` | boolean | no | Present only on a dry run, and always true: a failing dry run returns a tool error instead. |
| `verdict` | object | no | Present only on a dry run: the validation verdict. |

## Error cases

| Code | Recovery |
| --- | --- |
| `currency_mismatch` | Amounts must use the store own currency. |
| `field_not_used_by_pricing_model` | Remove the field named by pointer; this customiser pricing model does not use it. |
| `insufficient_scope` | The connection was approved without pricing:write. |
| `pricing_model_mismatch` | The document is written against a different pricing model than this customiser uses. |
| `unknown_field` | The document or patch names a field that is not part of the pricing document. |
| `unsupported_value` | dry_run was sent with mode merge, which has no validate twin: apply the patch locally and validate the result with mode replace. |

## Example: Patch one rate

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_customiser_pricing",
    "arguments": {
      "customiser_id": 42,
      "mode": "merge",
      "patch": {
        "base_pricing": {
          "minimum_order_amount": 9900
        }
      }
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "customiser_id": 42,
      "pricing_model": "simple_letter",
      "currency": "USD",
      "document": {
        "customiser_id": 42,
        "pricing_model": "simple_letter",
        "currency": "USD",
        "base_pricing": {
          "minimum_order_amount": 9900
        }
      }
    }
  }
}
```

## Example: A merge dry run has no validate twin (error)

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_customiser_pricing",
    "arguments": {
      "customiser_id": 42,
      "mode": "merge",
      "patch": {
        "base_pricing": {
          "minimum_order_amount": 9900
        }
      },
      "dry_run": true
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "unsupported_value",
        "title": "Unsupported value",
        "detail": "The pricing validate operation checks a complete document, so dry_run is supported with mode replace only.",
        "recovery": "Send one of the values in allowed_values for the field named by pointer or parameter.",
        "parameter": "mode",
        "allowed_values": [
          "replace"
        ]
      }
    }
  }
}
```
