# Update Landed Cost

`PATCH /inventory/landed-costs/{id}`

Group: Inventory › Landed Costs · Operation ID: `updateLandedCost`

Updates the landed cost with the given identifier. Only the fields in the request body change. Only a draft can be changed.

Changes a draft landed cost. A committed one cannot be changed, because it has already revalued the stock.

receipts and charges are replaced wholesale, not merged. There are no createLines, updateLines or deleteLines arrays, because neither is a line with an identity of its own. A receipt selection points at another document and a charge points at another document's vendor bill line, so there is nothing stable to address a partial update to. Send the whole set you want, or omit the field to leave it alone.

The allocation is recomputed whenever either set changes, so reading the landed cost back after a change shows the new unit costs.

The entity cannot be changed. Every amount on the landed cost is in its functional currency, so changing the entity would reinterpret every charge at once. Delete the landed cost and create another instead.

[Open in the interactive reference](https://docs.api.lensing.ai/?op=updateLandedCost)

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `Api-Version` | header | `"v1"` | yes | The API version this request targets, named by its public identifier. Required on every request; omitting it, or naming a version this company does not have, is answered with 400. This document describes version `v1`. |
| `Idempotency-Key` | header | string | no | An opaque caller-chosen string (1-255 characters) that makes this request safe to retry. Repeating the same key with an identical request body replays the original response instead of re-executing - but only once that original request succeeded; a failed attempt re-executes on retry. Repeating the key with a different body is answered with 422. A key still in flight is answered with 409 - as is a key whose original request was interrupted before it finished, for a few minutes afterwards, until that attempt is presumed dead. A completed response stays replayable for 24 hours. The key is scoped to the caller, not to the action: reusing it for a different action is answered with 409 or 422 rather than treated independently. On read actions this header is ignored. On write actions that cannot offer the guarantee it is answered with `400 IDEMPOTENCY_NOT_SUPPORTED` rather than silently ignored. |
| `id` | path | string | yes | The unique identifier for the landed cost to update. |

## Request body

Required, `application/json`: updateLandedCostInput.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `documentDate` | string (date) | no | The date of the landed cost. Use format YYYY-MM-DD. |
| `notes` | string | no | Free text on the landed cost. |
| `receipts` | array of object | no | The receipts whose stock the charges are capitalized onto. At least one, and every one must be committed. Omit to leave the current set. To change it, send the whole set, because it replaces rather than merges. |
| `receipts[].receiptId` | string | yes | A committed receipt. See id on GET inventory/receipts/:id. |
| `receipts[].selectedLineIds` | array of string | no | The receipt lines to allocate onto, by their id under lines on GET inventory/receipts/:id. Omit to use all of them, which is the usual case. Every id must belong to this receipt, and an id from another one fails with REFERENCE_NOT_FOUND. |
| `charges` | array of object | no | The charges to capitalize, read from GET inventory/landed-costs/vendor-bill-lines. At least one, and every one from an approved vendor bill. Omit to leave the current set. To change it, send the whole set, because it replaces rather than merges. |
| `charges[].chargeId` | string | yes | The vendor bill line the charge comes from, by its id on GET inventory/landed-costs/vendor-bill-lines. The vendor bill is derived from it, so there is no second id to send. |
| `charges[].allocationMode` | string | no | How to spread this charge over the receipt lines. Accepted values: 'Equal', 'Quantity', 'LineTotal', 'Weight', 'Volume'. Pass back what GET inventory/landed-costs/vendor-bill-lines returned. Omitting it does not fall through to the landed cost item configuration. It falls through to the item's own default, which may be a different mode. |
| `charges[].amount` | string (decimal) | yes | How much of the charge to capitalize, in the entity's functional currency. Send functionalLineTotal from GET inventory/landed-costs/vendor-bill-lines, less anything already allocated, not the bill's own lineTotal. Nothing converts this amount. |
| `charges[].isSelected` | boolean | no | Whether to include the charge. Defaults to true. A charge set to false is kept on the landed cost and allocated nothing. |

Example:

```json
{
  "documentDate": "2026-01-15",
  "notes": "<notes>",
  "receipts": [
    {
      "receiptId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "selectedLineIds": [
        "<selectedLineIds>"
      ]
    }
  ],
  "charges": [
    {
      "chargeId": "9c47e1b8-2a63-4d05-b7f9-04e28d5a1c37",
      "allocationMode": "LineTotal",
      "amount": "300"
    }
  ]
}
```

## Response

`200` Success

Under `data` (updateLandedCostOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | The unique identifier for the landed cost. |
| `allocationLineCount` | number | no | The number of allocation lines after the change, one per selected receipt line. |

## Response headers

- `Idempotency-Replayed` — Present and `true` only when this response replays a previously stored one for the same Idempotency-Key, rather than reflecting a live execution. Absent on a live response - never sent as `false`.

## Errors

| Code | Status |
| --- | --- |
| `NOT_FOUND` | 400 |
| `WRONG_STATUS` | 400 |
| `REFERENCE_NOT_FOUND` | 400 |
| `NO_RECEIPTS` | 400 |
| `NO_CHARGES` | 400 |
| `RECEIPT_NOT_COMMITTED` | 400 |
| `VENDOR_BILL_NOT_APPROVED` | 400 |
| `INVALID_AMOUNT` | 400 |
| `UNKNOWN_ALLOCATION_MODE` | 400 |
| `IDEMPOTENCY_KEY_CONFLICT` | 409 |
| `IDEMPOTENCY_PAYLOAD_MISMATCH` | 422 |

## Statuses

- `400` — Invalid request or business failure. Codes: NOT_FOUND, WRONG_STATUS, REFERENCE_NOT_FOUND, NO_RECEIPTS, NO_CHARGES, RECEIPT_NOT_COMMITTED, VENDOR_BILL_NOT_APPROVED, INVALID_AMOUNT, UNKNOWN_ALLOCATION_MODE
- `401` — Missing or invalid access token
- `403` — Not authorized
- `404` — Not found
- `409` — The Idempotency-Key is still being processed by another request.
- `422` — The Idempotency-Key was already used with a different request payload.
- `429` — Too many requests
- `500` — Internal server error
