Customiser extras
Create an extra
Adds an extra to the customiser, at the end of the current presentation
order. name and input_type are required; every other field has a
documented default (default_value false, both exclusion lists empty,
base_price 0, price_multiplier 0, price_multiplier_target
base_letter_price).
Overview
The input type decides which fields the extra reads, and naming one it
never reads is a 422 field_not_used_by_input_type on that field. A
yes_no extra reads its labels, default answer, colour exclusions, and
its own price; a dropdown or image_choice reads select_options,
where each choice carries its own price; a notes extra reads
char_limit. A dropdown or image choice needs at least one choice.
An extra charges a flat amount or a multiplier, never both: naming one
clears the other, and a body naming both is a 422 price_mode_conflict.
A defaulted price charges nothing.
Colour exclusions name the customiser's own colours — an id from another
customiser or another store is a 422 on the offending element — and each
one may be scoped to a single letter_part or left unscoped with null.
Choice images cannot be set here: image upload is a follow-up surface, so
image_url and example_image_url are read-only and an image-choice
extra created through the API draws its choices without pictures until one
is uploaded in the merchant admin.
Requires customisers:write and an Idempotency-Key.
The write clears the customiser's cached storefront configuration and runs
the advisory language sync. It never regenerates Shopify products, product
images, or the product cache, so live listings are untouched. Option
writes also spend one unit of a separate per-key option-write budget;
exhausting it returns a 429 with retry_after.
Authorisation
Bearer token required. Include it in theAuthorization header.
Required scope: customisers:write
Path parameters
The customiser id.
Example: 1
Request body
Request body example
{
"input_type": "yes_no",
"yes_colour_exclusions": [
{
"letter_part": "face"
}
],
"no_colour_exclusions": [
[]
],
"price_multiplier_target": "base_letter_price",
"name": "Dimmer",
"description": "Adds a dimmer switch to the transformer",
"true_label": "Yes",
"false_label": "No",
"default_value": false,
"base_price": 500
}curl https://web.signcustomiser.com/api/v3/customisers/1/extras \
--request POST \
--header 'Accept: application/json' \
--header 'Authorization: Bearer YOUR_API_TOKEN' \
--header 'Content-Type: application/json' \
--data '{
"input_type": "yes_no",
"yes_colour_exclusions": [
{
"letter_part": "face"
}
],
"no_colour_exclusions": [
[]
],
"price_multiplier_target": "base_letter_price",
"name": "Dimmer",
"description": "Adds a dimmer switch to the transformer",
"true_label": "Yes",
"false_label": "No",
"default_value": false,
"base_price": 500
}'{
"data": {
"object": "extra",
"id": 9,
"customiser_id": 42,
"name": "Dimmer",
"description": null,
"input_type": "yes_no",
"true_label": null,
"false_label": null,
"default_value": false,
"char_limit": null,
"yes_colour_exclusions": [],
"no_colour_exclusions": [],
"select_options": null,
"image_url": null,
"base_price": 0,
"currency": "USD",
"price_multiplier": 0,
"price_multiplier_target": "base_letter_price",
"sort_order": 1,
"created_at": "2026-08-13T00:00:00Z",
"updated_at": "2026-08-13T00:00:00Z"
},
"links": {
"self": "https://web.signcustomiser.com/api/v3/customisers/42/extras/9",
"documentation": "https://www.signcustomiser.com/help/api/"
},
"meta": {
"api_version": "v3",
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
}{
"type": "https://www.signcustomiser.com/help/api/problems/missing_idempotency_key",
"title": "Missing idempotency key",
"status": 400,
"code": "missing_idempotency_key",
"detail": "Provide an Idempotency-Key header for this write.",
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/missing_api_key",
"title": "Missing API key",
"status": 401,
"code": "missing_api_key",
"detail": "Provide a store API key as a bearer token.",
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/insufficient_scope",
"title": "Insufficient scope",
"status": 403,
"code": "insufficient_scope",
"detail": "This operation requires the customisers:write scope.",
"required_scopes": [
"customisers:write"
],
"granted_scopes": [
"customisers:read"
],
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/resource_not_found",
"title": "Resource not found",
"status": 404,
"code": "resource_not_found",
"detail": "The requested resource does not exist or does not belong to the authenticated store.",
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/idempotency_key_conflict",
"title": "Idempotency key conflict",
"status": 409,
"code": "idempotency_key_conflict",
"detail": "This Idempotency-Key was already used for a different request body on this operation.",
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/request_too_large",
"title": "Request too large",
"status": 413,
"code": "request_too_large",
"detail": "The request body must not exceed 2 MiB.",
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/validation_failed",
"title": "Validation failed",
"status": 422,
"code": "validation_failed",
"detail": "A notes extra never reads base_price.",
"errors": [
{
"pointer": "/base_price",
"code": "field_not_used_by_input_type",
"detail": "A notes extra does not use base_price."
}
],
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}{
"type": "https://www.signcustomiser.com/help/api/problems/rate_limited",
"title": "Too many requests",
"status": 429,
"code": "rate_limited",
"detail": "You have exceeded the request limit for this API key.",
"retry_after": 37,
"request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}