Sign Customiser

Store one product created by an enabled custom integration for the authenticated Store and customiser. The response returns the modern product id used by order line items.

POST/api/v3/customisers/{customiser_id}/products

Overview

Sign Customiser also creates a private compatibility projection for the established manufacturer email and export paths. This inbound operation never downloads remote artwork, calls the integration callback, or emits the product-created webhook. Requires products:write. integration_id must identify an enabled custom integration belonging to the Store. store_product_id is the integration's stable external id. This v3 operation rejects an id already present in the Store and serialises concurrent v3 synchronisations. During migration, do not send the same logical product through legacy and v3 writes in parallel. Money is integer minor units and currency must equal the Store currency. Artwork references must be credential-free HTTPS URLs no longer than 255 characters; they are stored as references and are not fetched during this request. Send a unique Idempotency-Key for each logical product. Repeating the exact method, path, body, credential, and key replays the original 201 response with Idempotency-Replay: true and does not create another product. A 409 idempotency_key_in_flight is safe to retry with the same key after retry_after; a key/body conflict needs a new key or the original body. Correct every pointer reported by a 422 before retrying.

Authorisation

Bearer token required. Include it in theAuthorization header.

Required scope: products:write

Path parameters

customiser_idstringpathrequired

Store customiser receiving the product.

Example: 1

Request body

integration_idintegerbody
store_product_idstringbody
titlestringbody
descriptionstringbody
price_amountintegerbody
compare_at_amountintegerbody
currencystringbody
width_cmnumberbody
height_cmnumberbody
length_cmnumberbody
customisationsarraybody
artworkobjectbody

Request body example

application/json
{
  "integration_id": 17,
  "store_product_id": "ext-product-1001",
  "title": "Custom neon sign",
  "description": "Made to order.",
  "price_amount": 12900,
  "compare_at_amount": 14900,
  "currency": "AUD",
  "width_cm": 80.5,
  "height_cm": 31.5,
  "length_cm": 2.5,
  "customisations": [
    {
      "key": "sign_text",
      "label": "Sign text",
      "value": "Hello"
    }
  ],
  "artwork": {
    "preview_image_url": "https://cdn.example.com/sign.png",
    "svg_url": "https://cdn.example.com/sign.svg",
    "outline_image_url": "https://cdn.example.com/sign-outline.png",
    "eps_url": "https://cdn.example.com/sign.eps",
    "illustrator_pdf_url": "https://cdn.example.com/sign.pdf",
    "dxf_url": "https://cdn.example.com/sign.dxf",
    "custom_background_url": "https://cdn.example.com/background.png",
    "custom_background_original_url": "https://cdn.example.com/background-original.png",
    "source_file_url": "https://cdn.example.com/source.ai"
  }
}
Synchronise a product
curl https://web.signcustomiser.com/api/v3/customisers/1/products \
  --request POST \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
  "integration_id": 17,
  "store_product_id": "ext-product-1001",
  "title": "Custom neon sign",
  "description": "Made to order.",
  "price_amount": 12900,
  "compare_at_amount": 14900,
  "currency": "AUD",
  "width_cm": 80.5,
  "height_cm": 31.5,
  "length_cm": 2.5,
  "customisations": [
    {
      "key": "sign_text",
      "label": "Sign text",
      "value": "Hello"
    }
  ],
  "artwork": {
    "preview_image_url": "https://cdn.example.com/sign.png",
    "svg_url": "https://cdn.example.com/sign.svg",
    "outline_image_url": "https://cdn.example.com/sign-outline.png",
    "eps_url": "https://cdn.example.com/sign.eps",
    "illustrator_pdf_url": "https://cdn.example.com/sign.pdf",
    "dxf_url": "https://cdn.example.com/sign.dxf",
    "custom_background_url": "https://cdn.example.com/background.png",
    "custom_background_original_url": "https://cdn.example.com/background-original.png",
    "source_file_url": "https://cdn.example.com/source.ai"
  }
}'
Response201
{
  "data": {
    "object": "product",
    "id": 731,
    "customiser_id": 42,
    "title": "Custom neon sign",
    "price_amount": 12900,
    "compare_at_amount": 14900,
    "currency": "AUD",
    "image_url": null,
    "created_at": "2026-07-19T09:15:00Z",
    "updated_at": "2026-07-19T09:15:00Z",
    "description": "Made to order.",
    "width_cm": 80.5,
    "height_cm": 31.5,
    "length_cm": 2.5,
    "artwork": null
  },
  "links": {
    "self": "https://web.signcustomiser.com/api/v3/products/731",
    "documentation": "https://www.signcustomiser.com/help/api/"
  },
  "meta": {
    "api_version": "v3",
    "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
  }
}
Response400
{
  "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 operation.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
Response401
{
  "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"
}
Response403
{
  "type": "https://www.signcustomiser.com/help/api/problems/insufficient_scope",
  "title": "Insufficient scope",
  "status": 403,
  "code": "insufficient_scope",
  "detail": "This operation requires the products:write scope.",
  "required_scopes": [
    "products:write"
  ],
  "granted_scopes": [
    "products:read"
  ],
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
Response404
{
  "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"
}
Response409
{
  "type": "https://www.signcustomiser.com/help/api/problems/store_product_id_conflict",
  "title": "Store product ID conflict",
  "status": 409,
  "code": "store_product_id_conflict",
  "detail": "This Store has already synchronised a product with the supplied store_product_id. Retry the original request with its original Idempotency-Key, or use a new store_product_id.",
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
Response413
{
  "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"
}
Response422
{
  "type": "https://www.signcustomiser.com/help/api/problems/validation_failed",
  "title": "Validation failed",
  "status": 422,
  "code": "validation_failed",
  "detail": "One or more request fields are invalid.",
  "errors": [
    {
      "parameter": "currency",
      "pointer": "/currency",
      "code": "invalid_field",
      "detail": "The currency must match the authenticated Store currency."
    }
  ],
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}
Response429
{
  "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": 60,
  "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t"
}