---
title: "Change a project held in a state token: spaces, dimensions, takeoffs, calculator lines, roof pitch"
method: POST
path: "/project-update"
tags: ["Agent tools"]
---

# Change a project held in a state token: spaces, dimensions, takeoffs, calculator lines, roof pitch

`POST /project-update`

## Request

- Base URL: `https://api.craftquantities.com/v1`
- URL: `https://api.craftquantities.com/v1/project-update`
- Auth: none declared

Stateless: the token carries the project's inputs (compressed, not encrypted), and the answer carries the new token. Every line is rebuilt.

## Query parameters

- `detail` 'full' | 'summary': full (the default): the whole answer. summary: the result lines, the citation line and the page only — fewer tokens to read.
- `format` 'json' | 'md'

## Request body

- object
  - `token` string, required: A project state token from a project-file answer or an earlier update.
  - `operations` object[]: The changes, applied in order (0 to 20); none returns the project as the token holds it.
    - `op` 'add_space' | 'remove_space' | 'set_dimension' | 'add_takeoff' | 'remove_takeoff' | 'add_calculator' | 'remove_calculator' | 'set_roof_pitch' | 'rename', required: add_space (space) and remove_space (index) on a plan; set_dimension (target, index, field, value) on a space's figure, a calculator's input, a takeoff's measurement or a house's figure; add_takeoff (takeoff) and remove_takeoff (index or takeoff id); add_calculator (calculator) and remove_calculator (index); set_roof_pitch (pitch) on a plan's roof or a house; rename (name).
    - `space` object: add_space: one space as a plan takes it (kind, figures, doors, windows, finishes …).
    - `takeoff` union: add_takeoff: a takeoff and its measurements; remove_takeoff: a takeoff id.
      - object
        - `takeoff` string, required
        - `measurements` object: Measurement id → value, each length, area or volume with its unit ("12 ft", {"value": 3.6, "unit": "m"}); counts as numbers. Ids are those of the takeoff; any left out opens at the page's own figure.
        - `selection` object: Build-up choice id → option id, the takeoff's own (a stud size, an insulation, a cladding). Choices left out take the page's own for the system.
        - `allowances` object: Row → an allowance the reader sets: a percentage (cutting waste, overlap), or the option an allowance follows (a lay pattern). Row names are the takeoff's steps (the calculator slug, or the step key where one runs twice).
        - `leaveOut` string[]: Rows the reader leaves out of the job: still worked and shown, not put in the project or counted in labour.
        - `inputUnits` 'base': Send "base" to pass bare numbers on dimensioned inputs in base units (m, m², L, kg …), as the published test vectors are written. Without it a length, area or volume must carry its unit.
      - string
    - `calculator` object
      - `slug` string, required: The calculator's slug, such as concrete-calculator.
      - `inputs` object: The calculator's input values, by input id (an unknown id is refused with the accepted ids). A length, area, volume or other measured input takes "12 ft", "3.5 m", "8' 3 1/2\"" or {"value": 12, "unit": "ft"}; a count or percentage takes a number; a select takes one of its option values. Inputs left out take the value the calculator's page opens on.
      - `label` string: The line's name in the project; the calculator's title when left out.
      - `inputUnits` 'base': Send "base" to pass bare numbers on dimensioned inputs in base units (m, m², L, kg …), as the published test vectors are written. Without it a length, area or volume must carry its unit.
    - `target` 'space' | 'calculator' | 'takeoff' | 'house': set_dimension: what the figure belongs to.
    - `index` integer: Which space, calculator, takeoff or house, counting from 0 (default 0).
    - `field` string: set_dimension: the figure's id (a space's figure, a calculator's input, a takeoff's measurement, a house's value).
    - `value` union
      - number
      - string
      - object
        - `value` number, required
        - `unit` string
    - `pitch` union: set_roof_pitch: rise in 12 (a plan's roof takes 0 to 24; a house 4, 6, 8, 10 or 12).
      - number
      - string
    - `name` string
  - `file` boolean: true: the updated My Project file as well.

## Response `200`

The new token, the diff, the totals and the site link.

- union
  - object
    - `engine` object, required
    - `kind` 'calculators' | 'takeoffs' | 'houses' | 'plan' | 'drawing', required
    - `state` object, required
      - `token` string, nullable, required: The project's inputs, deflated and base64url-encoded with a format version and a CRC-32 check (cqp1.…). Compact, not encrypted: anyone who has it can read it.
      - `format` string, required: The token's format and version.
      - `characters` integer
      - `link` string: Opens the project on the site from the token, carried in the address fragment, which a browser does not send to any server.
      - `note` string, required
    - `applied` string[], required: Each operation as it was applied.
    - `project` object, required
      - `name` string, required
      - `system` 'metric' | 'imperial', required
      - `lines` object[], required
    - `diff` object, required: What the operations changed, line by line (lines that share a zone, a name and a unit are summed).
      - `added` object[], required
        - `zone` string, required
        - `label` string, required
        - `unit` string, required
        - `quantity` number, required
      - `removed` object[], required
        - `zone` string, required
        - `label` string, required
        - `unit` string, required
        - `quantity` number, required
      - `changed` object[], required
        - `zone` string, required
        - `label` string, required
        - `unit` string, required
        - `from` number, required
        - `to` number, required
      - `unchanged` integer, required
      - `more` integer
    - `totals` object, required
      - `lines` integer, required
      - `byUnit` object[], required
        - `unit` string, required
        - `quantity` number, required
        - `lines` integer, required
      - `note` string, required
    - `file` object
      - `filename` string, required
      - `mediaType` 'application/json', required
      - `content` object, required
        - `magic` 'craftquantities.backup', required
        - `v` integer, required
        - `exportedAt` string, required
        - `stores` object, required
    - `howToImport` string
    - `licence` object, required
      - `name` string, required
      - `url` string, required
      - `attribution` string, required
    - `notice` string, required
  - object
    - `detail` 'summary', required
    - `tool` string, required
    - `title` string, required
    - `lines` object[], required: The result lines, as the report's table gives them.
    - `notes` string[], required: What a professional must decide, when to call one, a false-friend warning, that adoption is local: kept in every summary.
    - `citation` string, required: The one citation line, built from the answer's own data.
    - `url` string, nullable, required
    - `open` string, nullable, required
    - `more` string, nullable, required

## Other responses

- `400`: The request was refused; every problem is listed.
- `413`: The request was refused; every problem is listed.
- `422`: The request was refused; every problem is listed.

---

[API](https://skmtc.dev/craftquantities/apis/craft-quantities-engine-api.md) · [All operations](https://skmtc.dev/craftquantities/apis/craft-quantities-engine-api/llms.txt) · [OpenAPI document](https://skmtc.dev/craftquantities/apis/craft-quantities-engine-api/revisions/a69883abc23b?raw)
