Sign Customiser

Navigation

Dark mode

Pricing

duplicate_customiser_length_pricing

write

Duplicate customiser length pricing

Copy page

Start a new length pricing from the prices of an existing one, for example to give AI Sign Designer designs their own prices on an advanced_letter customiser.

Overview

Copies one length pricing of an advanced_letter or frame_fit customiser, with its shipping settings and every row and price, into a new length pricing on the same customiser. The copy is named name, or "Copy of" and the source name when name is omitted. Nothing uses the copy until a font or the settings icon_length_pricing_id point at it, so the copy changes no storefront price. On an advanced_letter customiser, to give AI Sign Designer its own prices, copy the price list AI designs pay from, then set icon_length_pricing_id to the copy with update_customiser. Through the API a frame_fit customiser holds one price list, because the pricing document holds exactly one, so its copy is refused with price_list_limit_reached; another pricing model is refused with pricing_model_mismatch. It requires the pricing:write scope and an idempotency_key, and supports dry_run.

Permission

Requires thepricing:writepermission. A connection without it answersinsufficient_scopenaming the permission to approve.

Annotations

readOnlyHintfalse
destructiveHintfalse
idempotentHinttrue
openWorldHintfalse

Prerequisites

  • An advanced_letter or frame_fit customiser id from list_customisers and a length pricing id from list_customiser_length_pricings.
  • A merchant has connected this store and approved the pricing:write scope.

Side effects

  • Creates one length pricing on one customiser, a copy of the source price list.
  • Clears the customiser cached storefront configuration.
  • Spends one unit of the store option-write budget.
  • Claims the idempotency_key for at least 24 hours.

Arguments

customiser_idintegerrequired

The customiser id, from list_customisers.

length_pricing_idintegerrequired

The id of the length pricing to copy, from list_customiser_length_pricings.

namestring

The name of the copy. Omit it for "Copy of" and the source name.

idempotency_keystringrequired unless dry_run is true

A client-generated key unique to this logical write, such as a UUID. Required: repeating the call with the same key and the same arguments replays the original result instead of writing twice, and the same key with different arguments is an idempotency_key_conflict.

dry_runboolean

When true, the source price list, the customiser pricing model and the frame_fit limit are checked 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. A dry run claims no key.

Result

The new length pricing with every row, in the shape get_customiser_length_pricing returns. A dry run returns the duplicate verdict instead and writes nothing.

request_idstringalways present
storeobjectalways present
store.idintegeralways present
store.namestringalways present
customiser_idintegeralways present
source_length_pricing_idintegeralways present
length_pricingobject

The new length pricing with every row. Absent on a dry run.

length_pricing.idintegeralways present
length_pricing.customiser_idintegeralways present
length_pricing.namestring or null
length_pricing.letter_pricing_modestring or null

One of: every_letter_cost, price_by_position

length_pricing.letter_pricing_methodstring or null

One of: material_length, fixed_letter

length_pricing.shippingobject
length_pricing.shipping.calculationstring or null
length_pricing.shipping.volumetric_divisorinteger or null
length_pricing.shipping.volumetric_divisor_authoredinteger or null
length_pricing.shipping.volumetric_divisor_unitstring or null
length_pricing.shipping.volumetric_divisor_canonicalnumber or null
length_pricing.shipping.authored_unitsobject
length_pricing.shipping.add_weight_to_productboolean
length_pricing.currencystring or null

The ISO 4217 currency of every integer minor-unit amount on the record.

length_pricing.rows_revisioninteger
length_pricing.rowsarray of object
length_pricing.rows[].idstring
length_pricing.rows[].base_pricenumber or null
length_pricing.rows[].price_per_letternumber or null
length_pricing.rows[].price_per_cmnumber or null
length_pricing.rows[].price_per_innumber or null
length_pricing.rows[].price_per_sq_cmnumber or null
length_pricing.rows[].price_per_sq_innumber or null
length_pricing.rows[].price_per_lbnumber or null
length_pricing.rows[].max_price_multipliernumber or null
length_pricing.rows[].width_limit_cmnumber or null
length_pricing.rows[].width_limit_innumber or null
length_pricing.rows[].height_limit_cmnumber or null
length_pricing.rows[].height_limit_innumber or null
length_pricing.rows[].length_limit_cmnumber or null
length_pricing.rows[].length_limit_innumber or null
length_pricing.rows[].fixed_length_cmnumber or null
length_pricing.rows[].fixed_length_innumber or null
length_pricing.rows[].width_modifiernumber or null
length_pricing.rows[].width_modifier_innumber or null
length_pricing.rows[].height_modifiernumber or null
length_pricing.rows[].height_modifier_innumber or null
length_pricing.rows[].length_modifiernumber or null
length_pricing.rows[].length_modifier_innumber or null
length_pricing.rows[].price_per_sq_cm_basisstring

One of: per_sq_cm, per_kg_volumetric

length_pricing.rows[].price_per_letter_by_positionarray of integer
length_pricing.rows[].authored_unitsobject
length_pricing.created_atstring or null
length_pricing.updated_atstring or null
idempotent_replayboolean

True when this call replayed a previously recorded response for the same idempotency_key instead of applying the write again.

dry_runboolean

Present and true only when dry_run was requested.

validboolean

Present only on a dry run, and always true: a failing dry run returns a tool error instead.

verdictobject

Present only on a dry run: the duplicate verdict.

Error cases

idempotency_subject_changed

The copy was later deleted. Issue a new key and re-check the resource before writing again.

insufficient_scope

The connection was approved without pricing:write.

pricing_model_mismatch

The customiser does not price by advanced_letter or frame_fit, so a length pricing would never be used.

rate_limited

The store option-write budget is spent. Wait retry_after seconds.

resource_not_found

No length pricing with that id belongs to that customiser in this store. Sheet pricing is not a length pricing.

unknown_field

Remove the field named by pointer; the duplicate takes only name.

validation_failed

The name is longer than 255 characters, or the customiser is frame_fit and already has the one price list the API allows (price_list_limit_reached). The pointer names the field.

Copy the price list AI designs pay from

tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "duplicate_customiser_length_pricing",
    "arguments": {
      "customiser_id": 42,
      "length_pricing_id": 9,
      "name": "Standard (AI Sign Designer)",
      "idempotency_key": "d5e6f7a8-b9c0-4d1e-8f2a-3b4c5d6e7f80"
    }
  }
}
result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "customiser_id": 42,
      "source_length_pricing_id": 9,
      "length_pricing": {
        "id": 10,
        "customiser_id": 42,
        "name": "Standard (AI Sign Designer)",
        "letter_pricing_mode": "every_letter_cost",
        "letter_pricing_method": "material_length",
        "shipping": {
          "calculation": "physical",
          "volumetric_divisor": null,
          "add_weight_to_product": false
        },
        "currency": "USD",
        "rows": [
          {
            "base_price": 4500,
            "width_limit_cm": 120,
            "height_limit_cm": 60,
            "length_limit_cm": null,
            "price_per_sq_cm": null,
            "price_per_sq_cm_basis": "per_sq_cm",
            "fixed_length_cm": null,
            "width_modifier": null,
            "height_modifier": null,
            "length_modifier": null,
            "max_price_multiplier": null,
            "price_per_cm": 1.25,
            "price_per_letter": null,
            "price_per_letter_by_position": null
          }
        ],
        "created_at": "2026-11-14T00:00:00Z",
        "updated_at": "2026-11-14T00:00:00Z"
      },
      "idempotent_replay": false
    }
  }
}

A frame_fit customiser already has its price list (error)

tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "duplicate_customiser_length_pricing",
    "arguments": {
      "customiser_id": 43,
      "length_pricing_id": 12,
      "dry_run": true
    }
  }
}
result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "validation_failed",
        "title": "Validation failed",
        "detail": "Through the API a frame-fit customiser holds one price list, because the customiser pricing document holds exactly one. Update the existing one instead.",
        "recovery": "Correct every field listed in errors, using its pointer to locate the value and allowed_values where one is given, then call the tool again.",
        "pointer": "",
        "errors": [
          {
            "pointer": "",
            "code": "price_list_limit_reached",
            "detail": "This customiser already has the one price list the API allows for its pricing model."
          }
        ]
      }
    }
  }
}

Type a question and press Enter. Use the arrow keys to move between the results.