# Creates several landed costs in one call, each as a draft.

`POST /inventory/landed-costs/bulk`

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

Creates several landed costs as drafts in one all-or-nothing call, the shape a period-end run takes, where a month of freight invoices is capitalized onto the receipts they belong to in one pass.

If any landed cost is rejected, none is created, and the error names the offending document's index. Every precondition of the single create applies to every entry.

Nothing is committed. Each landed cost comes back as a draft and has to be committed on its own. A commit revalues stock, and one that failed partway through a batch would leave some of the batch's stock restated and the rest not.

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

## 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. |

## Request body

Required, `application/json`: bulkCreateLandedCostsInput.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `landedCosts` | array of object | yes | The landed costs to create, each as a draft. All or nothing: if any is invalid, nothing is created. |
| `landedCosts[].entityId` | string | yes | The legal entity. It decides the functional currency that every amount on the landed cost is in, and it cannot be changed after create. |
| `landedCosts[].documentDate` | string (date) | no | The date of the landed cost. Use format YYYY-MM-DD. Defaults to today. |
| `landedCosts[].notes` | string | no | Free text on the landed cost. |
| `landedCosts[].receipts` | array of object | yes | The receipts whose stock the charges are capitalized onto. At least one, and every one must be committed. |
| `landedCosts[].receipts[].receiptId` | string | yes | A committed receipt. See id on GET inventory/receipts/:id. |
| `landedCosts[].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. |
| `landedCosts[].charges` | array of object | yes | The charges to capitalize, read from GET inventory/landed-costs/vendor-bill-lines. At least one, and every one from an approved vendor bill. |
| `landedCosts[].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. |
| `landedCosts[].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. |
| `landedCosts[].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. |
| `landedCosts[].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
{
  "landedCosts": [
    {
      "entityId": "7039b992-696a-40c7-a181-51759304ef83",
      "receipts": [
        {
          "receiptId": "b1a7c930-5e46-4f82-8d05-71c3e9a24f68"
        }
      ],
      "charges": [
        {
          "chargeId": "9c47e1b8-2a63-4d05-b7f9-04e28d5a1c37",
          "allocationMode": "Quantity",
          "amount": "240"
        }
      ]
    }
  ]
}
```

## Response

`200` Success

Under `data` (bulkCreateLandedCostsOutput):

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `created` | array of object | yes | The created landed costs, in input order, each a draft. Match them to inputs by index. |
| `created[].id` | string | yes | The unique identifier for the created landed cost. |
| `created[].documentNumber` | string | no | The landed cost number, for example 'LC-1007'. Assigned when the landed cost is created. |

## 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 |
| --- | --- |
| `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: 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
