patch/grids/{gridId}/buttons/{buttonId}experimentalSession required
Updates any subset of a button's emoji, label, unit, unitPrice, backgroundColor and iconFileId, and returns the whole updated grid, not just the changed button. The body is strict, an unknown field is a 400. backgroundColor and iconFileId are independently clearable: omit a key to leave it untouched, send it as null to remove the button's existing value, or send a new value to replace it - this is distinct from the other three fields, which have no null-clearing behavior since a button always has an emoji, a label and a unit. Sending iconFileId as null skips the icon-validity check below. Responds 403 when the caller is not a member of the grid's workshop and 404 both when no such grid exists and when the grid exists but has no button with this id - the two cases are indistinguishable in the response. Responds 400 when the body fails schema validation, in the usual ValidationError shape, or - with an empty body instead, not ValidationError - when iconFileId is given as a non-null value that does not reference a file uploaded with category grid_tile_icon scoped to this grid's workshop.
Path parameters
| Name | Type | Required | Constraints | Description |
|---|
| gridId | string | Yes | - | Grid id |
| buttonId | string | Yes | - | Button id |
Request body
| Field | Type | Required | Constraints | Description |
|---|
| emoji | Emoji | No | - | One emoji from Mercastra's curated icon set (see EMOJI_CATEGORIES). |
| label | string | No | minLength: 1 | - |
| unit | LineItemUnit | No | - | A line item's unit of measure, one of these seven values. |
| unitPrice | number | No | minimum: 0 | - |
| backgroundColor | HexColor | null | No | - | - |
| iconFileId | string | null | No | - | - |
Example
{
"unitPrice": 95
}Responses
200Success
| Field | Type | Required | Constraints | Description |
|---|
| id | string | Yes | - | - |
| workshopId | string | Yes | - | - |
| name | string | Yes | - | - |
| iconSize | GridIconSize | Yes | - | A grid's icon size, one of these three values. |
| createdAt | string | Yes | format: "date-time" | - |
| updatedAt | string | Yes | format: "date-time" | - |
| buttons | array of GridButton | Yes | - | - |
Example
{
"id": "grid-1",
"workshopId": "workshop-1",
"name": "Standard pricing",
"iconSize": "medium",
"createdAt": "2026-08-01T09:00:00.000Z",
"updatedAt": "2026-08-10T14:30:00.000Z",
"buttons": [
{
"id": "button-1",
"emoji": "🛠️",
"label": "Labor",
"unit": "hour",
"unitPrice": 80
}
]
}400The body fails schema validation (ValidationError shape), or a non-null iconFileId does not reference a valid grid_tile_icon file (empty body)
The shared validation error body, see Validation errors.
401Not authenticated
No body.
403Forbidden
No body.
404Not found
No body.
Example request
curl -X PATCH 'https://mercastra.cloud/api/grids/<gridId>/buttons/<buttonId>' \
-H 'Cookie: session=<session cookie>' \
-H 'X-CSRF-Token: <csrf-token cookie value>' \
-H 'Content-Type: application/json' \
-d '{"unitPrice":95}'