Grids

10 endpointówTylko po angielsku

Read a grid

get/grids/{gridId}experimentalWymagana sesja

Responds 403 when the caller is not a member of the grid's workshop and 404 when no such grid exists.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "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
        }
      ]
    }
  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X GET 'https://mercastra.cloud/api/grids/<gridId>' \
  -H 'Cookie: session=<session cookie>'

Rename a grid or change its icon size

patch/grids/{gridId}experimentalWymagana sesja

Updates any subset of name and iconSize; the body is strict, an unknown field is a 400. Neither field can be cleared, only replaced with a new value. Buttons are not editable through this endpoint, see the button endpoints below. Responds 403 when the caller is not a member of the grid's workshop and 404 when no such grid exists.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id

Treść żądania

PoleTypWymaganeOgraniczeniaOpis
namestringNieminLength: 1-
iconSizeGridIconSizeNie-A grid's icon size, one of these three values.
Przykład
{
  "name": "Standard pricing"
}

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "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 request body does not match the schema

    Wspólna treść błędu walidacji, zobacz Błędy walidacji.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X PATCH 'https://mercastra.cloud/api/grids/<gridId>' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Standard pricing"}'

Delete a grid

delete/grids/{gridId}experimentalWymagana sesja

Permanently deletes the grid and its buttons. Responds with an empty body on success. Responds 403 when the caller is not a member of the grid's workshop and 404 when no such grid exists.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id

Odpowiedzi

  • 200Success

    Brak treści.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X DELETE 'https://mercastra.cloud/api/grids/<gridId>' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>'

Add a button to a grid

post/grids/{gridId}/buttonsexperimentalWymagana sesja

Appends one button, assigned a fresh id, and returns the whole updated grid, not just the new button. The body is not strict, an unknown field is silently dropped rather than rejected. There is no per-grid button count cap, only the per-workshop grid cap above. Responds 403 when the caller is not a member of the grid's workshop and 404 when no such grid exists. 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 but does not reference a file uploaded with category grid_tile_icon scoped to this grid's workshop.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id

Treść żądania

PoleTypWymaganeOgraniczeniaOpis
emojiEmojiTak-One emoji from Mercastra's curated icon set (see EMOJI_CATEGORIES).
labelstringTakminLength: 1-
unitLineItemUnitTak-A line item's unit of measure, one of these seven values.
unitPricenumberTakminimum: 0-
backgroundColorHexColorNie-A #RRGGBB hex color.
iconFileIdstringNieminLength: 1-
Przykład
{
  "emoji": "🛠️",
  "label": "Labor",
  "unit": "hour",
  "unitPrice": 80
}

Odpowiedzi

  • 201Created
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "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 iconFileId does not reference a valid, unused grid_tile_icon file (empty body)

    Wspólna treść błędu walidacji, zobacz Błędy walidacji.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X POST 'https://mercastra.cloud/api/grids/<gridId>/buttons' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>' \
  -H 'Content-Type: application/json' \
  -d '{"emoji":"🛠️","label":"Labor","unit":"hour","unitPrice":80}'

Update a button

patch/grids/{gridId}/buttons/{buttonId}experimentalWymagana sesja

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.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id
buttonIdstringTak-Button id

Treść żądania

PoleTypWymaganeOgraniczeniaOpis
emojiEmojiNie-One emoji from Mercastra's curated icon set (see EMOJI_CATEGORIES).
labelstringNieminLength: 1-
unitLineItemUnitNie-A line item's unit of measure, one of these seven values.
unitPricenumberNieminimum: 0-
backgroundColorHexColor | nullNie--
iconFileIdstring | nullNie--
Przykład
{
  "unitPrice": 95
}

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "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)

    Wspólna treść błędu walidacji, zobacz Błędy walidacji.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

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}'

Remove a button

delete/grids/{gridId}/buttons/{buttonId}experimentalWymagana sesja

Removes one button and returns the whole updated grid, not an empty body (unlike deleting the grid itself). 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.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id
buttonIdstringTak-Button id

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "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
        }
      ]
    }
  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

Przykładowe żądanie

curl -X DELETE 'https://mercastra.cloud/api/grids/<gridId>/buttons/<buttonId>' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>'

Duplicate a grid

post/grids/{gridId}/duplicateexperimentalWymagana sesja

Creates a new grid copying name (suffixed with " (copy)"), iconSize and every button, each assigned a fresh id; everything else about a button is copied verbatim, including its iconFileId. Responds 403 when the caller is not a member of the grid's workshop, 404 when no such grid exists, and 409 with an empty body when the workshop already has 10 grids, the same per-workshop cap as creating one, checked against the source grid's workshop.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
gridIdstringTak-Grid id

Odpowiedzi

  • 201Created
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "id": "grid-2",
      "workshopId": "workshop-1",
      "name": "Standard pricing (copy)",
      "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
        }
      ]
    }
  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

  • 409Conflict

    Brak treści.

Przykładowe żądanie

curl -X POST 'https://mercastra.cloud/api/grids/<gridId>/duplicate' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>'

Delete a grid button icon

delete/workshops/{workshopId}/grid-icons/{fileId}experimentalWymagana sesja

Deletes a file uploaded with category grid_tile_icon, scoped to this workshop. When one or more grid buttons in the workshop still reference the icon by iconFileId, the default behavior is to respond 409 with the ids of every grid using it and delete nothing; pass detach=true to instead clear iconFileId from every referencing button first and then delete the file. detach is compared to the literal string "true"; any other value, including absent, is treated as false, there is no 400 for an invalid value. Responds 403 when the caller is not a member of the workshop and 404 when fileId does not reference a grid_tile_icon file scoped to this workshop.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
workshopIdstringTak-Workshop id
fileIdstringTak-File id

Parametry zapytania

NazwaTypWymaganeOgraniczeniaOpis
detachstringNie-Pass the literal string "true" to detach and delete; any other value behaves as false

Odpowiedzi

  • 200Success

    Brak treści.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 404Not found

    Brak treści.

  • 409Conflict
    PoleTypWymaganeOgraniczeniaOpis
    gridIdsarray of stringTak--
    Przykład
    {
      "gridIds": [
        "grid-1"
      ]
    }

Przykładowe żądanie

curl -X DELETE 'https://mercastra.cloud/api/workshops/<workshopId>/grid-icons/<fileId>?detach=<detach>' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>'

List a workshop's grids

get/workshops/{workshopId}/gridsexperimentalWymagana sesja

Returns every grid belonging to the workshop. Responds 403 when the caller is not a member of the workshop; there is no 404 for an unknown workshop id, a non-member sees 403 either way.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
workshopIdstringTak-Workshop id

Odpowiedzi

  • 200Success
    PoleTypWymaganeOgraniczeniaOpis
    gridsarray of GridTak--
    Przykład
    {
      "grids": [
        {
          "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
            }
          ]
        }
      ]
    }
  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

Przykładowe żądanie

curl -X GET 'https://mercastra.cloud/api/workshops/<workshopId>/grids' \
  -H 'Cookie: session=<session cookie>'

Create a grid in a workshop

post/workshops/{workshopId}/gridsexperimentalWymagana sesja

Creates a new grid. name defaults to "Untitled grid" when omitted or blank after trimming; iconSize defaults to medium and buttons default to none, each submitted button is assigned a fresh id. The body is not strict, an unknown field is silently dropped rather than rejected. Responds 403 when the caller is not a member of the workshop and 409 with an empty body when the workshop already has 10 grids, the per-workshop cap; there is no 404 for an unknown workshop id, a non-member sees 403 either way.

Parametry ścieżki

NazwaTypWymaganeOgraniczeniaOpis
workshopIdstringTak-Workshop id

Treść żądania

PoleTypWymaganeOgraniczeniaOpis
namestringNie--
iconSizeGridIconSizeNie-A grid's icon size, one of these three values.
buttonsarray of objectNie--
buttons[].emojiEmojiTak-One emoji from Mercastra's curated icon set (see EMOJI_CATEGORIES).
buttons[].labelstringTakminLength: 1-
buttons[].unitLineItemUnitTak-A line item's unit of measure, one of these seven values.
buttons[].unitPricenumberTakminimum: 0-
buttons[].backgroundColorHexColorNie-A #RRGGBB hex color.
buttons[].iconFileIdstringNieminLength: 1-
Przykład
{
  "name": "Standard pricing"
}

Odpowiedzi

  • 201Created
    PoleTypWymaganeOgraniczeniaOpis
    idstringTak--
    workshopIdstringTak--
    namestringTak--
    iconSizeGridIconSizeTak-A grid's icon size, one of these three values.
    createdAtstringTakformat: "date-time"-
    updatedAtstringTakformat: "date-time"-
    buttonsarray of GridButtonTak--
    Przykład
    {
      "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 request body does not match the schema

    Wspólna treść błędu walidacji, zobacz Błędy walidacji.

  • 401Not authenticated

    Brak treści.

  • 403Forbidden

    Brak treści.

  • 409Conflict

    Brak treści.

Przykładowe żądanie

curl -X POST 'https://mercastra.cloud/api/workshops/<workshopId>/grids' \
  -H 'Cookie: session=<session cookie>' \
  -H 'X-CSRF-Token: <csrf-token cookie value>' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Standard pricing"}'