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

# Import shipments (JSON)

> Push a batch of shipments into your shipment ledger.

<Note>
  **`POST`** `/v1/org/shipments/imports`
</Note>

Send up to **1000 shipments** in one call, in the
[published structure](/guides/shipment-structure).

The call returns as soon as the batch is accepted — it does not wait for the shipments to
be written. You get an `importId`; [poll it](/api-reference/get-import) for the outcome
and [read the rejected rows](/api-reference/get-import-errors) if any.

<Info>
  **Sending the same shipment twice is safe.** A `shipmentId` already in the ledger is
  updated, not duplicated — its goods lines are replaced by the ones you send. Retries,
  re-runs and corrected re-sends all do the right thing.
</Info>

## Authorization

<ParamField header="x-api-key" type="string" required>
  Your organisation API key (`dzk_live_…`).
</ParamField>

## Body

<ParamField body="shipments" type="Shipment[]" required>
  1–1000 shipments. See [Shipment structure](/guides/shipment-structure) for every field.
  Each shipment needs at least one entry in `items`, at most 500, and the batch as a
  whole may carry at most 10,000 goods lines — send bigger runs
  [as a file](/api-reference/import-shipments-file).
</ParamField>

<ParamField body="sourceDetails" type="string">
  Your own reference for this push — a batch id, run date or filename. It is echoed on
  the import and recorded against every shipment it creates, so a shipment can be traced
  back to the run that sent it.
</ParamField>

<Warning>
  Unknown fields are **rejected**, not ignored. If you send `weight` where the structure
  says `itemWeight`, you get a `400` naming the field rather than a shipment that
  silently lost its weight.
</Warning>

## Response

`202 Accepted` with the import's id and where to poll it.

| Field               | Description                                                        |
| ------------------- | ------------------------------------------------------------------ |
| `importId`          | Poll this for the outcome                                          |
| `status`            | `queued` on acceptance                                             |
| `source`            | `data` for this endpoint                                           |
| `shipmentsReceived` | Shipments accepted for processing (the import's `counts` are rows) |
| `statusUrl`         | Convenience path to the status endpoint                            |

## Errors

| Status | When                                                                                                                                                                                                                          |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Malformed body, more than 1000 shipments, more than 10,000 goods lines in total, more than 500 lines on one shipment, a shipment with no items, an unrecognised field, or a custom field your organisation has not configured |
| `400`  | Too many imports already queued — wait for the queue to drain                                                                                                                                                                 |
| `401`  | Missing or invalid API key                                                                                                                                                                                                    |
| `429`  | Rate limit exceeded — see [Rate limits](/guides/rate-limits)                                                                                                                                                                  |

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.dyspach.com/v1/org/shipments/imports \
    -H "x-api-key: $DYSPACH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "sourceDetails": "nightly-2026-08-14",
      "shipments": [
        {
          "shipmentId": "CONN-88213",
          "customerId": "ACME",
          "originPostCode": "3000",
          "originSuburb": "Melbourne",
          "originState": "VIC",
          "originCountryCode": "AU",
          "destinationPostCode": "2000",
          "destinationSuburb": "Sydney",
          "destinationState": "NSW",
          "destinationCountryCode": "AU",
          "quoteDate": "2026-08-14T02:15:00Z",
          "rateCardAlias": "EXPRESS",
          "totalCostReceived": 412.55,
          "customFields": { "Purchase Order": "PO-99187" },
          "items": [
            { "itemType": "Pallet", "itemQuantity": 2, "itemWeight": 240 },
            { "itemType": "Carton", "itemQuantity": 6, "itemWeight": 18 }
          ]
        }
      ]
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 202 theme={null}
  {
    "importId": "9f2b1c44-0d3e-4a71-9b52-0f4c1e77a8d1",
    "status": "queued",
    "source": "data",
    "shipmentsReceived": 1,
    "statusUrl": "/v1/org/shipments/imports/9f2b1c44-0d3e-4a71-9b52-0f4c1e77a8d1"
  }
  ```

  ```json 400 theme={null}
  {
    "statusCode": 400,
    "message": ["shipments.0.items should not be empty"],
    "error": "Bad Request"
  }
  ```
</ResponseExample>
