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

# Shipping Solutions

> Learn how to fulfill orders with tracking information using the Trackstar API

Shipping is a critical component of order fulfillment. This guide shows you how to ship orders and attach shipping labels using the Trackstar API.

## Overview

The shipping workflow typically involves:

1. Creating shipments with tracking information
2. Attaching shipping labels and documentation
3. Providing tracking details to customers

## Shipping an Order

Use the [Create Shipment endpoint](/api-reference/wms-api/orders/create-shipment) to mark an order as fulfilled and provide shipment and tracking information.

<Tip>For a full list of fields that need to be passed in, see the [Programmatic Writes guide](/how-to-guides/programmatic-writes).</Tip>

### Create an Order Shipment

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://production.trackstarhq.com/wms/orders/order_abc123/shipments \
    -H "Content-Type: application/json" \
    -H "x-trackstar-api-key: YOUR_API_KEY" \
    -H "x-trackstar-access-token: YOUR_ACCESS_TOKEN" \
    -d '{
      "shipped_date": "2024-01-15T14:30:00Z",
      "carrier_id": "fedex",
      "shipping_method_id": "fedex_ground",
      "warehouse_id": "warehouse_main",
      "packages": [
        {
          "package_id": "pkg_001",
          "tracking_number": "1Z999AA1234567890"
        }
      ]
    }'
  ```

  ```python Python theme={null}
  import requests
  import json

  url = "https://production.trackstarhq.com/wms/orders/order_abc123/shipments"

  headers = {
      "Content-Type": "application/json",
      "x-trackstar-api-key": "YOUR_API_KEY",
      "x-trackstar-access-token": "YOUR_ACCESS_TOKEN"
  }

  payload = {
      "shipped_date": "2024-01-15T14:30:00Z",
      "carrier_id": "fedex",
      "shipping_method_id": "fedex_ground",
      "warehouse_id": "warehouse_main",
      "packages": [
          {
              "package_id": "pkg_001",
              "tracking_number": "1Z999AA1234567890"
          }
      ]
  }

  response = requests.post(url, headers=headers, json=payload)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const url = "https://production.trackstarhq.com/wms/orders/order_abc123/shipments";

  const payload = {
    shipped_date: "2024-01-15T14:30:00Z",
    carrier_id: "fedex",
    shipping_method_id: "fedex_ground",
    warehouse_id: "warehouse_main",
    packages: [
      {
        package_id: "pkg_001",
        tracking_number: "1Z999AA1234567890"
      }
    ]
  };

  fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-trackstar-api-key": "YOUR_API_KEY",
      "x-trackstar-access-token": "YOUR_ACCESS_TOKEN"
    },
    body: JSON.stringify(payload)
  })
  .then(response => response.json())
  .then(data => console.log(data));
  ```

  ```php PHP theme={null}
  <?php
  $url = "https://production.trackstarhq.com/wms/orders/order_abc123/shipments";

  $payload = [
      "shipped_date" => "2024-01-15T14:30:00Z",
      "carrier_id" => "fedex",
      "shipping_method_id" => "fedex_ground",
      "warehouse_id" => "warehouse_main",
      "packages" => [
          [
              "package_id" => "pkg_001",
              "tracking_number" => "1Z999AA1234567890"
          ]
      ]
  ];

  $options = [
      "http" => [
          "header" => "Content-Type: application/json\r\n" .
                     "x-trackstar-api-key: YOUR_API_KEY\r\n" .
                     "x-trackstar-access-token: YOUR_ACCESS_TOKEN\r\n",
          "method" => "POST",
          "content" => json_encode($payload)
      ]
  ];

  $context = stream_context_create($options);
  $response = file_get_contents($url, false, $context);
  echo $response;
  ?>
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
  )

  type ShipmentRequest struct {
      ShippedDate       string    `json:"shipped_date"`
      CarrierID         string    `json:"carrier_id"`
      ShippingMethodID  string    `json:"shipping_method_id"`
      WarehouseID       string    `json:"warehouse_id"`
      Packages          []Package `json:"packages"`
  }

  type Package struct {
      PackageID       string `json:"package_id"`
      TrackingNumber  string `json:"tracking_number"`
  }

  func main() {
      url := "https://production.trackstarhq.com/wms/orders/order_abc123/shipments"

      shipmentReq := ShipmentRequest{
          ShippedDate:      "2024-01-15T14:30:00Z",
          CarrierID:        "fedex",
          ShippingMethodID: "fedex_ground",
          WarehouseID:      "warehouse_main",
          Packages: []Package{
              {
                  PackageID:      "pkg_001",
                  TrackingNumber: "1Z999AA1234567890",
              },
          },
      }

      jsonData, _ := json.Marshal(shipmentReq)

      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
      req.Header.Set("Content-Type", "application/json")
      req.Header.Set("x-trackstar-api-key", "YOUR_API_KEY")
      req.Header.Set("x-trackstar-access-token", "YOUR_ACCESS_TOKEN")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      fmt.Println("Response Status:", resp.Status)
  }
  ```

  ```java Java theme={null}
  import java.io.IOException;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.net.URI;

  public class TrackstarShipmentExample {
      public static void main(String[] args) throws IOException, InterruptedException {
          String url = "https://production.trackstarhq.com/wms/orders/order_abc123/shipments";

          String jsonPayload = """
          {
              "shipped_date": "2024-01-15T14:30:00Z",
              "carrier_id": "fedex",
              "shipping_method_id": "fedex_ground",
              "warehouse_id": "warehouse_main",
              "packages": [
                  {
                      "package_id": "pkg_001",
                      "tracking_number": "1Z999AA1234567890"
                  }
              ]
          }
          """;

          HttpRequest request = HttpRequest.newBuilder()
                  .uri(URI.create(url))
                  .header("Content-Type", "application/json")
                  .header("x-trackstar-api-key", "YOUR_API_KEY")
                  .header("x-trackstar-access-token", "YOUR_ACCESS_TOKEN")
                  .POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
                  .build();

          HttpClient client = HttpClient.newHttpClient();
          HttpResponse<String> response = client.send(request,
                  HttpResponse.BodyHandlers.ofString());

          System.out.println("Status Code: " + response.statusCode());
          System.out.println("Response: " + response.body());
      }
  }
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'

  url = URI('https://production.trackstarhq.com/wms/orders/order_abc123/shipments')

  payload = {
    shipped_date: "2024-01-15T14:30:00Z",
    carrier_id: "fedex",
    shipping_method_id: "fedex_ground",
    warehouse_id: "warehouse_main",
    packages: [
      {
        package_id: "pkg_001",
        tracking_number: "1Z999AA1234567890"
      }
    ]
  }

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(url)
  request['Content-Type'] = 'application/json'
  request['x-trackstar-api-key'] = 'YOUR_API_KEY'
  request['x-trackstar-access-token'] = 'YOUR_ACCESS_TOKEN'
  request.body = payload.to_json

  response = http.request(request)
  puts "Status: #{response.code}"
  puts "Response: #{response.body}"
  ```
</CodeGroup>

### Sample Response

```json theme={null}
{
  "data": {
    "id": "order_abc123",
    "warehouse_customer_id": "customer_12345",
    "warehouse_id": "warehouse_main",
    "created_date": "2024-01-15T10:00:00Z",
    "updated_date": "2024-01-15T14:35:00Z",
    "reference_id": "order_2024_001",
    "order_number": "ORD-001",
    "status": "fulfilled",
    "raw_status": "shipped",
    "channel": "shopify",
    "channel_object": {
      "channel_id": "Online Store",
      "channel_name": "shopify"
    },
    "type": "d2c",
    "trading_partner": "Direct",
    "shipping_method": "fedex_ground",
    "service_level": "Standard",
    "shipping_method_id": "fedex_ground",
    "shipping_method_name": "FedEx Ground",
    "carrier_id": "fedex",
    "carrier_name": "FedEx",
    "scac": "FEDX",
    "is_third_party_freight": false,
    "third_party_freight_account_number": null,
    "first_party_freight_account_number": null,
    "invoice_currency_code": "USD",
    "total_price": 79.98,
    "total_tax": 6.40,
    "total_discount": 3.00,
    "total_shipping": 8.95,
    "ship_to_address": {
      "full_name": "John Doe",
      "company": null,
      "address1": "123 Main St",
      "address2": "Apt 4B",
      "address3": null,
      "city": "Anytown",
      "state": "NY",
      "postal_code": "12345",
      "country": "US",
      "phone_number": "123-456-7890",
      "email_address": "john@example.com"
    },
    "line_items": [
      {
        "product_id": "prod_widget_001",
        "sku": "WIDGET-001",
        "quantity": 2,
        "unit_price": 29.99,
        "is_picked": true,
        "discount_amount": 1.5
      },
      {
        "product_id": "prod_gadget_002",
        "sku": "GADGET-002",
        "quantity": 1,
        "unit_price": 19.99,
        "is_picked": true,
        "discount_amount": 1.5
      }
    ],
    "tags": ["rush_order"],
    "required_ship_date": "2024-01-18T00:00:00Z",
    "saturday_delivery": false,
    "signature_required": false,
    "international_duty_paid_by": null,
    "shipments": [
      {
        "shipment_id": "shipment_abc123",
        "warehouse_id": "warehouse_main",
        "shipped_date": "2024-01-15T14:30:00Z",
        "raw_status": "shipped",
        "status": "shipped",
        "shipping_method": "fedex_ground",
        "line_items": [
          {
            "inventory_item_id": "inv_widget001_main",
            "sku": "WIDGET-001",
            "quantity": 2,
            "parent_product_id": null
          },
          {
            "inventory_item_id": "inv_gadget002_main",
            "sku": "GADGET-002",
            "quantity": 1,
            "parent_product_id": null
          }
        ],
        "ship_to_address": {
          "full_name": "John Doe",
          "company": null,
          "address1": "123 Main St",
          "address2": "Apt 4B",
          "address3": null,
          "city": "Anytown",
          "state": "NY",
          "postal_code": "12345",
          "country": "US"
        },
        "ship_from_address": {
          "address1": "456 Warehouse Blvd",
          "address2": null,
          "address3": null,
          "city": "Distribution City",
          "state": "NJ",
          "postal_code": "07001",
          "country": "US"
        },
        "packages": [
          {
            "package_id": "pkg_001",
            "package_name": "12x9x4",
            "tracking_number": "1Z999AA1234567890",
            "tracking_url": "https://www.fedex.com/apps/fedextrack/?tracknumbers=1Z999AA1234567890",
            "shipping_method": "fedex_ground",
            "carrier": "FedEx",
            "shipping_method_id": "fedex_ground",
            "shipping_method_name": "FedEx Ground",
            "carrier_id": "fedex",
            "carrier_name": "FedEx",
            "scac": "FEDX",
            "shipping_cost": 8.95,
            "measurements": {
              "length": 12.0,
              "width": 9.0,
              "height": 4.0,
              "unit": "in",
              "weight": 2.5,
              "weight_unit": "lb"
            },
            "line_items": [
              {
                "inventory_item_id": "inv_widget001_main",
                "sku": "WIDGET-001",
                "quantity": 2,
                "lot_id": null,
                "expiration_date": null,
                "parent_product_id": null
              },
              {
                "inventory_item_id": "inv_gadget002_main",
                "sku": "GADGET-002",
                "quantity": 1,
                "lot_id": null,
                "expiration_date": null,
                "parent_product_id": null
              }
            ]
          }
        ]
      }
    ],
    "external_system_url": "https://wms.example.com/orders/order_abc123",
    "trackstar_tags": ["high-priority", {"customer_type": "premium"}],
    "additional_fields": {
      "order_notes": "Handle with care",
      "customer_tier": "gold"
    }
  }
}
```

### Multi-Package Shipment

For orders that ship in multiple packages, you can include each under `packages` in your request body:

```json theme={null}
{
  "packages": [
    {
      "package_id": "pkg_001",
      "tracking_number": "1Z999AA1234567890"
    },
    {
      "package_id": "pkg_002",
      "tracking_number": "1Z999AA1234567891"
    }
  ]
}
```

## Adding Shipping Labels

Use the [Attach File endpoint](/api-reference/wms-api/orders/attach-file) to attach shipping labels and other documentation to orders.

### Attach File

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://production.trackstarhq.com/wms/orders/order_abc123/file \
    -H "x-trackstar-api-key: YOUR_API_KEY" \
    -H "x-trackstar-access-token: YOUR_ACCESS_TOKEN" \
    -F "file=@/path/to/shipping_label.pdf" \
    -F "file_name=shipping_label.pdf" \
    -F "file_url=https://labels.example.com/shipping_label_123.pdf"
  ```

  ```python Python theme={null}
  import requests

  url = "https://production.trackstarhq.com/wms/orders/order_abc123/file"

  headers = {
      "x-trackstar-api-key": "YOUR_API_KEY",
      "x-trackstar-access-token": "YOUR_ACCESS_TOKEN"
  }

  # Upload file from local path
  with open('/path/to/shipping_label.pdf', 'rb') as f:
      files = {
          'file': ('shipping_label.pdf', f, 'application/pdf')
      }
      data = {
          'file_name': 'shipping_label.pdf',
          'file_url': 'https://labels.example.com/shipping_label_123.pdf'
      }

      response = requests.post(url, headers=headers, files=files, data=data)
      print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const url = "https://production.trackstarhq.com/wms/orders/order_abc123/file";

  // Using FormData for file upload
  const formData = new FormData();
  formData.append('file_name', 'shipping_label.pdf');
  formData.append('file_url', 'https://labels.example.com/shipping_label_123.pdf');

  // Assuming you have a file input element with id 'fileInput'
  const fileInput = document.getElementById('fileInput');
  if (fileInput.files.length > 0) {
    formData.append('file', fileInput.files[0]);
  }

  fetch(url, {
    method: "POST",
    headers: {
      "x-trackstar-api-key": "YOUR_API_KEY",
      "x-trackstar-access-token": "YOUR_ACCESS_TOKEN"
      // Don't set Content-Type for FormData - let browser set it
    },
    body: formData
  })
  .then(response => response.json())
  .then(data => console.log(data));
  ```

  ```php PHP theme={null}
  <?php
  $url = "https://production.trackstarhq.com/wms/orders/order_abc123/file";

  $headers = [
      "x-trackstar-api-key: YOUR_API_KEY",
      "x-trackstar-access-token: YOUR_ACCESS_TOKEN"
  ];

  $postFields = [
      'file' => new CURLFile('/path/to/shipping_label.pdf', 'application/pdf', 'shipping_label.pdf'),
      'file_name' => 'shipping_label.pdf',
      'file_url' => 'https://labels.example.com/shipping_label_123.pdf'
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  curl_close($ch);

  echo $response;
  ?>
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "fmt"
      "io"
      "mime/multipart"
      "net/http"
      "os"
  )

  func main() {
      url := "https://production.trackstarhq.com/wms/orders/order_abc123/file"

      // Create multipart form
      var b bytes.Buffer
      writer := multipart.NewWriter(&b)

      // Add form fields
      writer.WriteField("file_name", "shipping_label.pdf")
      writer.WriteField("file_url", "https://labels.example.com/shipping_label_123.pdf")

      // Add file
      file, err := os.Open("/path/to/shipping_label.pdf")
      if err != nil {
          panic(err)
      }
      defer file.Close()

      part, err := writer.CreateFormFile("file", "shipping_label.pdf")
      if err != nil {
          panic(err)
      }

      io.Copy(part, file)
      writer.Close()

      // Create request
      req, _ := http.NewRequest("POST", url, &b)
      req.Header.Set("Content-Type", writer.FormDataContentType())
      req.Header.Set("x-trackstar-api-key", "YOUR_API_KEY")
      req.Header.Set("x-trackstar-access-token", "YOUR_ACCESS_TOKEN")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      fmt.Println("Response Status:", resp.Status)
  }
  ```

  ```java Java theme={null}
  import java.io.File;
  import java.io.IOException;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;
  import java.net.URI;
  import java.nio.file.Files;

  public class TrackstarFileUploadExample {
      public static void main(String[] args) throws IOException, InterruptedException {
          String url = "https://production.trackstarhq.com/wms/orders/order_abc123/file";
          String boundary = "----TrackstarFormBoundary" + System.currentTimeMillis();

          // Read file content
          File file = new File("/path/to/shipping_label.pdf");
          byte[] fileContent = Files.readAllBytes(file.toPath());

          // Build multipart form data
          StringBuilder formData = new StringBuilder();
          formData.append("--").append(boundary).append("\r\n");
          formData.append("Content-Disposition: form-data; name=\"file_name\"\r\n\r\n");
          formData.append("shipping_label.pdf\r\n");
          formData.append("--").append(boundary).append("\r\n");
          formData.append("Content-Disposition: form-data; name=\"file_url\"\r\n\r\n");
          formData.append("https://labels.example.com/shipping_label_123.pdf\r\n");
          formData.append("--").append(boundary).append("\r\n");
          formData.append("Content-Disposition: form-data; name=\"file\"; filename=\"shipping_label.pdf\"\r\n");
          formData.append("Content-Type: application/pdf\r\n\r\n");

          String formDataString = formData.toString();
          String endBoundary = "\r\n--" + boundary + "--\r\n";

          // Combine form data, file content, and end boundary
          byte[] requestBody = new byte[formDataString.getBytes().length + fileContent.length + endBoundary.getBytes().length];
          System.arraycopy(formDataString.getBytes(), 0, requestBody, 0, formDataString.getBytes().length);
          System.arraycopy(fileContent, 0, requestBody, formDataString.getBytes().length, fileContent.length);
          System.arraycopy(endBoundary.getBytes(), 0, requestBody, formDataString.getBytes().length + fileContent.length, endBoundary.getBytes().length);

          HttpRequest request = HttpRequest.newBuilder()
                  .uri(URI.create(url))
                  .header("Content-Type", "multipart/form-data; boundary=" + boundary)
                  .header("x-trackstar-api-key", "YOUR_API_KEY")
                  .header("x-trackstar-access-token", "YOUR_ACCESS_TOKEN")
                  .POST(HttpRequest.BodyPublishers.ofByteArray(requestBody))
                  .build();

          HttpClient client = HttpClient.newHttpClient();
          HttpResponse<String> response = client.send(request,
                  HttpResponse.BodyHandlers.ofString());

          System.out.println("Status Code: " + response.statusCode());
          System.out.println("Response: " + response.body());
      }
  }
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'mime/types'

  url = URI('https://production.trackstarhq.com/wms/orders/order_abc123/file')

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true

  request = Net::HTTP::Post.new(url)
  request['x-trackstar-api-key'] = 'YOUR_API_KEY'
  request['x-trackstar-access-token'] = 'YOUR_ACCESS_TOKEN'

  # Create multipart form data
  boundary = "----RubyFormBoundary#{rand(1000000)}"
  request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"

  file_path = '/path/to/shipping_label.pdf'
  file_content = File.read(file_path)

  form_data = []
  form_data << "--#{boundary}\r\n"
  form_data << "Content-Disposition: form-data; name=\"file_name\"\r\n\r\n"
  form_data << "shipping_label.pdf\r\n"
  form_data << "--#{boundary}\r\n"
  form_data << "Content-Disposition: form-data; name=\"file_url\"\r\n\r\n"
  form_data << "https://labels.example.com/shipping_label_123.pdf\r\n"
  form_data << "--#{boundary}\r\n"
  form_data << "Content-Disposition: form-data; name=\"file\"; filename=\"shipping_label.pdf\"\r\n"
  form_data << "Content-Type: application/pdf\r\n\r\n"
  form_data << file_content
  form_data << "\r\n--#{boundary}--\r\n"

  request.body = form_data.join

  response = http.request(request)
  puts "Status: #{response.code}"
  puts "Response: #{response.body}"
  ```
</CodeGroup>

**Sample Response:**

```json theme={null}
{
  "data": "",
  "id": "id",
  "unused_fields": [
    ""
  ]
}
```

## Order Status Updates

Creating a shipment automatically updates the order status to "fulfilled" in Trackstar. This status change will trigger [webhooks](/how-to-guides/webhooks) to keep your systems synchronized.
