> ## Documentation Index
> Fetch the complete documentation index at: https://docs.portal.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Building a Proposal Item by Item

> A short walkthrough of the typical item lifecycle: add an item, price it, set its supplier, then organize it within the proposal.

This guide walks through the typical sequence for managing items on a proposal: add the item, price it, assign a supplier, then organize it alongside other items. Each step links to its full endpoint reference in [Proposal Items](/api-reference/proposals/items/overview).

<Note>
  The calls that change an item all return the same [`List<PublicAreaItemModel>`](/api-reference/proposals/items/overview#response-shape) response shape. See that page for the shared error codes and flag conventions, and [reading proposal items](/concepts/proposal-item-model) for what the returned fields mean. [List item suppliers](/api-reference/proposals/items/list-item-suppliers) is the exception — it returns supplier records rather than items.

  The `curl` snippets here are trimmed to the payload. Every real request also needs the four HMAC headers from [signing requests](/authentication/signing-requests). The `POST` calls send a JSON body, so set `Content-Type: application/json` and sign that same value. The `GET` has no body, and its canonical message omits the content-type segment entirely.
</Note>

<Steps>
  <Step title="Add the item">
    Call [add items](/api-reference/proposals/items/add-items) with the catalog item id, its type, and the target area option. Area option ids come from [get proposal](/api-reference/proposals/get-proposal), under `areas[].options[]`. The response includes the new item's `id` — save it for every following step.

    ```bash curl theme={null}
    curl -X POST https://api.portal.io/public/proposals/123/items \
      -H 'Content-Type: application/json' \
      -d '{
        "items": [
          {
            "catalogItemId": 88213,
            "itemType": "Part",
            "proposalAreaOptions": [{ "proposalAreaOptionId": 201, "quantity": 2 }]
          }
        ]
      }'
    ```

    ```json response theme={null}
    [
      {
        "id": 5001,
        "itemType": "Part",
        "referencedItemId": 88213,
        "shortDescription": "Sonos Amp",
        "sellPrice": 649.00,
        "cost": 499.00,
        "quantity": 2,
        "supplier": "Sonos Inc.",
        "total": { "amount": 1298.00, "currency": { "code": "USD", "symbol": "$" }, "isCombinedPrice": false }
      }
    ]
    ```
  </Step>

  <Step title="Price the item">
    Adjust the sell price, cost, or MSRP if the catalog defaults don't apply. Use [update sell price](/api-reference/proposals/items/update-item-sell-price), [update cost](/api-reference/proposals/items/update-item-cost), or [update MSRP](/api-reference/proposals/items/update-item-msrp) — each accepts either an absolute value or a percentage + basis.

    ```bash curl theme={null}
    curl -X POST https://api.portal.io/public/proposals/123/items/5001/sellprice \
      -H 'Content-Type: application/json' \
      -d '{ "sellPrice": 599.00, "setDefault": false, "updateAllInstances": false }'
    ```

    ```json response theme={null}
    [
      {
        "id": 5001,
        "sellPrice": 599.00,
        "cost": 499.00,
        "quantity": 2,
        "total": { "amount": 1198.00, "currency": { "code": "USD", "symbol": "$" }, "isCombinedPrice": false }
      }
    ]
    ```
  </Step>

  <Step title="Set the supplier">
    Call [list item suppliers](/api-reference/proposals/items/list-item-suppliers) to see which suppliers are available for this item, then [set item supplier](/api-reference/proposals/items/set-item-supplier) with the chosen supplier's id. This updates every instance of the same catalog item in the proposal.

    ```bash curl theme={null}
    curl https://api.portal.io/public/proposals/123/items/5001/suppliers
    ```

    ```json response theme={null}
    [
      { "id": 771, "name": "Sonos Inc.", "isDefault": true, "isInStock": true },
      { "id": 902, "name": "ADI Global Distribution", "isDefault": false, "isInStock": true }
    ]
    ```

    ```bash curl theme={null}
    curl -X POST https://api.portal.io/public/proposals/123/items/5001/supplier/902 \
      -H 'Content-Type: application/json' \
      -d '{ "setDefault": false }'
    ```

    ```json response theme={null}
    [
      {
        "id": 5001,
        "supplier": "ADI Global Distribution",
        "cost": 512.50,
        "sellPrice": 599.00,
        "total": { "amount": 1198.00, "currency": { "code": "USD", "symbol": "$" }, "isCombinedPrice": false }
      }
    ]
    ```
  </Step>

  <Step title="Organize the item">
    Once pricing and supplier are set, move or copy the item to its final area option with [move items](/api-reference/proposals/items/move-items) or [copy items](/api-reference/proposals/items/copy-items). Nested (child) items move or copy along with their parent unless you suppress that with `moveNestedItems`/`copyNestedItems`.

    ```bash curl theme={null}
    curl -X POST https://api.portal.io/public/proposals/123/items/move \
      -H 'Content-Type: application/json' \
      -d '{ "destinationAreaOptionId": 305, "proposalItemIds": [5001], "moveNestedItems": true }'
    ```

    ```json response theme={null}
    [
      {
        "id": 5001,
        "shortDescription": "Sonos Amp",
        "supplier": "ADI Global Distribution",
        "sellPrice": 599.00,
        "quantity": 2,
        "total": { "amount": 1198.00, "currency": { "code": "USD", "symbol": "$" }, "isCombinedPrice": false }
      }
    ]
    ```
  </Step>
</Steps>

## Next steps

* To remove an item instead, see [delete items](/api-reference/proposals/items/delete-items) — note its response is `void`, unlike every step above.
* To pull the item's supplier cost from the catalog after a supplier price change elsewhere, see [refresh item costs](/api-reference/proposals/items/refresh-item-costs) — also `void`.
* For the tax-exempt and recurring-service flags, see the [Flags](/api-reference/proposals/items/update-item-tax-exempt) endpoints.
* No webhook fires when an item changes, so to pick up edits made elsewhere, re-fetch [get proposal](/api-reference/proposals/get-proposal) and watch its `Last-Modified` header.
