> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.milenow.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.milenow.com/_mcp/server.

# 2. Create FTLs

An FTL holds the cargo details: numbers, customer, consignee, containers, and the pickup and delivery days. You can create it in two ways:

* **On its own** with [`POST /api/v1/partners/shipments`](/ftl-trips/api-reference/ftl/create-ftl). Then put it on a trip in the [Mile web app](/ftl-trips/guides/build-trips), or [add it to a trip](/ftl-trips/guides/manage-stops#add-ftls-to-a-trip) with its `shipment_id`.
* **Inside a stop**, as a `shipment` object, when you [add stops](/ftl-trips/guides/manage-stops#add-ftls-to-a-trip) to a trip. It takes the same fields and is created together with the stop.

Both ways apply the same validation and the same [duplicate rule](/ftl-trips/business-rules#ftls).

## Request

```bash
curl -X POST "https://lastmile.milenow.com/index.php/api/v1/partners/shipments" \
  -H "Authorization: Bearer $MILE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "shipment_no": "SHP-1001",
    "bl_no": "BL-55001",
    "created_on": "2026-11-03",
    "expected_on": "2026-11-03",
    "shipping_line": "MAERSK",
    "payment_term": "Company Credit",
    "shipping_charges": 2200,
    "other_charges": 150,
    "pickup_from_port": true,
    "destination_port": "SA JED",
    "customer": {
      "name": "Coastal Trading LLC",
      "phone": "+966500000000",
      "address": "Al Sulaimaniyah Industrial, Jeddah"
    },
    "consignee": {
      "name": "Coastal Trading Factory",
      "address": "South Industrial Area, Jeddah"
    },
    "containers": [
      {
        "category": "Containers",
        "product": "40ft GP Container - Full",
        "container_no": "MSKU4821736",
        "seal_no": "SL-77120",
        "size": "40ft",
        "quantity": 1,
        "weight": 26000
      }
    ]
  }'
```

## Required fields

| Field                               | Rule                                                                |
| ----------------------------------- | ------------------------------------------------------------------- |
| `shipment_no`, `bl_no`              | Your FTL and bill of lading numbers                                 |
| `created_on`                        | **Pickup day**, `Y-m-d`                                             |
| `expected_on`                       | **Delivery day**, `Y-m-d`. Same day as `created_on` or later        |
| `shipping_line`, `payment_term`     | Name or `*_id` from [FTL options](/ftl-trips/guides/reference-data) |
| `shipping_charges`, `other_charges` | Numbers, 0 or more                                                  |
| `customer`                          | The shipper. `id`, or `name`, `phone` and `address` for a new one   |
| `consignee`                         | The receiver. `id`, or `name` and `address` for a new one           |
| `containers`                        | At least one. See below                                             |
| `vendor`                            | Only when options returns `vendor_required: true`                   |

Optional fields include `vessel`, `voyage_no`, `tracking_no`, `notes`, `origination_port`, `stayed_ports`, `shipping_method`, `country` and `documents`. The [reference](/ftl-trips/api-reference/ftl/create-ftl) lists them all.

### Customer and consignee

Send `id` to reuse a party: the `consigner.id` or `consignee.id` from an earlier FTL. For a new party, send `name` and `address`. A new customer also needs `phone`. Send the phone in the correct format for its country, with the country code. Mile matches it against existing customers in your account. Mile locates the address with Google Maps. Read [customers and consignees](/ftl-trips/business-rules#customers-and-consignees) for how phones and coordinates are matched.

### Containers

| Field                 | Rule                                                                                 |
| --------------------- | ------------------------------------------------------------------------------------ |
| `category`, `product` | From `categories[].products` in options. Name or `*_id`                              |
| `container_no`        | Unique within the FTL. Alias `container_id`                                          |
| `seal_no`             | Alias `seal_number`                                                                  |
| `size`                | `20ft`, `40ft`, `40ft HC` or `45ft HC`. `40HC`, `40 hq` and `20GP` are also accepted |
| `quantity`            | 1 to 10                                                                              |
| `weight`              | 0 or more                                                                            |

### Pickup at a port

By default the container is picked up at the customer's address. To pick it up at a port, send `pickup_from_port: true` and the port as `destination_port` (name, code or UN/LOCODE) or `destination_port_id`. Find ports with [port search](/ftl-trips/guides/reference-data#ports).

### Documents

Optional. Each document has a `type` from options, a `file_name` ending in `.png`, `.jpg`, `.jpeg` or `.pdf`, and `file_base64` of 300 KB or less.

## Response

```json
{
  "status": 200,
  "msg": "Shipment created",
  "msgs": [],
  "data": {
    "id": 301,
    "shipment_no": "SHP-1001",
    "tracking_no": "TRK48210",
    "bl_no": "BL-55001",
    "status": { "id": 10, "name": "Awaiting Approval" },
    "created_on": "2026-11-03 00:00:00",
    "expected_on": "2026-11-03 00:00:00",
    "consigner": { "id": 7001021045, "name": "Coastal Trading LLC", "address": "Al Sulaimaniyah Industrial, Jeddah", "latitude": 21.452, "longitude": 39.257 },
    "consignee": { "id": 7001021046, "name": "Coastal Trading Factory", "address": "South Industrial Area, Jeddah", "latitude": 21.305, "longitude": 39.235 },
    "pickup_from_port": true,
    "destination_port": { "id": 61021, "name": "Jiddah", "unlocode": "SA JED" },
    "containers": [
      { "id": 376, "container_no": "MSKU4821736", "seal_no": "SL-77120", "size": "40ft", "weight": "26000", "quantity": 1 }
    ]
  }
}
```

The response is shortened here. Keep these fields:

* `id`: send it as `shipment_id` in a trip stop.
* `consigner.id` and `consignee.id`: send them as `customer.id` and `consignee.id` in later FTLs.

## Errors

#### 412: several problems at once

Every problem is in `msgs`. Fix them all and send again.

```json
{
  "status": 412,
  "msg": "3 problems found, listed in msgs. Fix all of them and send again.",
  "msgs": [
    "expected_on (2026-11-01) is before created_on (2026-11-03). created_on is the pickup day and expected_on the delivery day",
    "containers[0].product \"20ft\" matches more than one product, send the exact name: 20ft GP Container - Full, 20ft Container - Empty",
    "containers[0].weight is required (0 or more)"
  ],
  "data": []
}
```

#### 409: the FTL already exists

The same `shipment_no`, `bl_no` and container number are already in your account. Use the `shipment_id` from the message instead of creating it again.

```json
{
  "status": 409,
  "msg": "Shipment SHP-1001 with BL BL-55001 and container MSKU4821736 already exists as shipment_id 301. Use shipment_id 301 instead of creating it again.",
  "msgs": ["Shipment SHP-1001 with BL BL-55001 and container MSKU4821736 already exists as shipment_id 301. Use shipment_id 301 instead of creating it again."],
  "data": []
}
```

Next: [build trips](/ftl-trips/guides/build-trips).