Skip to main content

Update Storefront Block

Sparse-update one draft widget on a storefront (Creator page). Omitted keys are left unchanged. Unknown keys at any nesting level return 422.

Do not send type, order, or id — they are not allowed, even when the value matches the stored widget. type cannot change; hide the old widget and create a new one.

layout swaps the layout token only. Stored config is left as-is — titles, photos, and product ids are not re-seeded. The token must be in the allowlist for the stored type. layout of "" or null returns 422; omit the key to leave the stored token.

config is sparse-merged onto the stored config for that type (the same keys as create). Nested objects merge; items and fields replace when sent.

An empty body {} returns 200; nothing changes. { "config": {} } is a write. Hide a widget with is_hidden: true — there is no delete. Hidden widgets stay on GET so they can be unhidden.

Some widget types are read-only and cannot be updated, including with {}. They are still returned by GET. See Block.

The response includes a fresh preview_url of the saved draft. Visitors still see the last published page at public_url until Publish Storefront.

Request​

PATCH /storefronts/{storefrontId}/blocks/{id}

Path Parameters​

ParameterTypeRequiredDescription
storefrontIdstringYesStorefront UUID
idstringYesBlock UUID

Request Body​

All fields are optional. Only include the keys you want to change. Unknown keys are rejected.

ParameterTypeDescription
layoutstringLayout token for the stored type. Omit to leave. Must be in that type's allowlist. "" and null return 422. Swaps the token only.
is_hiddenbooleanOmit to leave. true takes the widget off the public page.
is_hidden_on_mobilebooleanOmit to leave. Independent of is_hidden.
configobjectSparse object merged onto stored config. Nested objects merge; items / fields replace. {} still counts as a write. See Config keys.

product_id / items[].product_id must be a product UUID of this store, or "". list_uuid must be a UUID or "". null on those identifiers and on URL strings clears to "".

Example Requests​

Hide a widget:

curl -X PATCH "https://cart.easy.tools/api/v1/storefronts/b10f5980-d653-4494-ad1c-6a9d68c96d19/blocks/372a48fe-9035-4b1c-9257-1aa1fdff415d" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"is_hidden": true
}'

Swap layout without touching config:

curl -X PATCH "https://cart.easy.tools/api/v1/storefronts/b10f5980-d653-4494-ad1c-6a9d68c96d19/blocks/372a48fe-9035-4b1c-9257-1aa1fdff415d" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"layout": "6x3"
}'

Response​

Success Response (200)​

Returns the widget plus a fresh preview_url. A later GET of the same widget omits preview_url.

{
"id": "372a48fe-9035-4b1c-9257-1aa1fdff415d",
"type": "product",
"layout": "6x3",
"order": 3,
"is_hidden": true,
"is_hidden_on_mobile": false,
"config": {
"use_block_padding": true,
"use_block_surface": true,
"is_block_highlighted": false,
"product_id": "3288e647-aab0-4289-957f-dac92e9b3ffe",
"photo": {
"media_type": "image",
"src_url": "",
"alt": "",
"video_src_url": "",
"video_autoplay": true,
"video_controls": false,
"video_loop": true,
"iframe_src_url": "",
"is_hidden": false,
"fit": "cover"
},
"title": "Product title",
"price": { "value": "$0.00", "is_hidden": false },
"old_price": { "value": "", "is_hidden": false },
"description": { "value": "Product description", "is_hidden": false },
"link": "",
"cta_label": { "value": "Buy now", "is_hidden": false },
"ownership_status": "show_all",
"owned_cta_label": "Open"
},
"preview_url": "https://cart.easy.tools/storefront-preview/b10f5980-d653-4494-ad1c-6a9d68c96d19?expires=1788349464&signature=901c177ef43e5bbd6857afc112bbf8acad9d475dd62f1a95a8bb65949b97559f"
}

preview_url is a fresh signature on every write, including {}. See Draft preview.

Response Fields​

Block fields are documented on the Block object. Updates add preview_url:

FieldTypeNullableDescription
preview_urlstringNoTemporary signed URL of the saved draft. Expires after about one hour.

Error Responses​

Bad Request (400)​

Returned when {storefrontId} or {id} is not a UUID. Both path values are checked before existence.

{
"message": "Invalid storefront ID"
}
{
"message": "Invalid block ID"
}

Not Found Error (404)​

Returned when the storefront UUID does not exist, belongs to another store, or points at a deleted storefront (Storefront not found), or when the block UUID does not exist on this storefront (Block not found).

{
"message": "Storefront not found"
}
{
"message": "Block not found"
}

Validation Error (422 Unprocessable Entity)​

Returned for an unknown key (including type, order, and id), a layout that is not allowed for the stored type (including "" and null), an unknown config key, a product_id that is not a product UUID of this store, an email that is not a valid address, or a read-only widget type (This block type cannot be updated via this API.).

{
"message": "The type field is not allowed.",
"errors": {
"type": [
"The type field is not allowed."
]
}
}

Unauthorized (401)​

{
"message": "Unauthenticated."
}

Forbidden (403)​

Returned when your API key has not been granted access to the requested store.

{
"message": "You do not have API access to the requested store."
}

Too Many Requests (429)​

Returned when you exceed the rate limit. The Retry-After response header gives the number of seconds to wait.

{
"message": "Too many requests. Please retry after 60 seconds."
}