1. Shipments
  2. Update Shipments

Shipments

Update Shipments

This endpoint enables you to update various aspects of an existing shipment, including tracking information, status updates, and associated metadata.

POST
`/v1/shipments/:shipment`

Request Parameters

Path Parameters

Parameter Type Description
shipment string The ID of the shipment to update.

Request Body

The request body can include any combination of the following fields:

js
        {
  // Basic Information
  disable_webhooks: boolean;
  type: "outbound" | "inbound",
  coordinates: [number, number],
  estimated_delivery_at: string | number | Date,
  pickup_at: string | number | Date,

  // Reference Numbers
  rma_number: string,
  invoice_number: string,
  order_number: string,
  purchase_order: string,
  reference_number: string,
  account_id: string,

  // Tracking Information
  tracking_number: string,
  provider_id: string,
  service_level_id: string,

  weight: number,
  dimensions: {
    length: number,
    width: number,
    height: number,
  },
  force_update: boolean,

  // Additional Information
  notes: string,
  tags: string[],
  metadata: object,

  // Tracking Updates
  tracking_update: {
    container_id: string,
    status: string,        // optional - omit to add a comment without changing status
    layout_id: string,
    location_id: string,
    contact_id: string,
    user_id: string,
    comment: string,
    address: string | object
    images: string[]
  },

  // Log Entry
  log: {
    message: string,
    images: string[],
    visibility: string,
  },

  // Customs (International)
  customs: {
    incoterm: string,
    signer: string,
    certify: boolean,
    contents_type: string,
    contents_explanation: string,
    eel_type: string,
    restriction_type: string,
    restriction_comments: string,
    non_delivery_option: string,
    items: [
      {
        description: string,
        quantity: number,
        value: number,
        weight: number,
        sku: string,
        code: string,         // optional: product code (uses sku if provided, otherwise defaults to "N/A")
        origin_country: string,
        hs_tariff_number: string,
        currency: string,
        mode: string,                // optional: customs mode (defaults to "test")
        manufacturer: string         // optional: manufacturer name (defaults to "N/A")
      }
    ]
  }
}

      

Request Examples

Comment-Only Update

You can add a comment to a shipment's tracking timeline without changing its status. Omit status from tracking_update and provide only comment. The API creates a new tracking timeline entry that copies the shipment's current status and attaches your comment.

js
        const body = {
  tracking_update: {
    comment: "Package held at front desk - recipient notified.",
  },
};

const response = await fetch(`https://api.packagex.io/v1/shipments/${shipment_id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const shipment = response.data;
// shipment.tracking_updates will contain a new entry that repeats the current status with your comment

      

Behavior notes:

  • The new tracking update entry inherits the shipment's most recent status and carries your comment.
  • The shipment.updated webhook fires for a comment-only update, just as it does for any other tracking update.
  • Customer-facing pickup and delivery notifications are NOT re-sent for a comment-only update (the repeated status does not re-trigger them).
  • A comment-only update is treated like any other tracking update: it bumps the shipment's updated_at timestamp and, when the status is pickup_available, counts toward the pickup-reminder limit the same way any repeated pickup_available entry does.
  • If the shipment has no prior tracking update with a status, a 400 error is returned with code invalid:comment.

Basic Information Update

js
        const body = {
  tracking_number: "1Z999999999999999",
  provider_id: "ups",
  estimated_delivery_at: "2025-02-22T15:00:00Z",
  pickup_at: "2025-02-22T15:00:00Z",
};

const response = await fetch(`https://api.packagex.io/v1/shipments/${shipment_id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const shipment = response.data;

      

Status Update Example

js
        const body = {
  tracking_update: {
    status: "in_transit",
    location_id: "loc_abc123",
    comment: "Package picked up from sender",
    images: ["https://example.com/image1.jpg"],
  },
};

const response = await fetch(`https://api.packagex.io/v1/shipments/${shipment_id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const shipment = response.data;

      

Customs Update Example (International)

js
        const body = {
  customs: {
    incoterm: "DAP",
    signer: "John Smith",
    certify: true,
    contents_type: "merchandise",
    eel_type: "NOEEI 30.37(a)",
    restriction_type: "none",
    non_delivery_option: "return",
    items: [
      {
        description: "Coffee Beans",
        quantity: 2,
        value: 1200,
        weight: 1.5,
        sku: "COF-001",
        origin_country: "US",
        hs_tariff_number: "090111",
        currency: "USD",
      },
    ],
  },
};

const response = await fetch(`https://api.packagex.io/v1/shipments/${shipment_id}`, {
  method: "POST",
  headers: {
    "PX-API-KEY": process.env.PX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
}).then((res) => res.json());

const shipment = response.data;

      

Update Restrictions

  1. Container-Related Restrictions

    • Cannot update status or location for shipments in containers. Either unlink the shipment or update the container directly.
  2. Purchased Shipment Restrictions

    • Cannot modify provider_id
    • Cannot update tracking_number
    • Cannot change service_level_id
    • Cannot modify dimensions or weight
  3. Status Update Restrictions

    • Must provide valid status transitions
    • Location and layout must be compatible
  4. International Field Restrictions

    • A shipment is treated as international when sender and recipient countries differ. International shipping must be enabled in your organization settings; otherwise a 400 error is returned when attempting to rate or update international customs.
    • For international shipments, customs fields must satisfy validation (e.g., contents_explanation required when contents_type is other, and restriction_comments required when restriction_type is not none).

Error Handling

Common error scenarios include:

  1. Invalid Updates
js
        {
  "error": {
    "code": "update.disabled",
    "errors": ["container_id"],
    "message": "Cannot update the status or location on a shipment in a container. Either unlink the shipment from the container or update the container directly.",
    "status": 400
  }
}

      
  1. Validation Errors
js
        {
  "error": {
    "code": "small_tracking_number",
    "errors": ["tracking_number"],
    "message": "Invalid tracking number: The tracking number must be at least 10 characters long. Please provide a complete and valid tracking number.",
    "status": 400
  }
}

      
  1. Comment-Only on a Shipment With No Prior Status
js
        {
  "error": {
    "code": "invalid:comment",
    "errors": ["comment"],
    "message": "Cannot add a comment without an existing tracking update",
    "status": 400
  }
}

      
  1. Permission Errors
js
        {
  "error": {
    "code": "invalid:contact",
    "errors": ["contact_id"],
    "message": "Contact does not belong to the organization",
    "status": 400
  }
}