Skip to main content
The endpoints in this section edit the line items of a proposal — one field per call. This page covers what they all have in common; each endpoint page then describes only its own behavior. To read items, or to find the item and area option ids these endpoints need, see reading proposal items. For an end-to-end walkthrough, see building a proposal item by item.

Authentication

Item endpoints accept the same HMAC-signed authentication as the rest of the Portal.io API — see signing requests for how to build X-MSS-SIGNATURE. All requests carry the standard header set: An authenticated Portal.io session is also accepted, which is how the web app calls these routes. API integrations should sign requests. The portal_auth / portalAuth helper imported by the code samples on these pages is the signing routine from signing requests — copy it from there.

Error codes

Three endpoints deviate: refresh item costs has no 400 (it takes no payload), set item supplier documents none either, and list item suppliers has neither 400 nor 409 (it is a read).

Response shape

Every endpoint except the three noted below returns 200 with a JSON array of PublicAreaItemModel — including endpoints that affect a single item, which return a one-element array. There is no unwrapped single-object response in this section. The array holds only the items the call actually affected, not the proposal. Ordering follows the proposal structure (area, then option, then display order), not the order of ids in your request, so match results back by id rather than by position. Field-by-field meanings are in reading proposal items. Delete items and refresh item costs return no body — either 200 or 204, so treat both as success. Re-fetch get proposal afterwards to read the resulting state. List item suppliers is the third exception: it only reads data, so it returns an array of PublicSupplierInfoModel rather than proposal items.

Which flags an endpoint accepts

SetDefault and UpdateAllInstances control two independent things, and support for them varies per endpoint:

SetDefault

Saves the new value outside this proposal, so items added later start with it. What it writes depends on the item type: a Part updates the company’s catalog data, while Labor, CustomItem, and Fee items update their library item. Client note is the exception — whatever the item type, it saves a default for you alone rather than for the company. Defaults to false.

UpdateAllInstances

Applies the new value to the proposal’s other items from the same source item that share its item type, in any area option — plus the same assigned supplier for cost. Defaults to false. Writes nothing outside the proposal.
SetDefault writes outside the proposal you are editing, and some of those writes travel further than the catalog: saving a cost or a supplier also updates the company’s other draft proposals and draft orders that carry the same part without a cost of their own. It also depends on access your account may not grant, and is silently skipped where that access is missing — the proposal item is still updated and a 200 is still returned. Read the value back if you need to be certain it took effect.
Each endpoint page spells out what its own SetDefault saves, since the behaviour differs by field and item type — a percentage-based price, for instance, is not saved on a Part at all.

Driving these endpoints from an integration

  • One field per call, no bulk endpoint. Repricing 50 items means 50 signed requests. Budget for it.
  • Writes are not idempotent. Retrying add items after a timeout adds a second copy rather than reconciling with the first. Confirm with a GET before retrying.
  • Serialize writes per proposal. Totals are recalculated on every write, so concurrent calls against the same proposal race each other. Parallelize across proposals instead.
  • Percentage-priced items move on their own. Every basis is recalculated each time the proposal is read, so editing one item changes the price of others: ProposalTotal, PartTotal, and LaborTotal change when anything in the proposal changes, AreaTotal, PartsInAreaTotal, and LaborInAreaTotal when anything in the same area option changes, and CostOfSellPrice when the item’s own sell price changes. Re-read the proposal after a batch rather than assembling state from individual responses.
  • No item-level webhooks. Only proposal-level events fire; poll get proposal and use its Last-Modified header to detect changes made in the Portal.io UI.
  • Not everything lands in the response. Attachment items added by add items, and the cross-proposal copies made by update image, are applied asynchronously. A GET a moment later is the only way to see them. Replace item is the exception: its attachments are added inline and do appear in the response.